Home | History | Annotate | Download | only in hal
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2014 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 ((p_cb->p_rcv_msg) &&
    320                 ((sizeof (NFC_HDR) + HCIE_PREAMBLE_SIZE + byte) > GKI_get_buf_size (p_cb->p_rcv_msg))  )
    321             {
    322                 /* Message cannot fit into buffer */
    323                 GKI_freebuf (p_cb->p_rcv_msg);
    324                 p_cb->p_rcv_msg     = NULL;
    325 
    326                 HAL_TRACE_ERROR0 ("Invalid length for incoming BT HCI message.");
    327             }
    328 
    329             /* Message length is valid */
    330             if (byte)
    331             {
    332                 /* Read rest of message */
    333                 p_cb->rcv_state = NFC_HAL_RCV_BT_PAYLOAD_ST;
    334             }
    335             else
    336             {
    337                 /* Message has no additional parameters. (Entire message has been received) */
    338                 msg_received    = TRUE;
    339                 p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST;  /* Next, wait for packet type of next message */
    340             }
    341         }
    342         break;
    343 
    344     case NFC_HAL_RCV_BT_PAYLOAD_ST:
    345         p_cb->rcv_len--;
    346         if (p_cb->p_rcv_msg)
    347         {
    348             *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte;
    349 
    350             if (p_cb->rcv_len > 0)
    351             {
    352                 /* Read in the rest of the message */
    353                 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);
    354                 p_cb->p_rcv_msg->len    += len;
    355                 p_cb->rcv_len           -= len;
    356             }
    357         }
    358 
    359         /* Check if we read in entire message yet */
    360         if (p_cb->rcv_len == 0)
    361         {
    362             msg_received        = TRUE;
    363             p_cb->rcv_state     = NFC_HAL_RCV_IDLE_ST;      /* Next, wait for packet type of next message */
    364         }
    365         break;
    366     }
    367 
    368     /* If we received entire message */
    369 #if (NFC_HAL_TRACE_PROTOCOL == TRUE)
    370     if (msg_received && p_cb->p_rcv_msg)
    371     {
    372         /* Display protocol trace message */
    373         DispHciEvt (p_cb->p_rcv_msg);
    374     }
    375 #endif
    376 
    377     return (msg_received);
    378 }
    379 
    380 /*******************************************************************************
    381 **
    382 ** Function         nfc_hal_nci_proc_rx_bt_msg
    383 **
    384 ** Description      Received BT message from NFCC
    385 **
    386 **                  Notify command complete if initializing NFCC
    387 **                  Forward BT message to NFC task
    388 **
    389 ** Returns          void
    390 **
    391 *******************************************************************************/
    392 static void nfc_hal_nci_proc_rx_bt_msg (void)
    393 {
    394     UINT8   *p;
    395     NFC_HDR *p_msg;
    396     UINT16  opcode, old_opcode;
    397     tNFC_HAL_BTVSC_CPLT       vcs_cplt_params;
    398     tNFC_HAL_BTVSC_CPLT_CBACK *p_cback = NULL;
    399 
    400     /* if complete BT message is received successfully */
    401     if (nfc_hal_cb.ncit_cb.p_rcv_msg)
    402     {
    403         p_msg   = nfc_hal_cb.ncit_cb.p_rcv_msg;
    404         HAL_TRACE_DEBUG1 ("nfc_hal_nci_proc_rx_bt_msg (): GOT an BT msgs init_sta:%d", nfc_hal_cb.dev_cb.initializing_state);
    405         HAL_TRACE_DEBUG2 ("event: 0x%x, wait_rsp:0x%x", p_msg->event, nfc_hal_cb.ncit_cb.nci_wait_rsp);
    406         /* increase the cmd window here */
    407         if (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_PROP)
    408         {
    409             p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    410             if (*p == HCI_COMMAND_COMPLETE_EVT)
    411             {
    412                 p  += 3; /* code, len, cmd window */
    413                 STREAM_TO_UINT16 (opcode, p);
    414                 p   = nfc_hal_cb.ncit_cb.last_hdr;
    415                 STREAM_TO_UINT16 (old_opcode, p);
    416                 if (opcode == old_opcode)
    417                 {
    418                     nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
    419                     p_cback = (tNFC_HAL_BTVSC_CPLT_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback;
    420                     nfc_hal_cb.ncit_cb.p_vsc_cback  = NULL;
    421                     nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
    422                 }
    423             }
    424         }
    425 
    426         /* if initializing BRCM NFCC */
    427         if ((nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) ||
    428             (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_BUILD_INFO) ||
    429             (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE))
    430         {
    431             /* this is command complete event for baud rate update or download patch */
    432             p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    433 
    434             p += 1;    /* skip opcode */
    435             STREAM_TO_UINT8  (vcs_cplt_params.param_len, p);
    436 
    437             p += 1;    /* skip num command packets */
    438             STREAM_TO_UINT16 (vcs_cplt_params.opcode, p);
    439 
    440             vcs_cplt_params.param_len -= 3;
    441             vcs_cplt_params.p_param_buf = p;
    442 
    443             if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)
    444             {
    445                 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    446                 nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_OK);
    447             }
    448             if (p_cback)
    449             {
    450                 nfc_hal_cb.ncit_cb.p_vsc_cback = NULL;
    451                 (*p_cback) (&vcs_cplt_params);
    452             }
    453 
    454             /* do not BT send message to NFC task */
    455             GKI_freebuf (p_msg);
    456         }
    457         else
    458         {
    459             /* do not BT send message to NFC task */
    460             GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg);
    461         }
    462         nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
    463     }
    464 }
    465 
    466 /*****************************************************************************
    467 **
    468 ** Function         nfc_hal_nci_receive_msg
    469 **
    470 ** Description
    471 **      Handle incoming data (NCI events) from the serial port.
    472 **
    473 **      If there is data waiting from the serial port, this funciton reads the
    474 **      data and parses it. Once an entire NCI message has been read, it sends
    475 **      the message the the NFC_TASK for processing
    476 **
    477 *****************************************************************************/
    478 BOOLEAN nfc_hal_nci_receive_msg (UINT8 byte)
    479 {
    480     tNFC_HAL_NCIT_CB *p_cb = &(nfc_hal_cb.ncit_cb);
    481     BOOLEAN msg_received = FALSE;
    482 
    483     if (p_cb->rcv_state == NFC_HAL_RCV_IDLE_ST)
    484     {
    485         /* if this is NCI message */
    486         if (byte == HCIT_TYPE_NFC)
    487         {
    488             p_cb->rcv_state = NFC_HAL_RCV_NCI_MSG_ST;
    489         }
    490         /* if this is BT message */
    491         else if (byte == HCIT_TYPE_EVENT)
    492         {
    493             p_cb->rcv_state = NFC_HAL_RCV_BT_MSG_ST;
    494         }
    495         else
    496         {
    497             HAL_TRACE_ERROR1 ("Unknown packet type drop this byte 0x%x", byte);
    498         }
    499     }
    500     else if (p_cb->rcv_state <= NFC_HAL_RCV_NCI_PAYLOAD_ST)
    501     {
    502         msg_received = nfc_hal_nci_receive_nci_msg (p_cb, byte);
    503     }
    504     else
    505     {
    506         if (nfc_hal_nci_receive_bt_msg (p_cb, byte))
    507         {
    508             /* received BT message */
    509             nfc_hal_nci_proc_rx_bt_msg ();
    510         }
    511     }
    512 
    513     return (msg_received);
    514 }
    515 
    516 /*******************************************************************************
    517 **
    518 ** Function         nfc_hal_nci_preproc_rx_nci_msg
    519 **
    520 ** Description      NFCC sends NCI message to DH while initializing NFCC
    521 **                  processing low power mode
    522 **
    523 ** Returns          TRUE, if NFC task need to receive NCI message
    524 **
    525 *******************************************************************************/
    526 BOOLEAN nfc_hal_nci_preproc_rx_nci_msg (NFC_HDR *p_msg)
    527 {
    528     UINT8 *p, *pp;
    529     UINT8 mt, pbf, gid, op_code;
    530     UINT8 payload_len;
    531 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    532     UINT8  cid;
    533     UINT16 data_len;
    534 #endif
    535 
    536     HAL_TRACE_DEBUG0 ("nfc_hal_nci_preproc_rx_nci_msg()");
    537 
    538     /* if initializing BRCM NFCC */
    539     if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE)
    540     {
    541         nfc_hal_dm_proc_msg_during_init (p_msg);
    542         /* do not send message to NFC task while initializing NFCC */
    543         return (FALSE);
    544     }
    545     else
    546     {
    547         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    548         pp = p;
    549         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    550         NCI_MSG_PRS_HDR1 (p, op_code);
    551         payload_len = *p++;
    552 
    553 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    554         if (mt == NCI_MT_DATA)
    555         {
    556             if (nfc_hal_cb.hci_cb.hcp_conn_id)
    557             {
    558                 NCI_DATA_PRS_HDR(pp, pbf, cid, data_len);
    559                 if (cid == nfc_hal_cb.hci_cb.hcp_conn_id)
    560                 {
    561                     nfc_hal_hci_handle_hcp_pkt_from_hc (pp);
    562                 }
    563 
    564             }
    565         }
    566 
    567         if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */
    568         {
    569             if (mt == NCI_MT_NTF)
    570             {
    571                 if (op_code == NCI_MSG_HCI_NETWK)
    572                 {
    573                     nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset);
    574                 }
    575             }
    576         }
    577         else
    578 #endif
    579         if (gid == NCI_GID_RF_MANAGE)
    580         {
    581             if (mt == NCI_MT_NTF)
    582             {
    583                 if (op_code == NCI_MSG_RF_INTF_ACTIVATED)
    584                 {
    585                     if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5))
    586                     {
    587                         /* API used wants to limit the RF data credits */
    588                         p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */
    589                         if (*p > nfc_hal_cb.max_rf_credits)
    590                         {
    591                             HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits);
    592                             *p = nfc_hal_cb.max_rf_credits;
    593                         }
    594                     }
    595                 }
    596             }
    597         }
    598 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    599         else if (gid == NCI_GID_CORE)
    600         {
    601             if (mt == NCI_MT_RSP)
    602             {
    603                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    604                 {
    605                     if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp)
    606                     {
    607                         p++; /* skip status byte */
    608                         nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    609                         p++; /* skip buff size */
    610                         p++; /* num of buffers */
    611                         nfc_hal_cb.hci_cb.hcp_conn_id = *p;
    612                     }
    613                 }
    614             }
    615         }
    616 #endif
    617     }
    618 
    619     if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL)
    620     {
    621         if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE)
    622         {
    623             /* extend idle timer */
    624             nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT);
    625         }
    626     }
    627 
    628     return (TRUE);
    629 }
    630 
    631 /*******************************************************************************
    632 **
    633 ** Function         nfc_hal_nci_add_nfc_pkt_type
    634 **
    635 ** Description      Add packet type (HCIT_TYPE_NFC)
    636 **
    637 ** Returns          TRUE, if NFCC can receive NCI message
    638 **
    639 *******************************************************************************/
    640 void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg)
    641 {
    642     UINT8   *p;
    643     UINT8   hcit;
    644 
    645     /* add packet type in front of NCI header */
    646     if (p_msg->offset > 0)
    647     {
    648         p_msg->offset--;
    649         p_msg->len++;
    650 
    651         p  = (UINT8 *) (p_msg + 1) + p_msg->offset;
    652         *p = HCIT_TYPE_NFC;
    653     }
    654     else
    655     {
    656         HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type");
    657         hcit = HCIT_TYPE_NFC;
    658         USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1);
    659     }
    660 }
    661 
    662 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    663 /*******************************************************************************
    664 **
    665 ** Function         nci_brcm_check_cmd_create_hcp_connection
    666 **
    667 ** Description      Check if this is command to create HCP connection
    668 **
    669 ** Returns          None
    670 **
    671 *******************************************************************************/
    672 static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg)
    673 {
    674     UINT8 *p;
    675     UINT8 mt, pbf, gid, op_code;
    676 
    677     nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    678 
    679     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    680 
    681     if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE)
    682     {
    683         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    684         NCI_MSG_PRS_HDR1 (p, op_code);
    685 
    686         if (gid == NCI_GID_CORE)
    687         {
    688             if (mt == NCI_MT_CMD)
    689             {
    690                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    691                 {
    692                     if (  ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++)
    693                         &&(NCI_DEST_TYPE_NFCEE == *p++)
    694                         &&(1 == *p++)
    695                         &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++)
    696                         &&(2 == *p++)  )
    697                     {
    698                         p++;
    699                         if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p)
    700                         {
    701                             nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE;
    702                             return;
    703                         }
    704                     }
    705 
    706                 }
    707             }
    708         }
    709     }
    710 }
    711 
    712 #endif
    713 
    714 /*******************************************************************************
    715 **
    716 ** Function         nfc_hal_nci_send_cmd
    717 **
    718 ** Description      Send NCI command to the transport
    719 **
    720 ** Returns          void
    721 **
    722 *******************************************************************************/
    723 void nfc_hal_nci_send_cmd (NFC_HDR *p_buf)
    724 {
    725     BOOLEAN continue_to_process = TRUE;
    726     UINT8   *ps, *pd;
    727     UINT16  max_len;
    728     UINT16  buf_len, offset;
    729     UINT8   *p;
    730     UINT8   hdr[NCI_MSG_HDR_SIZE];
    731     UINT8   nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size;
    732     UINT8   delta = 0;
    733 
    734 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    735     if (  (nfc_hal_cb.hci_cb.hcp_conn_id == 0)
    736         &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE)  )
    737         nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf);
    738 #endif
    739 
    740     /* check low power mode state */
    741     continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT);
    742 
    743     if (!continue_to_process)
    744     {
    745         /* save the command to be sent until NFCC is free. */
    746         nfc_hal_cb.ncit_cb.p_pend_cmd   = p_buf;
    747         return;
    748     }
    749 
    750     max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE;
    751     buf_len = p_buf->len;
    752     offset  = p_buf->offset;
    753 #ifdef DISP_NCI
    754     if (buf_len > max_len)
    755     {
    756         /* this command needs to be fragmented. display the complete packet first */
    757         DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE);
    758     }
    759 #endif
    760     ps      = (UINT8 *) (p_buf + 1) + p_buf->offset;
    761     memcpy (hdr, ps, NCI_MSG_HDR_SIZE);
    762     while (buf_len > max_len)
    763     {
    764         HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len);
    765         /* the NCI command is bigger than the NFCC Max Control Packet Payload Length
    766          * fragment the command */
    767 
    768         p_buf->len  = max_len;
    769         ps   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    770         /* mark the control packet as fragmented */
    771         *ps |= NCI_PBF_ST_CONT;
    772         /* adjust the length of this fragment */
    773         ps  += 2;
    774         *ps  = nci_ctrl_size;
    775 
    776         /* add NCI packet type in front of message */
    777         nfc_hal_nci_add_nfc_pkt_type (p_buf);
    778 
    779         /* send this fragment to transport */
    780         p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    781 
    782 #ifdef DISP_NCI
    783         delta = p_buf->len - max_len;
    784         DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    785 #endif
    786         USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    787 
    788         /* adjust the len and offset to reflect that part of the command is already sent */
    789         buf_len -= nci_ctrl_size;
    790         offset  += nci_ctrl_size;
    791         HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len);
    792         p_buf->len      = buf_len;
    793         p_buf->offset   = offset;
    794         pd   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    795         /* restore the NCI header */
    796         memcpy (pd, hdr, NCI_MSG_HDR_SIZE);
    797         pd  += 2;
    798         *pd  = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE);
    799     }
    800 
    801     HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len);
    802 
    803     /* add NCI packet type in front of message */
    804     nfc_hal_nci_add_nfc_pkt_type (p_buf);
    805 
    806     /* send this fragment to transport */
    807     p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    808 
    809 #ifdef DISP_NCI
    810     delta = p_buf->len - buf_len;
    811     DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    812 #endif
    813     USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    814 
    815     GKI_freebuf (p_buf);
    816 }
    817 
    818 /*******************************************************************************
    819 **
    820 ** Function         nfc_hal_nci_cmd_timeout_cback
    821 **
    822 ** Description      callback function for timeout
    823 **
    824 ** Returns          void
    825 **
    826 *******************************************************************************/
    827 void nfc_hal_nci_cmd_timeout_cback (void *p_tle)
    828 {
    829     TIMER_LIST_ENT  *p_tlent = (TIMER_LIST_ENT *)p_tle;
    830 
    831     HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()");
    832 
    833     nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
    834 
    835     if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP)
    836     {
    837         if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO)
    838         {
    839             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    840             nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    841         }
    842         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE)
    843         {
    844             if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE)
    845             {
    846                 nfc_hal_prm_process_timeout (NULL);
    847             }
    848             else
    849             {
    850                 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    851                 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    852             }
    853         }
    854         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE)
    855         {
    856             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    857             nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    858         }
    859         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)
    860         {
    861             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    862             nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    863         }
    864         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE)
    865         {
    866             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    867             nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    868         }
    869     }
    870 }
    871 
    872 
    873 /*******************************************************************************
    874 **
    875 ** Function         HAL_NfcSetMaxRfDataCredits
    876 **
    877 ** Description      This function sets the maximum RF data credit for HAL.
    878 **                  If 0, use the value reported from NFCC.
    879 **
    880 ** Returns          none
    881 **
    882 *******************************************************************************/
    883 void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits)
    884 {
    885     HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits);
    886     nfc_hal_cb.max_rf_credits   = max_credits;
    887 }
    888