| /****************************************************************************** |
| * |
| * Copyright (C) 2010-2014 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| |
| /****************************************************************************** |
| * |
| * This file contains function of the NFC unit to receive/process NCI/VS |
| * commands/responses. |
| * |
| ******************************************************************************/ |
| #include <string.h> |
| #include "nfc_hal_int.h" |
| #include "nfc_hal_post_reset.h" |
| #include "userial.h" |
| #include "nci_defs.h" |
| |
| |
| /***************************************************************************** |
| ** Constants and types |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| ** Local function prototypes |
| *****************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_assemble_nci_msg |
| ** |
| ** Description This function is called to reassemble the received NCI |
| ** response/notification packet, if required. |
| ** (The data packets are posted to NFC task for reassembly) |
| ** |
| ** Returns void. |
| ** |
| *******************************************************************************/ |
| void nfc_hal_nci_assemble_nci_msg (void) |
| { |
| NFC_HDR *p_msg = nfc_hal_cb.ncit_cb.p_rcv_msg; |
| UINT8 u8; |
| UINT8 *p, *pp; |
| UINT8 hdr[2]; |
| UINT8 *ps, *pd; |
| UINT16 size, needed; |
| BOOLEAN disp_again = FALSE; |
| |
| if ((p_msg == NULL) || (p_msg->len < NCI_MSG_HDR_SIZE)) |
| return; |
| |
| #ifdef DISP_NCI |
| DISP_NCI ((UINT8 *) (p_msg + 1) + p_msg->offset, (UINT16) (p_msg->len), TRUE); |
| #endif |
| |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| u8 = *p++; |
| /* remove the PBF bit for potential reassembly later */ |
| hdr[0] = u8 & ~NCI_PBF_MASK; |
| if ((u8 & NCI_MT_MASK) == NCI_MT_DATA) |
| { |
| /* clear the RFU in octet1 */ |
| *(p) = 0; |
| /* data packet reassembly is performed in NFC task */ |
| return; |
| } |
| else |
| { |
| *(p) &= NCI_OID_MASK; |
| } |
| |
| hdr[1] = *p; |
| pp = hdr; |
| /* save octet0 and octet1 of an NCI header in layer_specific for the received packet */ |
| STREAM_TO_UINT16 (p_msg->layer_specific, pp); |
| |
| if (nfc_hal_cb.ncit_cb.p_frag_msg) |
| { |
| if (nfc_hal_cb.ncit_cb.p_frag_msg->layer_specific != p_msg->layer_specific) |
| { |
| /* check if these fragments are of the same NCI message */ |
| HAL_TRACE_ERROR2 ("nfc_hal_nci_assemble_nci_msg() - different messages 0x%x, 0x%x!!", nfc_hal_cb.ncit_cb.p_frag_msg->layer_specific, p_msg->layer_specific); |
| nfc_hal_cb.ncit_cb.nci_ras |= NFC_HAL_NCI_RAS_ERROR; |
| } |
| else if (nfc_hal_cb.ncit_cb.nci_ras == 0) |
| { |
| disp_again = TRUE; |
| /* if not previous reassembly error, append the new fragment */ |
| p_msg->offset += NCI_MSG_HDR_SIZE; |
| p_msg->len -= NCI_MSG_HDR_SIZE; |
| size = GKI_get_buf_size (nfc_hal_cb.ncit_cb.p_frag_msg); |
| needed = (NFC_HDR_SIZE + nfc_hal_cb.ncit_cb.p_frag_msg->len + nfc_hal_cb.ncit_cb.p_frag_msg->offset + p_msg->len); |
| if (size >= needed) |
| { |
| /* the buffer for reassembly is big enough to append the new fragment */ |
| ps = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| pd = (UINT8 *) (nfc_hal_cb.ncit_cb.p_frag_msg + 1) + nfc_hal_cb.ncit_cb.p_frag_msg->offset + nfc_hal_cb.ncit_cb.p_frag_msg->len; |
| memcpy (pd, ps, p_msg->len); |
| nfc_hal_cb.ncit_cb.p_frag_msg->len += p_msg->len; |
| /* adjust the NCI packet length */ |
| pd = (UINT8 *) (nfc_hal_cb.ncit_cb.p_frag_msg + 1) + nfc_hal_cb.ncit_cb.p_frag_msg->offset + 2; |
| *pd = (UINT8) (nfc_hal_cb.ncit_cb.p_frag_msg->len - NCI_MSG_HDR_SIZE); |
| } |
| else |
| { |
| nfc_hal_cb.ncit_cb.nci_ras |= NFC_HAL_NCI_RAS_TOO_BIG; |
| HAL_TRACE_ERROR2 ("nfc_hal_nci_assemble_nci_msg() buffer overrun (%d + %d)!!", nfc_hal_cb.ncit_cb.p_frag_msg->len, p_msg->len); |
| } |
| } |
| /* we are done with this new fragment, free it */ |
| GKI_freebuf (p_msg); |
| } |
| else |
| { |
| nfc_hal_cb.ncit_cb.p_frag_msg = p_msg; |
| } |
| |
| |
| if ((u8 & NCI_PBF_MASK) == NCI_PBF_NO_OR_LAST) |
| { |
| /* last fragment */ |
| p_msg = nfc_hal_cb.ncit_cb.p_frag_msg; |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| *p = u8; /* this should make the PBF flag as Last Fragment */ |
| nfc_hal_cb.ncit_cb.p_frag_msg = NULL; |
| |
| p_msg->layer_specific = nfc_hal_cb.ncit_cb.nci_ras; |
| /* still report the data packet, if the incoming packet is too big */ |
| if (nfc_hal_cb.ncit_cb.nci_ras & NFC_HAL_NCI_RAS_ERROR) |
| { |
| /* NFCC reported NCI fragments for different NCI messages and this is the last fragment - drop it */ |
| HAL_TRACE_ERROR0 ("nfc_hal_nci_assemble_nci_msg() clearing NCI_RAS_ERROR"); |
| GKI_freebuf (p_msg); |
| p_msg = NULL; |
| } |
| #ifdef DISP_NCI |
| if ((nfc_hal_cb.ncit_cb.nci_ras == 0) && (disp_again)) |
| { |
| DISP_NCI ((UINT8 *) (p_msg + 1) + p_msg->offset, (UINT16) (p_msg->len), TRUE); |
| } |
| #endif |
| /* clear the error flags, so the next NCI packet is clean */ |
| nfc_hal_cb.ncit_cb.nci_ras = 0; |
| } |
| else |
| { |
| /* still reassembling */ |
| p_msg = NULL; |
| } |
| |
| nfc_hal_cb.ncit_cb.p_rcv_msg = p_msg; |
| } |
| |
| /***************************************************************************** |
| ** |
| ** Function nfc_hal_nci_receive_nci_msg |
| ** |
| ** Description |
| ** Handle incoming data (NCI events) from the serial port. |
| ** |
| ** If there is data waiting from the serial port, this funciton reads the |
| ** data and parses it. Once an entire NCI message has been read, it sends |
| ** the message the the NFC_TASK for processing |
| ** |
| *****************************************************************************/ |
| static BOOLEAN nfc_hal_nci_receive_nci_msg (tNFC_HAL_NCIT_CB *p_cb, UINT8 byte) |
| { |
| UINT16 len; |
| BOOLEAN msg_received = FALSE; |
| |
| switch (p_cb->rcv_state) |
| { |
| case NFC_HAL_RCV_NCI_MSG_ST: |
| |
| /* Initialize rx parameters */ |
| p_cb->rcv_state = NFC_HAL_RCV_NCI_HDR_ST; |
| p_cb->rcv_len = NCI_MSG_HDR_SIZE; |
| |
| /* Start of new message. Allocate a buffer for message */ |
| if ((p_cb->p_rcv_msg = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) |
| { |
| /* Initialize NFC_HDR */ |
| p_cb->p_rcv_msg->len = 0; |
| p_cb->p_rcv_msg->event = 0; |
| p_cb->p_rcv_msg->offset = 0; |
| |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| } |
| else |
| { |
| HAL_TRACE_ERROR0 ("Unable to allocate buffer for incoming NCI message."); |
| } |
| p_cb->rcv_len--; |
| break; |
| |
| case NFC_HAL_RCV_NCI_HDR_ST: |
| |
| if (p_cb->p_rcv_msg) |
| { |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| } |
| |
| p_cb->rcv_len--; |
| |
| /* Check if we read in entire NFC message header yet */ |
| if (p_cb->rcv_len == 0) |
| { |
| p_cb->rcv_len = byte; |
| |
| /* If non-zero payload, then go to receive-data state */ |
| if (byte > 0) |
| { |
| p_cb->rcv_state = NFC_HAL_RCV_NCI_PAYLOAD_ST; |
| } |
| else |
| { |
| msg_received = TRUE; |
| p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; |
| } |
| } |
| break; |
| |
| case NFC_HAL_RCV_NCI_PAYLOAD_ST: |
| |
| p_cb->rcv_len--; |
| if (p_cb->p_rcv_msg) |
| { |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| |
| if (p_cb->rcv_len > 0) |
| { |
| /* Read in the rest of the message */ |
| len = USERIAL_Read (USERIAL_NFC_PORT, ((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len), p_cb->rcv_len); |
| p_cb->p_rcv_msg->len += len; |
| p_cb->rcv_len -= len; |
| } |
| } |
| |
| /* Check if we read in entire message yet */ |
| if (p_cb->rcv_len == 0) |
| { |
| msg_received = TRUE; |
| p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; |
| } |
| break; |
| } |
| |
| return (msg_received); |
| } |
| |
| /***************************************************************************** |
| ** |
| ** Function nfc_hal_nci_receive_bt_msg |
| ** |
| ** Description |
| ** Handle incoming BRCM specific data from the serial port. |
| ** |
| ** If there is data waiting from the serial port, this funciton reads the |
| ** data and parses it. Once an entire message has been read, it returns |
| ** TRUE. |
| ** |
| *****************************************************************************/ |
| static BOOLEAN nfc_hal_nci_receive_bt_msg (tNFC_HAL_NCIT_CB *p_cb, UINT8 byte) |
| { |
| UINT16 len; |
| BOOLEAN msg_received = FALSE; |
| |
| switch (p_cb->rcv_state) |
| { |
| case NFC_HAL_RCV_BT_MSG_ST: |
| |
| /* Initialize rx parameters */ |
| p_cb->rcv_state = NFC_HAL_RCV_BT_HDR_ST; |
| p_cb->rcv_len = HCIE_PREAMBLE_SIZE; |
| |
| if ((p_cb->p_rcv_msg = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL) |
| { |
| /* Initialize NFC_HDR */ |
| p_cb->p_rcv_msg->len = 0; |
| p_cb->p_rcv_msg->event = 0; |
| p_cb->p_rcv_msg->offset = 0; |
| |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| } |
| else |
| { |
| HAL_TRACE_ERROR0 ("[nfc] Unable to allocate buffer for incoming NCI message."); |
| } |
| p_cb->rcv_len--; |
| break; |
| |
| case NFC_HAL_RCV_BT_HDR_ST: |
| if (p_cb->p_rcv_msg) |
| { |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| } |
| p_cb->rcv_len--; |
| |
| /* Check if we received entire preamble yet */ |
| if (p_cb->rcv_len == 0) |
| { |
| /* Received entire preamble. Length is in the last byte(s) of the preamble */ |
| p_cb->rcv_len = byte; |
| |
| /* Verify that buffer is big enough to fit message */ |
| if ((p_cb->p_rcv_msg) && |
| ((sizeof (NFC_HDR) + HCIE_PREAMBLE_SIZE + byte) > GKI_get_buf_size (p_cb->p_rcv_msg)) ) |
| { |
| /* Message cannot fit into buffer */ |
| GKI_freebuf (p_cb->p_rcv_msg); |
| p_cb->p_rcv_msg = NULL; |
| |
| HAL_TRACE_ERROR0 ("Invalid length for incoming BT HCI message."); |
| } |
| |
| /* Message length is valid */ |
| if (byte) |
| { |
| /* Read rest of message */ |
| p_cb->rcv_state = NFC_HAL_RCV_BT_PAYLOAD_ST; |
| } |
| else |
| { |
| /* Message has no additional parameters. (Entire message has been received) */ |
| msg_received = TRUE; |
| p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; /* Next, wait for packet type of next message */ |
| } |
| } |
| break; |
| |
| case NFC_HAL_RCV_BT_PAYLOAD_ST: |
| p_cb->rcv_len--; |
| if (p_cb->p_rcv_msg) |
| { |
| *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; |
| |
| if (p_cb->rcv_len > 0) |
| { |
| /* Read in the rest of the message */ |
| len = USERIAL_Read (USERIAL_NFC_PORT, ((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len), p_cb->rcv_len); |
| p_cb->p_rcv_msg->len += len; |
| p_cb->rcv_len -= len; |
| } |
| } |
| |
| /* Check if we read in entire message yet */ |
| if (p_cb->rcv_len == 0) |
| { |
| msg_received = TRUE; |
| p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; /* Next, wait for packet type of next message */ |
| } |
| break; |
| } |
| |
| /* If we received entire message */ |
| #if (NFC_HAL_TRACE_PROTOCOL == TRUE) |
| if (msg_received && p_cb->p_rcv_msg) |
| { |
| /* Display protocol trace message */ |
| DispHciEvt (p_cb->p_rcv_msg); |
| } |
| #endif |
| |
| return (msg_received); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_proc_rx_bt_msg |
| ** |
| ** Description Received BT message from NFCC |
| ** |
| ** Notify command complete if initializing NFCC |
| ** Forward BT message to NFC task |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| static void nfc_hal_nci_proc_rx_bt_msg (void) |
| { |
| UINT8 *p; |
| NFC_HDR *p_msg; |
| UINT16 opcode, old_opcode; |
| tNFC_HAL_BTVSC_CPLT vcs_cplt_params; |
| tNFC_HAL_BTVSC_CPLT_CBACK *p_cback = NULL; |
| |
| /* if complete BT message is received successfully */ |
| if (nfc_hal_cb.ncit_cb.p_rcv_msg) |
| { |
| p_msg = nfc_hal_cb.ncit_cb.p_rcv_msg; |
| HAL_TRACE_DEBUG1 ("nfc_hal_nci_proc_rx_bt_msg (): GOT an BT msgs init_sta:%d", nfc_hal_cb.dev_cb.initializing_state); |
| HAL_TRACE_DEBUG2 ("event: 0x%x, wait_rsp:0x%x", p_msg->event, nfc_hal_cb.ncit_cb.nci_wait_rsp); |
| /* increase the cmd window here */ |
| if (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_PROP) |
| { |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| if (*p == HCI_COMMAND_COMPLETE_EVT) |
| { |
| p += 3; /* code, len, cmd window */ |
| STREAM_TO_UINT16 (opcode, p); |
| p = nfc_hal_cb.ncit_cb.last_hdr; |
| STREAM_TO_UINT16 (old_opcode, p); |
| if (opcode == old_opcode) |
| { |
| nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; |
| p_cback = (tNFC_HAL_BTVSC_CPLT_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback; |
| nfc_hal_cb.ncit_cb.p_vsc_cback = NULL; |
| nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); |
| } |
| } |
| } |
| |
| /* if initializing BRCM NFCC */ |
| if ((nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) || |
| (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_BUILD_INFO) || |
| (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)) |
| { |
| /* this is command complete event for baud rate update or download patch */ |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| |
| p += 1; /* skip opcode */ |
| STREAM_TO_UINT8 (vcs_cplt_params.param_len, p); |
| |
| p += 1; /* skip num command packets */ |
| STREAM_TO_UINT16 (vcs_cplt_params.opcode, p); |
| |
| vcs_cplt_params.param_len -= 3; |
| vcs_cplt_params.p_param_buf = p; |
| |
| if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE) |
| { |
| NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_OK); |
| } |
| if (p_cback) |
| { |
| nfc_hal_cb.ncit_cb.p_vsc_cback = NULL; |
| (*p_cback) (&vcs_cplt_params); |
| } |
| |
| /* do not BT send message to NFC task */ |
| GKI_freebuf (p_msg); |
| } |
| else |
| { |
| /* do not BT send message to NFC task */ |
| GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); |
| } |
| nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; |
| } |
| } |
| |
| /***************************************************************************** |
| ** |
| ** Function nfc_hal_nci_receive_msg |
| ** |
| ** Description |
| ** Handle incoming data (NCI events) from the serial port. |
| ** |
| ** If there is data waiting from the serial port, this funciton reads the |
| ** data and parses it. Once an entire NCI message has been read, it sends |
| ** the message the the NFC_TASK for processing |
| ** |
| *****************************************************************************/ |
| BOOLEAN nfc_hal_nci_receive_msg (UINT8 byte) |
| { |
| tNFC_HAL_NCIT_CB *p_cb = &(nfc_hal_cb.ncit_cb); |
| BOOLEAN msg_received = FALSE; |
| |
| if (p_cb->rcv_state == NFC_HAL_RCV_IDLE_ST) |
| { |
| /* if this is NCI message */ |
| if (byte == HCIT_TYPE_NFC) |
| { |
| p_cb->rcv_state = NFC_HAL_RCV_NCI_MSG_ST; |
| } |
| /* if this is BT message */ |
| else if (byte == HCIT_TYPE_EVENT) |
| { |
| p_cb->rcv_state = NFC_HAL_RCV_BT_MSG_ST; |
| } |
| else |
| { |
| HAL_TRACE_ERROR1 ("Unknown packet type drop this byte 0x%x", byte); |
| } |
| } |
| else if (p_cb->rcv_state <= NFC_HAL_RCV_NCI_PAYLOAD_ST) |
| { |
| msg_received = nfc_hal_nci_receive_nci_msg (p_cb, byte); |
| } |
| else |
| { |
| if (nfc_hal_nci_receive_bt_msg (p_cb, byte)) |
| { |
| /* received BT message */ |
| nfc_hal_nci_proc_rx_bt_msg (); |
| } |
| } |
| |
| return (msg_received); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_preproc_rx_nci_msg |
| ** |
| ** Description NFCC sends NCI message to DH while initializing NFCC |
| ** processing low power mode |
| ** |
| ** Returns TRUE, if NFC task need to receive NCI message |
| ** |
| *******************************************************************************/ |
| BOOLEAN nfc_hal_nci_preproc_rx_nci_msg (NFC_HDR *p_msg) |
| { |
| UINT8 *p, *pp; |
| UINT8 mt, pbf, gid, op_code; |
| UINT8 payload_len; |
| #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) |
| UINT8 cid; |
| UINT16 data_len; |
| #endif |
| |
| HAL_TRACE_DEBUG0 ("nfc_hal_nci_preproc_rx_nci_msg()"); |
| |
| if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF) |
| { |
| /* if turning off BRCM NFCC */ |
| nfc_hal_dm_proc_msg_during_exit (p_msg); |
| /* do not send message to NFC task while shutting down */ |
| return (FALSE); |
| } |
| |
| /* if initializing BRCM NFCC */ |
| if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE) |
| { |
| nfc_hal_dm_proc_msg_during_init (p_msg); |
| /* do not send message to NFC task while initializing NFCC */ |
| return (FALSE); |
| } |
| else |
| { |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| pp = p; |
| NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); |
| NCI_MSG_PRS_HDR1 (p, op_code); |
| payload_len = *p++; |
| |
| #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) |
| if (mt == NCI_MT_DATA) |
| { |
| if (nfc_hal_cb.hci_cb.hcp_conn_id) |
| { |
| NCI_DATA_PRS_HDR(pp, pbf, cid, data_len); |
| if (cid == nfc_hal_cb.hci_cb.hcp_conn_id) |
| { |
| nfc_hal_hci_handle_hcp_pkt_from_hc (pp); |
| } |
| |
| } |
| } |
| |
| if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */ |
| { |
| if (mt == NCI_MT_NTF) |
| { |
| if (op_code == NCI_MSG_HCI_NETWK) |
| { |
| nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset); |
| } |
| } |
| } |
| else |
| #endif |
| if (gid == NCI_GID_RF_MANAGE) |
| { |
| if (mt == NCI_MT_NTF) |
| { |
| if (op_code == NCI_MSG_RF_INTF_ACTIVATED) |
| { |
| if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5)) |
| { |
| /* API used wants to limit the RF data credits */ |
| p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */ |
| if (*p > nfc_hal_cb.max_rf_credits) |
| { |
| HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits); |
| *p = nfc_hal_cb.max_rf_credits; |
| } |
| } |
| } |
| } |
| } |
| #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) |
| else if (gid == NCI_GID_CORE) |
| { |
| if (mt == NCI_MT_RSP) |
| { |
| if (op_code == NCI_MSG_CORE_CONN_CREATE) |
| { |
| if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp) |
| { |
| p++; /* skip status byte */ |
| nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; |
| p++; /* skip buff size */ |
| p++; /* num of buffers */ |
| nfc_hal_cb.hci_cb.hcp_conn_id = *p; |
| } |
| } |
| } |
| } |
| #endif |
| } |
| |
| if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) |
| { |
| if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) |
| { |
| /* extend idle timer */ |
| nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT); |
| } |
| } |
| |
| return (TRUE); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_add_nfc_pkt_type |
| ** |
| ** Description Add packet type (HCIT_TYPE_NFC) |
| ** |
| ** Returns TRUE, if NFCC can receive NCI message |
| ** |
| *******************************************************************************/ |
| void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg) |
| { |
| UINT8 *p; |
| UINT8 hcit; |
| |
| /* add packet type in front of NCI header */ |
| if (p_msg->offset > 0) |
| { |
| p_msg->offset--; |
| p_msg->len++; |
| |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| *p = HCIT_TYPE_NFC; |
| } |
| else |
| { |
| HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type"); |
| hcit = HCIT_TYPE_NFC; |
| USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1); |
| } |
| } |
| |
| #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) |
| /******************************************************************************* |
| ** |
| ** Function nci_brcm_check_cmd_create_hcp_connection |
| ** |
| ** Description Check if this is command to create HCP connection |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg) |
| { |
| UINT8 *p; |
| UINT8 mt, pbf, gid, op_code; |
| |
| nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; |
| |
| p = (UINT8 *) (p_msg + 1) + p_msg->offset; |
| |
| if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) |
| { |
| NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); |
| NCI_MSG_PRS_HDR1 (p, op_code); |
| |
| if (gid == NCI_GID_CORE) |
| { |
| if (mt == NCI_MT_CMD) |
| { |
| if (op_code == NCI_MSG_CORE_CONN_CREATE) |
| { |
| if ( ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++) |
| &&(NCI_DEST_TYPE_NFCEE == *p++) |
| &&(1 == *p++) |
| &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++) |
| &&(2 == *p++) ) |
| { |
| p++; |
| if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p) |
| { |
| nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE; |
| return; |
| } |
| } |
| |
| } |
| } |
| } |
| } |
| } |
| |
| #endif |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_send_cmd |
| ** |
| ** Description Send NCI command to the transport |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void nfc_hal_nci_send_cmd (NFC_HDR *p_buf) |
| { |
| BOOLEAN continue_to_process = TRUE; |
| UINT8 *ps, *pd; |
| UINT16 max_len; |
| UINT16 buf_len, offset; |
| UINT8 *p; |
| UINT8 hdr[NCI_MSG_HDR_SIZE]; |
| UINT8 nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size; |
| UINT8 delta = 0; |
| |
| #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) |
| if ( (nfc_hal_cb.hci_cb.hcp_conn_id == 0) |
| &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE) ) |
| nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf); |
| #endif |
| |
| /* check low power mode state */ |
| continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT); |
| |
| if (!continue_to_process) |
| { |
| /* save the command to be sent until NFCC is free. */ |
| nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf; |
| return; |
| } |
| |
| max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE; |
| buf_len = p_buf->len; |
| offset = p_buf->offset; |
| #ifdef DISP_NCI |
| if (buf_len > max_len) |
| { |
| /* this command needs to be fragmented. display the complete packet first */ |
| DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE); |
| } |
| #endif |
| ps = (UINT8 *) (p_buf + 1) + p_buf->offset; |
| memcpy (hdr, ps, NCI_MSG_HDR_SIZE); |
| while (buf_len > max_len) |
| { |
| HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len); |
| /* the NCI command is bigger than the NFCC Max Control Packet Payload Length |
| * fragment the command */ |
| |
| p_buf->len = max_len; |
| ps = (UINT8 *) (p_buf + 1) + p_buf->offset; |
| /* mark the control packet as fragmented */ |
| *ps |= NCI_PBF_ST_CONT; |
| /* adjust the length of this fragment */ |
| ps += 2; |
| *ps = nci_ctrl_size; |
| |
| /* add NCI packet type in front of message */ |
| nfc_hal_nci_add_nfc_pkt_type (p_buf); |
| |
| /* send this fragment to transport */ |
| p = (UINT8 *) (p_buf + 1) + p_buf->offset; |
| |
| #ifdef DISP_NCI |
| delta = p_buf->len - max_len; |
| DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); |
| #endif |
| USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); |
| |
| /* adjust the len and offset to reflect that part of the command is already sent */ |
| buf_len -= nci_ctrl_size; |
| offset += nci_ctrl_size; |
| HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len); |
| p_buf->len = buf_len; |
| p_buf->offset = offset; |
| pd = (UINT8 *) (p_buf + 1) + p_buf->offset; |
| /* restore the NCI header */ |
| memcpy (pd, hdr, NCI_MSG_HDR_SIZE); |
| pd += 2; |
| *pd = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE); |
| } |
| |
| HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len); |
| |
| /* add NCI packet type in front of message */ |
| nfc_hal_nci_add_nfc_pkt_type (p_buf); |
| |
| /* send this fragment to transport */ |
| p = (UINT8 *) (p_buf + 1) + p_buf->offset; |
| |
| #ifdef DISP_NCI |
| delta = p_buf->len - buf_len; |
| DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); |
| #endif |
| USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); |
| |
| GKI_freebuf (p_buf); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function nfc_hal_nci_cmd_timeout_cback |
| ** |
| ** Description callback function for timeout |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void nfc_hal_nci_cmd_timeout_cback (void *p_tle) |
| { |
| TIMER_LIST_ENT *p_tlent = (TIMER_LIST_ENT *)p_tle; |
| |
| HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()"); |
| |
| nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; |
| |
| if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP) |
| { |
| if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO) |
| { |
| NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); |
| } |
| else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) |
| { |
| if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE) |
| { |
| nfc_hal_prm_process_timeout (NULL); |
| } |
| else |
| { |
| NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); |
| } |
| } |
| else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE) |
| { |
| NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); |
| } |
| else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE) |
| { |
| NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); |
| } |
| else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE) |
| { |
| NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); |
| nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); |
| } |
| else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF) |
| { |
| nfc_hal_main_close (); |
| } |
| } |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function HAL_NfcSetMaxRfDataCredits |
| ** |
| ** Description This function sets the maximum RF data credit for HAL. |
| ** If 0, use the value reported from NFCC. |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits) |
| { |
| HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits); |
| nfc_hal_cb.max_rf_credits = max_credits; |
| } |