/******************************************************************************* ** ** Function nfa_p2p_update_active_listen ** ** Description Remove active listen mode temporarily or restore it ** ** ** Returns None ** *******************************************************************************/ static void nfa_p2p_update_active_listen (void) { tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0; BT_HDR *p_msg; P2P_TRACE_DEBUG1 ("nfa_p2p_update_active_listen (): listen_tech_mask_to_restore:0x%x", nfa_p2p_cb.listen_tech_mask_to_restore); /* if active listen mode was removed temporarily */ if (nfa_p2p_cb.listen_tech_mask_to_restore) { /* restore listen technologies */ nfa_p2p_cb.listen_tech_mask = nfa_p2p_cb.listen_tech_mask_to_restore; nfa_p2p_cb.listen_tech_mask_to_restore = 0; nfa_sys_stop_timer (&nfa_p2p_cb.active_listen_restore_timer); } else { /* start timer in case of no passive activation */ nfa_p2p_cb.active_listen_restore_timer.p_cback = (TIMER_CBACK *)nfa_p2p_update_active_listen_timeout_cback; nfa_sys_start_timer (&nfa_p2p_cb.active_listen_restore_timer, 0, NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT); /* save listen techonologies */ nfa_p2p_cb.listen_tech_mask_to_restore = nfa_p2p_cb.listen_tech_mask; /* remove active listen mode */ nfa_p2p_cb.listen_tech_mask &= ~( NFA_TECHNOLOGY_MASK_A_ACTIVE|NFA_TECHNOLOGY_MASK_F_ACTIVE); } if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) { nfa_dm_delete_rf_discover (nfa_p2p_cb.dm_disc_handle); nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID; } /* collect listen technologies with NFC-DEP protocol */ if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A) p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F) p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP; /* Configure listen technologies and protocols and register callback to NFA DM discovery */ nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover (p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback); /* restart RF discovery to update RF technologies */ if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof(BT_HDR))) != NULL) { p_msg->event = NFA_P2P_INT_RESTART_RF_DISC_EVT; nfa_sys_sendmsg (p_msg); } }
/******************************************************************************* ** ** Function nfa_ee_proc_nfcc_power_mode ** ** Description Restore NFA EE sub-module ** ** Returns None ** *******************************************************************************/ void nfa_ee_proc_nfcc_power_mode (UINT8 nfcc_power_mode) { UINT32 xx; tNFA_EE_ECB *p_cb; BOOLEAN proc_complete = TRUE; NFA_TRACE_DEBUG1 ("nfa_ee_proc_nfcc_power_mode (): nfcc_power_mode=%d", nfcc_power_mode); /* if NFCC power state is change to full power */ if (nfcc_power_mode == NFA_DM_PWR_MODE_FULL) { if (nfa_ee_max_ee_cfg) { p_cb = nfa_ee_cb.ecb; for (xx = 0; xx < NFA_EE_MAX_EE_SUPPORTED; xx++, p_cb++) { p_cb->ee_old_status = 0; if (xx >= nfa_ee_cb.cur_ee) p_cb->nfcee_id = NFA_EE_INVALID; if ((p_cb->nfcee_id != NFA_EE_INVALID) && (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) && (p_cb->ee_status != NFA_EE_STATUS_REMOVED)) { proc_complete = FALSE; /* NFA_EE_STATUS_RESTORING bit makes sure the ee_status restore to ee_old_status * NFA_EE_STATUS_RESTORING bit is cleared in ee_status at NFCEE_DISCOVER NTF. * NFA_EE_STATUS_RESTORING bit is cleared in ee_old_status at restoring the activate/inactive status after NFCEE_DISCOVER NTF */ p_cb->ee_status |= NFA_EE_STATUS_RESTORING; p_cb->ee_old_status = p_cb->ee_status; /* NFA_EE_FLAGS_RESTORE bit makes sure the routing/nci logical connection is restore to prior to entering low power mode */ p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_RESTORE; } } nfa_ee_cb.em_state = NFA_EE_EM_STATE_RESTORING; nfa_ee_cb.num_ee_expecting = 0; if (nfa_sys_is_register (NFA_ID_HCI)) { nfa_ee_cb.ee_flags |= NFA_EE_FLAG_WAIT_HCI; nfa_ee_cb.ee_flags |= NFA_EE_FLAG_NOTIFY_HCI; } NFC_NfceeDiscover (TRUE); nfa_sys_start_timer (&nfa_ee_cb.discv_timer, NFA_EE_DISCV_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL); } } else { nfa_sys_stop_timer (&nfa_ee_cb.timer); nfa_sys_stop_timer (&nfa_ee_cb.discv_timer); nfa_ee_cb.num_ee_expecting = 0; } if (proc_complete) nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_EE); }
/******************************************************************************* ** ** Function nfa_ee_sys_enable ** ** Description Enable NFA EE ** ** Returns None ** *******************************************************************************/ void nfa_ee_sys_enable (void) { if (nfa_ee_max_ee_cfg) { /* collect NFCEE information */ NFC_NfceeDiscover (TRUE); nfa_sys_start_timer (&nfa_ee_cb.discv_timer, NFA_EE_DISCV_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL); } else { nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE; nfa_sys_cback_notify_enable_complete (NFA_ID_EE); } }
/******************************************************************************* ** ** Function nfa_ee_sys_enable ** ** Description Enable NFA EE ** ** Returns None ** *******************************************************************************/ void nfa_ee_sys_enable (void) { /* collect NFCEE information */ NFC_NfceeDiscover (TRUE); nfa_sys_start_timer (&nfa_ee_cb.discv_timer, NFA_EE_DISCV_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL); }
/******************************************************************************* ** ** Function nfa_p2p_llcp_link_cback ** ** Description Processing event from LLCP link management callback ** ** ** Returns None ** *******************************************************************************/ void nfa_p2p_llcp_link_cback (UINT8 event, UINT8 reason) { tNFA_LLCP_ACTIVATED llcp_activated; tNFA_LLCP_DEACTIVATED llcp_deactivated; P2P_TRACE_DEBUG2 ("nfa_p2p_llcp_link_cback () event:0x%x, reason:0x%x", event, reason); if (event == LLCP_LINK_ACTIVATION_COMPLETE_EVT) { LLCP_GetLinkMIU (&nfa_p2p_cb.local_link_miu, &nfa_p2p_cb.remote_link_miu); nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_ACTIVATED; if (nfa_p2p_cb.is_initiator) { /* notify NFA DM to send Activate Event to applicaiton with status */ nfa_dm_notify_activation_status (NFA_STATUS_OK, NULL); } llcp_activated.is_initiator = nfa_p2p_cb.is_initiator; llcp_activated.local_link_miu = nfa_p2p_cb.local_link_miu; llcp_activated.remote_link_miu = nfa_p2p_cb.remote_link_miu; llcp_activated.remote_lsc = LLCP_GetRemoteLSC (); llcp_activated.remote_wks = LLCP_GetRemoteWKS (); nfa_dm_act_conn_cback_notify (NFA_LLCP_ACTIVATED_EVT, (tNFA_CONN_EVT_DATA *) &llcp_activated); } else if (event == LLCP_LINK_ACTIVATION_FAILED_EVT) { nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE; if (nfa_p2p_cb.is_initiator) { /* notify NFA DM to send Activate Event to applicaiton with status */ nfa_dm_notify_activation_status (NFA_STATUS_FAILED, NULL); } nfa_dm_rf_deactivate (NFA_DEACTIVATE_TYPE_DISCOVERY); } else if (event == LLCP_LINK_FIRST_PACKET_RECEIVED_EVT) { nfa_dm_act_conn_cback_notify (NFA_LLCP_FIRST_PACKET_RECEIVED_EVT, NULL); } else /* LLCP_LINK_DEACTIVATED_EVT */ { nfa_p2p_cb.llcp_state = NFA_P2P_LLCP_STATE_IDLE; /* if got RF link loss without any rx LLC PDU */ if (reason == LLCP_LINK_RF_LINK_LOSS_NO_RX_LLC) { /* if it was active listen mode */ if ( (nfa_p2p_cb.is_active_mode) &&(!nfa_p2p_cb.is_initiator)) { /* if it didn't retry without active listen mode and passive mode is available */ if ( (nfa_p2p_cb.listen_tech_mask_to_restore == 0x00) &&(nfa_p2p_cb.listen_tech_mask & ( NFA_TECHNOLOGY_MASK_A |NFA_TECHNOLOGY_MASK_F))) { P2P_TRACE_DEBUG0 ("Retry without active listen mode"); /* retry without active listen mode */ nfa_p2p_update_active_listen (); } } else if (nfa_p2p_cb.listen_tech_mask_to_restore) { nfa_sys_start_timer (&nfa_p2p_cb.active_listen_restore_timer, 0, NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT); } reason = LLCP_LINK_RF_LINK_LOSS_ERR; } else { if (nfa_p2p_cb.listen_tech_mask_to_restore) { /* restore active listen mode */ nfa_p2p_update_active_listen (); } } llcp_deactivated.reason = reason; nfa_dm_act_conn_cback_notify (NFA_LLCP_DEACTIVATED_EVT, (tNFA_CONN_EVT_DATA *)&llcp_deactivated); if (reason != LLCP_LINK_RF_LINK_LOSS_ERR) /* if NFC link is still up */ { if (nfa_p2p_cb.is_initiator) { nfa_dm_rf_deactivate (NFA_DEACTIVATE_TYPE_DISCOVERY); } else if ((nfa_p2p_cb.is_active_mode) && (reason == LLCP_LINK_TIMEOUT)) { /* ** target needs to trun off RF in case of receiving invalid frame from initiator */ P2P_TRACE_DEBUG0 ("Got LLCP_LINK_TIMEOUT in active mode on target"); nfa_dm_rf_deactivate (NFA_DEACTIVATE_TYPE_DISCOVERY); } } } }
/******************************************************************************* ** ** Function nfa_hciu_send_msg ** ** Description This function will fragment the given packet, if necessary ** and send it on the given pipe. ** ** Returns status ** *******************************************************************************/ tNFA_STATUS nfa_hciu_send_msg (UINT8 pipe_id, UINT8 type, UINT8 instruction, UINT16 msg_len, UINT8 *p_msg) { BT_HDR *p_buf; UINT8 *p_data; BOOLEAN first_pkt = TRUE; UINT16 data_len; tNFA_STATUS status = NFA_STATUS_OK; UINT16 max_seg_hcp_pkt_size = nfa_hci_cb.buff_size; #if (BT_TRACE_VERBOSE == TRUE) char buff[100]; NFA_TRACE_DEBUG3 ("nfa_hciu_send_msg pipe_id:%d %s len:%d", pipe_id, nfa_hciu_get_type_inst_names (pipe_id, type, instruction, buff), msg_len); #else NFA_TRACE_DEBUG4 ("nfa_hciu_send_msg pipe_id:%d Type: %u Inst: %u len: %d", pipe_id, type, instruction, msg_len); #endif if (instruction == NFA_HCI_ANY_GET_PARAMETER) nfa_hci_cb.param_in_use = *p_msg; while ((first_pkt == TRUE) || (msg_len != 0)) { if ((p_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL) { p_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; /* First packet has a 2-byte header, subsequent fragments have a 1-byte header */ data_len = first_pkt ? (max_seg_hcp_pkt_size - 2) : (max_seg_hcp_pkt_size - 1); p_data = (UINT8 *) (p_buf + 1) + p_buf->offset; /* Last or only segment has "no fragmentation" bit set */ if (msg_len > data_len) { *p_data++ = (NFA_HCI_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F); } else { data_len = msg_len; *p_data++ = (NFA_HCI_NO_MESSAGE_FRAGMENTATION << 7) | (pipe_id & 0x7F); } p_buf->len = 1; /* Message header only goes in the first segment */ if (first_pkt) { first_pkt = FALSE; *p_data++ = (type << 6) | instruction; p_buf->len++; } if (data_len != 0) { memcpy (p_data, p_msg, data_len); p_buf->len += data_len; msg_len -= data_len; if (msg_len > 0) p_msg += data_len; } #if (BT_TRACE_PROTOCOL == TRUE) DispHcp (((UINT8 *) (p_buf + 1) + p_buf->offset), p_buf->len, FALSE, (BOOLEAN) ((p_buf->len - data_len) == 2)); #endif if (HCI_LOOPBACK_DEBUG) handle_debug_loopback (p_buf, pipe_id, type, instruction); else status = NFC_SendData (nfa_hci_cb.conn_id, p_buf); } else { NFA_TRACE_ERROR0 ("nfa_hciu_send_data_packet no buffers"); status = NFA_STATUS_NO_BUFFERS; break; } } /* Start timer if response to wait for a particular time for the response */ if (type == NFA_HCI_COMMAND_TYPE) { nfa_hci_cb.cmd_sent = instruction; if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_RSP; nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hcp_response_timeout); } return status; }
/******************************************************************************* ** ** Function nfa_p2p_update_active_listen ** ** Description Remove active listen mode temporarily or restore it ** ** ** Returns None ** *******************************************************************************/ static void nfa_p2p_update_active_listen (void) { tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0; BT_HDR *p_msg; P2P_TRACE_DEBUG1 ("nfa_p2p_update_active_listen (): listen_tech_mask_to_restore:0x%x", nfa_p2p_cb.listen_tech_mask_to_restore); /* if active listen mode was removed temporarily */ if (nfa_p2p_cb.listen_tech_mask_to_restore) { /* restore listen technologies */ nfa_p2p_cb.listen_tech_mask = nfa_p2p_cb.listen_tech_mask_to_restore; nfa_p2p_cb.listen_tech_mask_to_restore = 0; nfa_sys_stop_timer (&nfa_p2p_cb.active_listen_restore_timer); } else { /* start timer in case of no passive activation */ nfa_p2p_cb.active_listen_restore_timer.p_cback = (TIMER_CBACK *)nfa_p2p_update_active_listen_timeout_cback; nfa_sys_start_timer (&nfa_p2p_cb.active_listen_restore_timer, 0, NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT); /* save listen techonologies */ nfa_p2p_cb.listen_tech_mask_to_restore = nfa_p2p_cb.listen_tech_mask; /* remove active listen mode */ nfa_p2p_cb.listen_tech_mask &= ~( NFA_TECHNOLOGY_MASK_A_ACTIVE|NFA_TECHNOLOGY_MASK_F_ACTIVE); } if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) { nfa_dm_delete_rf_discover (nfa_p2p_cb.dm_disc_handle); nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID; } /* collect listen technologies with NFC-DEP protocol */ if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A) p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F) p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP; #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) /*For P2P mode(Default DTA mode) open Raw channel to bypass LLCP layer. For LLCP DTA mode activate LLCP * Bypassing LLCP is handled in nfa_dm_poll_disc_cback*/ if ((appl_dta_mode_flag == 1) && (nfa_dm_cb.eDtaMode == NFA_DTA_DEFAULT_MODE)) { /* Configure listen technologies and protocols and register callback to NFA DM discovery */ P2P_TRACE_DEBUG0 ("DTA mode1:Registering nfa_dm_poll_disc_cback to avoid LLCP in P2P "); nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover (p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_dm_poll_disc_cback_dta_wrapper); } else #endif { /* Configure listen technologies and protocols and register callback to NFA DM discovery */ nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover (p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback); } /* restart RF discovery to update RF technologies */ if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof(BT_HDR))) != NULL) { p_msg->event = NFA_P2P_INT_RESTART_RF_DISC_EVT; nfa_sys_sendmsg (p_msg); } }