Home | History | Annotate | Download | only in hal
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2013 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 
     20 /******************************************************************************
     21  *
     22  *  This file contains function of the NFC unit to receive/process NCI/VS
     23  *  commands/responses.
     24  *
     25  ******************************************************************************/
     26 #include <string.h>
     27 #include "nfc_hal_int.h"
     28 #include "nfc_hal_post_reset.h"
     29 #include "userial.h"
     30 #include "nci_defs.h"
     31 
     32 
     33 /*****************************************************************************
     34 ** Constants and types
     35 *****************************************************************************/
     36 
     37 /*****************************************************************************
     38 ** Local function prototypes
     39 *****************************************************************************/
     40 
     41 /*******************************************************************************
     42 **
     43 ** Function         nfc_hal_nci_assemble_nci_msg
     44 **
     45 ** Description      This function is called to reassemble the received NCI
     46 **                  response/notification packet, if required.
     47 **                  (The data packets are posted to NFC task for reassembly)
     48 **
     49 ** Returns          void.
     50 **
     51 *******************************************************************************/
     52 void nfc_hal_nci_assemble_nci_msg (void)
     53 {
     54     NFC_HDR *p_msg = nfc_hal_cb.ncit_cb.p_rcv_msg;
     55     UINT8 u8;
     56     UINT8 *p, *pp;
     57     UINT8 hdr[2];
     58     UINT8   *ps, *pd;
     59     UINT16  size, needed;
     60     BOOLEAN disp_again = FALSE;
     61 
     62     if ((p_msg == NULL) || (p_msg->len < NCI_MSG_HDR_SIZE))
     63         return;
     64 
     65 #ifdef DISP_NCI
     66     DISP_NCI ((UINT8 *) (p_msg + 1) + p_msg->offset, (UINT16) (p_msg->len), TRUE);
     67 #endif
     68 
     69     p       = (UINT8 *) (p_msg + 1) + p_msg->offset;
     70     u8      = *p++;
     71     /* remove the PBF bit for potential reassembly later */
     72     hdr[0]  = u8 & ~NCI_PBF_MASK;
     73     if ((u8 & NCI_MT_MASK) == NCI_MT_DATA)
     74     {
     75         /* clear the RFU in octet1 */
     76         *(p) = 0;
     77         /* data packet reassembly is performed in NFC task */
     78         return;
     79     }
     80     else
     81     {
     82         *(p) &= NCI_OID_MASK;
     83     }
     84 
     85     hdr[1]  = *p;
     86     pp = hdr;
     87     /* save octet0 and octet1 of an NCI header in layer_specific for the received packet */
     88     STREAM_TO_UINT16 (p_msg->layer_specific, pp);
     89 
     90     if (nfc_hal_cb.ncit_cb.p_frag_msg)
     91     {
     92         if (nfc_hal_cb.ncit_cb.p_frag_msg->layer_specific != p_msg->layer_specific)
     93         {
     94             /* check if these fragments are of the same NCI message */
     95             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);
     96             nfc_hal_cb.ncit_cb.nci_ras  |= NFC_HAL_NCI_RAS_ERROR;
     97         }
     98         else if (nfc_hal_cb.ncit_cb.nci_ras == 0)
     99         {
    100             disp_again = TRUE;
    101             /* if not previous reassembly error, append the new fragment */
    102             p_msg->offset   += NCI_MSG_HDR_SIZE;
    103             p_msg->len      -= NCI_MSG_HDR_SIZE;
    104             size    = GKI_get_buf_size (nfc_hal_cb.ncit_cb.p_frag_msg);
    105             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);
    106             if (size >= needed)
    107             {
    108                 /* the buffer for reassembly is big enough to append the new fragment */
    109                 ps   = (UINT8 *) (p_msg + 1) + p_msg->offset;
    110                 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;
    111                 memcpy (pd, ps, p_msg->len);
    112                 nfc_hal_cb.ncit_cb.p_frag_msg->len  += p_msg->len;
    113                 /* adjust the NCI packet length */
    114                 pd   = (UINT8 *) (nfc_hal_cb.ncit_cb.p_frag_msg + 1) + nfc_hal_cb.ncit_cb.p_frag_msg->offset + 2;
    115                 *pd  = (UINT8) (nfc_hal_cb.ncit_cb.p_frag_msg->len - NCI_MSG_HDR_SIZE);
    116             }
    117             else
    118             {
    119                 nfc_hal_cb.ncit_cb.nci_ras  |= NFC_HAL_NCI_RAS_TOO_BIG;
    120                 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);
    121             }
    122         }
    123         /* we are done with this new fragment, free it */
    124         GKI_freebuf (p_msg);
    125     }
    126     else
    127     {
    128         nfc_hal_cb.ncit_cb.p_frag_msg = p_msg;
    129     }
    130 
    131 
    132     if ((u8 & NCI_PBF_MASK) == NCI_PBF_NO_OR_LAST)
    133     {
    134         /* last fragment */
    135         p_msg               = nfc_hal_cb.ncit_cb.p_frag_msg;
    136         p                   = (UINT8 *) (p_msg + 1) + p_msg->offset;
    137         *p                  = u8; /* this should make the PBF flag as Last Fragment */
    138         nfc_hal_cb.ncit_cb.p_frag_msg  = NULL;
    139 
    140         p_msg->layer_specific = nfc_hal_cb.ncit_cb.nci_ras;
    141         /* still report the data packet, if the incoming packet is too big */
    142         if (nfc_hal_cb.ncit_cb.nci_ras & NFC_HAL_NCI_RAS_ERROR)
    143         {
    144             /* NFCC reported NCI fragments for different NCI messages and this is the last fragment - drop it */
    145             HAL_TRACE_ERROR0 ("nfc_hal_nci_assemble_nci_msg() clearing NCI_RAS_ERROR");
    146             GKI_freebuf (p_msg);
    147             p_msg = NULL;
    148         }
    149 #ifdef DISP_NCI
    150         if ((nfc_hal_cb.ncit_cb.nci_ras == 0) && (disp_again))
    151         {
    152             DISP_NCI ((UINT8 *) (p_msg + 1) + p_msg->offset, (UINT16) (p_msg->len), TRUE);
    153         }
    154 #endif
    155         /* clear the error flags, so the next NCI packet is clean */
    156         nfc_hal_cb.ncit_cb.nci_ras = 0;
    157     }
    158     else
    159     {
    160         /* still reassembling */
    161         p_msg = NULL;
    162     }
    163 
    164     nfc_hal_cb.ncit_cb.p_rcv_msg = p_msg;
    165 }
    166 
    167 /*****************************************************************************
    168 **
    169 ** Function         nfc_hal_nci_receive_nci_msg
    170 **
    171 ** Description
    172 **      Handle incoming data (NCI events) from the serial port.
    173 **
    174 **      If there is data waiting from the serial port, this funciton reads the
    175 **      data and parses it. Once an entire NCI message has been read, it sends
    176 **      the message the the NFC_TASK for processing
    177 **
    178 *****************************************************************************/
    179 static BOOLEAN nfc_hal_nci_receive_nci_msg (tNFC_HAL_NCIT_CB *p_cb, UINT8 byte)
    180 {
    181     UINT16      len;
    182     BOOLEAN     msg_received = FALSE;
    183 
    184     switch (p_cb->rcv_state)
    185     {
    186     case NFC_HAL_RCV_NCI_MSG_ST:
    187 
    188         /* Initialize rx parameters */
    189         p_cb->rcv_state = NFC_HAL_RCV_NCI_HDR_ST;
    190         p_cb->rcv_len   = NCI_MSG_HDR_SIZE;
    191 
    192         /* Start of new message. Allocate a buffer for message */
    193         if ((p_cb->p_rcv_msg = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL)
    194         {
    195             /* Initialize NFC_HDR */
    196             p_cb->p_rcv_msg->len    = 0;
    197             p_cb->p_rcv_msg->event  = 0;
    198             p_cb->p_rcv_msg->offset = 0;
    199 
    200             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    201         }
    202         else
    203         {
    204             HAL_TRACE_ERROR0 ("Unable to allocate buffer for incoming NCI message.");
    205         }
    206         p_cb->rcv_len--;
    207         break;
    208 
    209     case NFC_HAL_RCV_NCI_HDR_ST:
    210 
    211         if (p_cb->p_rcv_msg)
    212         {
    213             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    214         }
    215 
    216         p_cb->rcv_len--;
    217 
    218         /* Check if we read in entire NFC message header yet */
    219         if (p_cb->rcv_len == 0)
    220         {
    221             p_cb->rcv_len       = byte;
    222 
    223             /* If non-zero payload, then go to receive-data state */
    224             if (byte > 0)
    225             {
    226                 p_cb->rcv_state = NFC_HAL_RCV_NCI_PAYLOAD_ST;
    227             }
    228             else
    229             {
    230                 msg_received    = TRUE;
    231                 p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST;
    232             }
    233         }
    234         break;
    235 
    236     case NFC_HAL_RCV_NCI_PAYLOAD_ST:
    237 
    238         p_cb->rcv_len--;
    239         if (p_cb->p_rcv_msg)
    240         {
    241             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    242 
    243             if (p_cb->rcv_len > 0)
    244             {
    245                 /* Read in the rest of the message */
    246                 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);
    247                 p_cb->p_rcv_msg->len    += len;
    248                 p_cb->rcv_len           -= len;
    249             }
    250         }
    251 
    252         /* Check if we read in entire message yet */
    253         if (p_cb->rcv_len == 0)
    254         {
    255             msg_received    = TRUE;
    256             p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST;
    257         }
    258         break;
    259     }
    260 
    261     return (msg_received);
    262 }
    263 
    264 /*****************************************************************************
    265 **
    266 ** Function         nfc_hal_nci_receive_bt_msg
    267 **
    268 ** Description
    269 **      Handle incoming BRCM specific data from the serial port.
    270 **
    271 **      If there is data waiting from the serial port, this funciton reads the
    272 **      data and parses it. Once an entire message has been read, it returns
    273 **      TRUE.
    274 **
    275 *****************************************************************************/
    276 static BOOLEAN nfc_hal_nci_receive_bt_msg (tNFC_HAL_NCIT_CB *p_cb, UINT8 byte)
    277 {
    278     UINT16  len;
    279     BOOLEAN msg_received = FALSE;
    280 
    281     switch (p_cb->rcv_state)
    282     {
    283     case NFC_HAL_RCV_BT_MSG_ST:
    284 
    285         /* Initialize rx parameters */
    286         p_cb->rcv_state = NFC_HAL_RCV_BT_HDR_ST;
    287         p_cb->rcv_len   = HCIE_PREAMBLE_SIZE;
    288 
    289         if ((p_cb->p_rcv_msg = (NFC_HDR *) GKI_getpoolbuf (NFC_HAL_NCI_POOL_ID)) != NULL)
    290         {
    291             /* Initialize NFC_HDR */
    292             p_cb->p_rcv_msg->len    = 0;
    293             p_cb->p_rcv_msg->event  = 0;
    294             p_cb->p_rcv_msg->offset = 0;
    295 
    296             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    297         }
    298         else
    299         {
    300             HAL_TRACE_ERROR0 ("[nfc] Unable to allocate buffer for incoming NCI message.");
    301         }
    302         p_cb->rcv_len--;
    303         break;
    304 
    305     case NFC_HAL_RCV_BT_HDR_ST:
    306         if (p_cb->p_rcv_msg)
    307         {
    308             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    309         }
    310         p_cb->rcv_len--;
    311 
    312         /* Check if we received entire preamble yet */
    313         if (p_cb->rcv_len == 0)
    314         {
    315             /* Received entire preamble. Length is in the last byte(s) of the preamble */
    316             p_cb->rcv_len = byte;
    317 
    318             /* Verify that buffer is big enough to fit message */
    319             if ((sizeof (NFC_HDR) + HCIE_PREAMBLE_SIZE + byte) > GKI_get_buf_size (p_cb->p_rcv_msg))
    320             {
    321                 /* Message cannot fit into buffer */
    322                 GKI_freebuf (p_cb->p_rcv_msg);
    323                 p_cb->p_rcv_msg     = NULL;
    324 
    325                 HAL_TRACE_ERROR0 ("Invalid length for incoming BT HCI message.");
    326             }
    327 
    328             /* Message length is valid */
    329             if (byte)
    330             {
    331                 /* Read rest of message */
    332                 p_cb->rcv_state = NFC_HAL_RCV_BT_PAYLOAD_ST;
    333             }
    334             else
    335             {
    336                 /* Message has no additional parameters. (Entire message has been received) */
    337                 msg_received    = TRUE;
    338                 p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST;  /* Next, wait for packet type of next message */
    339             }
    340         }
    341         break;
    342 
    343     case NFC_HAL_RCV_BT_PAYLOAD_ST:
    344         p_cb->rcv_len--;
    345         if (p_cb->p_rcv_msg)
    346         {
    347             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    348 
    349             if (p_cb->rcv_len > 0)
    350             {
    351                 /* Read in the rest of the message */
    352                 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);
    353                 p_cb->p_rcv_msg->len    += len;
    354                 p_cb->rcv_len           -= len;
    355             }
    356         }
    357 
    358         /* Check if we read in entire message yet */
    359         if (p_cb->rcv_len == 0)
    360         {
    361             msg_received        = TRUE;
    362             p_cb->rcv_state     = NFC_HAL_RCV_IDLE_ST;      /* Next, wait for packet type of next message */
    363         }
    364         break;
    365     }
    366 
    367     /* If we received entire message */
    368 #if (NFC_HAL_TRACE_PROTOCOL == TRUE)
    369     if (msg_received && p_cb->p_rcv_msg)
    370     {
    371         /* Display protocol trace message */
    372         DispHciEvt (p_cb->p_rcv_msg);
    373     }
    374 #endif
    375 
    376     return (msg_received);
    377 }
    378 
    379 /*******************************************************************************
    380 **
    381 ** Function         nfc_hal_nci_proc_rx_bt_msg
    382 **
    383 ** Description      Received BT message from NFCC
    384 **
    385 **                  Notify command complete if initializing NFCC
    386 **                  Forward BT message to NFC task
    387 **
    388 ** Returns          void
    389 **
    390 *******************************************************************************/
    391 static void nfc_hal_nci_proc_rx_bt_msg (void)
    392 {
    393     UINT8   *p;
    394     NFC_HDR *p_msg;
    395     UINT16  opcode, old_opcode;
    396     tNFC_HAL_BTVSC_CPLT       vcs_cplt_params;
    397     tNFC_HAL_BTVSC_CPLT_CBACK *p_cback = NULL;
    398 
    399     /* if complete BT message is received successfully */
    400     if (nfc_hal_cb.ncit_cb.p_rcv_msg)
    401     {
    402         p_msg   = nfc_hal_cb.ncit_cb.p_rcv_msg;
    403         HAL_TRACE_DEBUG1 ("nfc_hal_nci_proc_rx_bt_msg (): GOT an BT msgs init_sta:%d", nfc_hal_cb.dev_cb.initializing_state);
    404         HAL_TRACE_DEBUG2 ("event: 0x%x, wait_rsp:0x%x", p_msg->event, nfc_hal_cb.ncit_cb.nci_wait_rsp);
    405         /* increase the cmd window here */
    406         if (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_PROP)
    407         {
    408             p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    409             if (*p == HCI_COMMAND_COMPLETE_EVT)
    410             {
    411                 p  += 3; /* code, len, cmd window */
    412                 STREAM_TO_UINT16 (opcode, p);
    413                 p   = nfc_hal_cb.ncit_cb.last_hdr;
    414                 STREAM_TO_UINT16 (old_opcode, p);
    415                 if (opcode == old_opcode)
    416                 {
    417                     nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
    418                     p_cback = (tNFC_HAL_BTVSC_CPLT_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback;
    419                     nfc_hal_cb.ncit_cb.p_vsc_cback  = NULL;
    420                     nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
    421                 }
    422             }
    423         }
    424 
    425         /* if initializing BRCM NFCC */
    426         if ((nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) ||
    427             (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE))
    428         {
    429             /* this is command complete event for baud rate update or download patch */
    430             p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    431 
    432             p += 1;    /* skip opcode */
    433             STREAM_TO_UINT8  (vcs_cplt_params.param_len, p);
    434 
    435             p += 1;    /* skip num command packets */
    436             STREAM_TO_UINT16 (vcs_cplt_params.opcode, p);
    437 
    438             vcs_cplt_params.param_len -= 3;
    439             vcs_cplt_params.p_param_buf = p;
    440 
    441             if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)
    442             {
    443                 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    444                 nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_OK);
    445             }
    446             if (p_cback)
    447             {
    448                 nfc_hal_cb.ncit_cb.p_vsc_cback = NULL;
    449                 (*p_cback) (&vcs_cplt_params);
    450             }
    451 
    452             /* do not BT send message to NFC task */
    453             GKI_freebuf (p_msg);
    454         }
    455         else
    456         {
    457             /* do not BT send message to NFC task */
    458             GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg);
    459         }
    460         nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
    461     }
    462 }
    463 
    464 /*****************************************************************************
    465 **
    466 ** Function         nfc_hal_nci_receive_msg
    467 **
    468 ** Description
    469 **      Handle incoming data (NCI events) from the serial port.
    470 **
    471 **      If there is data waiting from the serial port, this funciton reads the
    472 **      data and parses it. Once an entire NCI message has been read, it sends
    473 **      the message the the NFC_TASK for processing
    474 **
    475 *****************************************************************************/
    476 BOOLEAN nfc_hal_nci_receive_msg (UINT8 byte)
    477 {
    478     tNFC_HAL_NCIT_CB *p_cb = &(nfc_hal_cb.ncit_cb);
    479     BOOLEAN msg_received = FALSE;
    480 
    481     if (p_cb->rcv_state == NFC_HAL_RCV_IDLE_ST)
    482     {
    483         /* if this is NCI message */
    484         if (byte == HCIT_TYPE_NFC)
    485         {
    486             p_cb->rcv_state = NFC_HAL_RCV_NCI_MSG_ST;
    487         }
    488         /* if this is BT message */
    489         else if (byte == HCIT_TYPE_EVENT)
    490         {
    491             p_cb->rcv_state = NFC_HAL_RCV_BT_MSG_ST;
    492         }
    493         else
    494         {
    495             HAL_TRACE_ERROR1 ("Unknown packet type drop this byte 0x%x", byte);
    496         }
    497     }
    498     else if (p_cb->rcv_state <= NFC_HAL_RCV_NCI_PAYLOAD_ST)
    499     {
    500         msg_received = nfc_hal_nci_receive_nci_msg (p_cb, byte);
    501     }
    502     else
    503     {
    504         if (nfc_hal_nci_receive_bt_msg (p_cb, byte))
    505         {
    506             /* received BT message */
    507             nfc_hal_nci_proc_rx_bt_msg ();
    508         }
    509     }
    510 
    511     return (msg_received);
    512 }
    513 
    514 /*******************************************************************************
    515 **
    516 ** Function         nfc_hal_nci_preproc_rx_nci_msg
    517 **
    518 ** Description      NFCC sends NCI message to DH while initializing NFCC
    519 **                  processing low power mode
    520 **
    521 ** Returns          TRUE, if NFC task need to receive NCI message
    522 **
    523 *******************************************************************************/
    524 BOOLEAN nfc_hal_nci_preproc_rx_nci_msg (NFC_HDR *p_msg)
    525 {
    526     UINT8 *p, *pp, cid;
    527     UINT8 mt, pbf, gid, op_code;
    528     UINT8 payload_len;
    529     UINT16 data_len;
    530 
    531     HAL_TRACE_DEBUG0 ("nfc_hal_nci_preproc_rx_nci_msg()");
    532 
    533     /* if initializing BRCM NFCC */
    534     if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE)
    535     {
    536         nfc_hal_dm_proc_msg_during_init (p_msg);
    537         /* do not send message to NFC task while initializing NFCC */
    538         return (FALSE);
    539     }
    540     else
    541     {
    542         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    543         pp = p;
    544         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    545         NCI_MSG_PRS_HDR1 (p, op_code);
    546         payload_len = *p++;
    547 
    548         if (mt == NCI_MT_DATA)
    549         {
    550             if (nfc_hal_cb.hci_cb.hcp_conn_id)
    551             {
    552                 NCI_DATA_PRS_HDR(pp, pbf, cid, data_len);
    553                 if (cid == nfc_hal_cb.hci_cb.hcp_conn_id)
    554                 {
    555                     nfc_hal_hci_handle_hcp_pkt_from_hc (pp);
    556                 }
    557 
    558             }
    559         }
    560 
    561         if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */
    562         {
    563             if (mt == NCI_MT_NTF)
    564             {
    565                 if (op_code == NCI_MSG_HCI_NETWK)
    566                 {
    567                     nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset);
    568                 }
    569             }
    570         }
    571         else if (gid == NCI_GID_RF_MANAGE)
    572         {
    573             if (mt == NCI_MT_NTF)
    574             {
    575                 if (op_code == NCI_MSG_RF_INTF_ACTIVATED)
    576                 {
    577                     if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5))
    578                     {
    579                         /* API used wants to limit the RF data credits */
    580                         p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */
    581                         if (*p > nfc_hal_cb.max_rf_credits)
    582                         {
    583                             HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits);
    584                             *p = nfc_hal_cb.max_rf_credits;
    585                         }
    586                     }
    587                 }
    588             }
    589         }
    590         else if (gid == NCI_GID_CORE)
    591         {
    592             if (mt == NCI_MT_RSP)
    593             {
    594                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    595                 {
    596                     if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp)
    597                     {
    598                         p++; /* skip status byte */
    599                         nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    600                         p++; /* skip buff size */
    601                         p++; /* num of buffers */
    602                         nfc_hal_cb.hci_cb.hcp_conn_id = *p;
    603                     }
    604                 }
    605             }
    606         }
    607     }
    608 
    609     if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL)
    610     {
    611         if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE)
    612         {
    613             /* extend idle timer */
    614             nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT);
    615         }
    616     }
    617 
    618     return (TRUE);
    619 }
    620 
    621 /*******************************************************************************
    622 **
    623 ** Function         nfc_hal_nci_add_nfc_pkt_type
    624 **
    625 ** Description      Add packet type (HCIT_TYPE_NFC)
    626 **
    627 ** Returns          TRUE, if NFCC can receive NCI message
    628 **
    629 *******************************************************************************/
    630 void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg)
    631 {
    632     UINT8   *p;
    633     UINT8   hcit;
    634 
    635     /* add packet type in front of NCI header */
    636     if (p_msg->offset > 0)
    637     {
    638         p_msg->offset--;
    639         p_msg->len++;
    640 
    641         p  = (UINT8 *) (p_msg + 1) + p_msg->offset;
    642         *p = HCIT_TYPE_NFC;
    643     }
    644     else
    645     {
    646         HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type");
    647         hcit = HCIT_TYPE_NFC;
    648         USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1);
    649     }
    650 }
    651 
    652 /*******************************************************************************
    653 **
    654 ** Function         nci_brcm_check_cmd_create_hcp_connection
    655 **
    656 ** Description      Check if this is command to create HCP connection
    657 **
    658 ** Returns          None
    659 **
    660 *******************************************************************************/
    661 static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg)
    662 {
    663     UINT8 *p;
    664     UINT8 mt, pbf, gid, op_code;
    665 
    666     nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    667 
    668     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    669 
    670     if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE)
    671     {
    672         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    673         NCI_MSG_PRS_HDR1 (p, op_code);
    674 
    675         if (gid == NCI_GID_CORE)
    676         {
    677             if (mt == NCI_MT_CMD)
    678             {
    679                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    680                 {
    681                     if (  ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++)
    682                         &&(NCI_DEST_TYPE_NFCEE == *p++)
    683                         &&(1 == *p++)
    684                         &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++)
    685                         &&(2 == *p++)  )
    686                     {
    687                         p++;
    688                         if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p)
    689                         {
    690                             nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE;
    691                             return;
    692                         }
    693                     }
    694 
    695                 }
    696             }
    697         }
    698     }
    699 }
    700 
    701 /*******************************************************************************
    702 **
    703 ** Function         nfc_hal_nci_send_cmd
    704 **
    705 ** Description      Send NCI command to the transport
    706 **
    707 ** Returns          void
    708 **
    709 *******************************************************************************/
    710 void nfc_hal_nci_send_cmd (NFC_HDR *p_buf)
    711 {
    712     BOOLEAN continue_to_process = TRUE;
    713     UINT8   *ps, *pd;
    714     UINT16  max_len;
    715     UINT16  buf_len, offset;
    716     UINT8   *p;
    717     UINT8   hdr[NCI_MSG_HDR_SIZE];
    718     UINT8   nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size;
    719     UINT8   delta = 0;
    720 
    721     if (  (nfc_hal_cb.hci_cb.hcp_conn_id == 0)
    722         &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE)  )
    723         nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf);
    724 
    725     /* check low power mode state */
    726     continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT);
    727 
    728     if (!continue_to_process)
    729     {
    730         /* save the command to be sent until NFCC is free. */
    731         nfc_hal_cb.ncit_cb.p_pend_cmd   = p_buf;
    732         return;
    733     }
    734 
    735     max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE;
    736     buf_len = p_buf->len;
    737     offset  = p_buf->offset;
    738 #ifdef DISP_NCI
    739     if (buf_len > max_len)
    740     {
    741         /* this command needs to be fragmented. display the complete packet first */
    742         DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE);
    743     }
    744 #endif
    745     ps      = (UINT8 *) (p_buf + 1) + p_buf->offset;
    746     memcpy (hdr, ps, NCI_MSG_HDR_SIZE);
    747     while (buf_len > max_len)
    748     {
    749         HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len);
    750         /* the NCI command is bigger than the NFCC Max Control Packet Payload Length
    751          * fragment the command */
    752 
    753         p_buf->len  = max_len;
    754         ps   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    755         /* mark the control packet as fragmented */
    756         *ps |= NCI_PBF_ST_CONT;
    757         /* adjust the length of this fragment */
    758         ps  += 2;
    759         *ps  = nci_ctrl_size;
    760 
    761         /* add NCI packet type in front of message */
    762         nfc_hal_nci_add_nfc_pkt_type (p_buf);
    763 
    764         /* send this fragment to transport */
    765         p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    766 
    767 #ifdef DISP_NCI
    768         delta = p_buf->len - max_len;
    769         DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    770 #endif
    771         USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    772 
    773         /* adjust the len and offset to reflect that part of the command is already sent */
    774         buf_len -= nci_ctrl_size;
    775         offset  += nci_ctrl_size;
    776         HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len);
    777         p_buf->len      = buf_len;
    778         p_buf->offset   = offset;
    779         pd   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    780         /* restore the NCI header */
    781         memcpy (pd, hdr, NCI_MSG_HDR_SIZE);
    782         pd  += 2;
    783         *pd  = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE);
    784     }
    785 
    786     HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len);
    787 
    788     /* add NCI packet type in front of message */
    789     nfc_hal_nci_add_nfc_pkt_type (p_buf);
    790 
    791     /* send this fragment to transport */
    792     p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    793 
    794 #ifdef DISP_NCI
    795     delta = p_buf->len - buf_len;
    796     DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    797 #endif
    798     USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    799 
    800     GKI_freebuf (p_buf);
    801 }
    802 
    803 /*******************************************************************************
    804 **
    805 ** Function         nfc_hal_nci_cmd_timeout_cback
    806 **
    807 ** Description      callback function for timeout
    808 **
    809 ** Returns          void
    810 **
    811 *******************************************************************************/
    812 void nfc_hal_nci_cmd_timeout_cback (void *p_tle)
    813 {
    814     TIMER_LIST_ENT  *p_tlent = (TIMER_LIST_ENT *)p_tle;
    815 
    816     HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()");
    817 
    818     nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
    819 
    820     if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP)
    821     {
    822         if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO)
    823         {
    824             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    825             nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    826         }
    827         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE)
    828         {
    829             if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE)
    830             {
    831                 nfc_hal_prm_process_timeout (NULL);
    832             }
    833             else
    834             {
    835                 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    836                 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    837             }
    838         }
    839         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE)
    840         {
    841             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    842             nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    843         }
    844         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)
    845         {
    846             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    847             nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    848         }
    849         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE)
    850         {
    851             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    852             nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    853         }
    854     }
    855 }
    856 
    857 
    858 /*******************************************************************************
    859 **
    860 ** Function         HAL_NfcSetMaxRfDataCredits
    861 **
    862 ** Description      This function sets the maximum RF data credit for HAL.
    863 **                  If 0, use the value reported from NFCC.
    864 **
    865 ** Returns          none
    866 **
    867 *******************************************************************************/
    868 void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits)
    869 {
    870     HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits);
    871     nfc_hal_cb.max_rf_credits   = max_credits;
    872 }
    873