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 (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF)
    539     {
    540         /* if turning off BRCM NFCC */
    541         nfc_hal_dm_proc_msg_during_exit (p_msg);
    542         /* do not send message to NFC task while shutting down */
    543         return (FALSE);
    544     }
    545 
    546     /* if initializing BRCM NFCC */
    547     if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE)
    548     {
    549         nfc_hal_dm_proc_msg_during_init (p_msg);
    550         /* do not send message to NFC task while initializing NFCC */
    551         return (FALSE);
    552     }
    553     else
    554     {
    555         p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    556         pp = p;
    557         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    558         NCI_MSG_PRS_HDR1 (p, op_code);
    559         payload_len = *p++;
    560 
    561 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    562         if (mt == NCI_MT_DATA)
    563         {
    564             if (nfc_hal_cb.hci_cb.hcp_conn_id)
    565             {
    566                 NCI_DATA_PRS_HDR(pp, pbf, cid, data_len);
    567                 if (cid == nfc_hal_cb.hci_cb.hcp_conn_id)
    568                 {
    569                     nfc_hal_hci_handle_hcp_pkt_from_hc (pp);
    570                 }
    571 
    572             }
    573         }
    574 
    575         if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */
    576         {
    577             if (mt == NCI_MT_NTF)
    578             {
    579                 if (op_code == NCI_MSG_HCI_NETWK)
    580                 {
    581                     nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset);
    582                 }
    583             }
    584         }
    585         else
    586 #endif
    587         if (gid == NCI_GID_RF_MANAGE)
    588         {
    589             if (mt == NCI_MT_NTF)
    590             {
    591                 if (op_code == NCI_MSG_RF_INTF_ACTIVATED)
    592                 {
    593                     if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5))
    594                     {
    595                         /* API used wants to limit the RF data credits */
    596                         p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */
    597                         if (*p > nfc_hal_cb.max_rf_credits)
    598                         {
    599                             HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits);
    600                             *p = nfc_hal_cb.max_rf_credits;
    601                         }
    602                     }
    603                 }
    604             }
    605         }
    606 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    607         else if (gid == NCI_GID_CORE)
    608         {
    609             if (mt == NCI_MT_RSP)
    610             {
    611                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    612                 {
    613                     if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp)
    614                     {
    615                         p++; /* skip status byte */
    616                         nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    617                         p++; /* skip buff size */
    618                         p++; /* num of buffers */
    619                         nfc_hal_cb.hci_cb.hcp_conn_id = *p;
    620                     }
    621                 }
    622             }
    623         }
    624 #endif
    625     }
    626 
    627     if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL)
    628     {
    629         if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE)
    630         {
    631             /* extend idle timer */
    632             nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT);
    633         }
    634     }
    635 
    636     return (TRUE);
    637 }
    638 
    639 /*******************************************************************************
    640 **
    641 ** Function         nfc_hal_nci_add_nfc_pkt_type
    642 **
    643 ** Description      Add packet type (HCIT_TYPE_NFC)
    644 **
    645 ** Returns          TRUE, if NFCC can receive NCI message
    646 **
    647 *******************************************************************************/
    648 void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg)
    649 {
    650     UINT8   *p;
    651     UINT8   hcit;
    652 
    653     /* add packet type in front of NCI header */
    654     if (p_msg->offset > 0)
    655     {
    656         p_msg->offset--;
    657         p_msg->len++;
    658 
    659         p  = (UINT8 *) (p_msg + 1) + p_msg->offset;
    660         *p = HCIT_TYPE_NFC;
    661     }
    662     else
    663     {
    664         HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type");
    665         hcit = HCIT_TYPE_NFC;
    666         USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1);
    667     }
    668 }
    669 
    670 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    671 /*******************************************************************************
    672 **
    673 ** Function         nci_brcm_check_cmd_create_hcp_connection
    674 **
    675 ** Description      Check if this is command to create HCP connection
    676 **
    677 ** Returns          None
    678 **
    679 *******************************************************************************/
    680 static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg)
    681 {
    682     UINT8 *p;
    683     UINT8 mt, pbf, gid, op_code;
    684 
    685     nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE;
    686 
    687     p = (UINT8 *) (p_msg + 1) + p_msg->offset;
    688 
    689     if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE)
    690     {
    691         NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
    692         NCI_MSG_PRS_HDR1 (p, op_code);
    693 
    694         if (gid == NCI_GID_CORE)
    695         {
    696             if (mt == NCI_MT_CMD)
    697             {
    698                 if (op_code == NCI_MSG_CORE_CONN_CREATE)
    699                 {
    700                     if (  ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++)
    701                         &&(NCI_DEST_TYPE_NFCEE == *p++)
    702                         &&(1 == *p++)
    703                         &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++)
    704                         &&(2 == *p++)  )
    705                     {
    706                         p++;
    707                         if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p)
    708                         {
    709                             nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE;
    710                             return;
    711                         }
    712                     }
    713 
    714                 }
    715             }
    716         }
    717     }
    718 }
    719 
    720 #endif
    721 
    722 /*******************************************************************************
    723 **
    724 ** Function         nfc_hal_nci_send_cmd
    725 **
    726 ** Description      Send NCI command to the transport
    727 **
    728 ** Returns          void
    729 **
    730 *******************************************************************************/
    731 void nfc_hal_nci_send_cmd (NFC_HDR *p_buf)
    732 {
    733     BOOLEAN continue_to_process = TRUE;
    734     UINT8   *ps, *pd;
    735     UINT16  max_len;
    736     UINT16  buf_len, offset;
    737     UINT8   *p;
    738     UINT8   hdr[NCI_MSG_HDR_SIZE];
    739     UINT8   nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size;
    740     UINT8   delta = 0;
    741 
    742 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE))
    743     if (  (nfc_hal_cb.hci_cb.hcp_conn_id == 0)
    744         &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE)  )
    745         nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf);
    746 #endif
    747 
    748     /* check low power mode state */
    749     continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT);
    750 
    751     if (!continue_to_process)
    752     {
    753         /* save the command to be sent until NFCC is free. */
    754         nfc_hal_cb.ncit_cb.p_pend_cmd   = p_buf;
    755         return;
    756     }
    757 
    758     max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE;
    759     buf_len = p_buf->len;
    760     offset  = p_buf->offset;
    761 #ifdef DISP_NCI
    762     if (buf_len > max_len)
    763     {
    764         /* this command needs to be fragmented. display the complete packet first */
    765         DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE);
    766     }
    767 #endif
    768     ps      = (UINT8 *) (p_buf + 1) + p_buf->offset;
    769     memcpy (hdr, ps, NCI_MSG_HDR_SIZE);
    770     while (buf_len > max_len)
    771     {
    772         HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len);
    773         /* the NCI command is bigger than the NFCC Max Control Packet Payload Length
    774          * fragment the command */
    775 
    776         p_buf->len  = max_len;
    777         ps   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    778         /* mark the control packet as fragmented */
    779         *ps |= NCI_PBF_ST_CONT;
    780         /* adjust the length of this fragment */
    781         ps  += 2;
    782         *ps  = nci_ctrl_size;
    783 
    784         /* add NCI packet type in front of message */
    785         nfc_hal_nci_add_nfc_pkt_type (p_buf);
    786 
    787         /* send this fragment to transport */
    788         p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    789 
    790 #ifdef DISP_NCI
    791         delta = p_buf->len - max_len;
    792         DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    793 #endif
    794         USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    795 
    796         /* adjust the len and offset to reflect that part of the command is already sent */
    797         buf_len -= nci_ctrl_size;
    798         offset  += nci_ctrl_size;
    799         HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len);
    800         p_buf->len      = buf_len;
    801         p_buf->offset   = offset;
    802         pd   = (UINT8 *) (p_buf + 1) + p_buf->offset;
    803         /* restore the NCI header */
    804         memcpy (pd, hdr, NCI_MSG_HDR_SIZE);
    805         pd  += 2;
    806         *pd  = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE);
    807     }
    808 
    809     HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len);
    810 
    811     /* add NCI packet type in front of message */
    812     nfc_hal_nci_add_nfc_pkt_type (p_buf);
    813 
    814     /* send this fragment to transport */
    815     p = (UINT8 *) (p_buf + 1) + p_buf->offset;
    816 
    817 #ifdef DISP_NCI
    818     delta = p_buf->len - buf_len;
    819     DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE);
    820 #endif
    821     USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len);
    822 
    823     GKI_freebuf (p_buf);
    824 }
    825 
    826 /*******************************************************************************
    827 **
    828 ** Function         nfc_hal_nci_cmd_timeout_cback
    829 **
    830 ** Description      callback function for timeout
    831 **
    832 ** Returns          void
    833 **
    834 *******************************************************************************/
    835 void nfc_hal_nci_cmd_timeout_cback (void *p_tle)
    836 {
    837     TIMER_LIST_ENT  *p_tlent = (TIMER_LIST_ENT *)p_tle;
    838 
    839     HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()");
    840 
    841     nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
    842 
    843     if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP)
    844     {
    845         if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO)
    846         {
    847             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    848             nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    849         }
    850         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE)
    851         {
    852             if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE)
    853             {
    854                 nfc_hal_prm_process_timeout (NULL);
    855             }
    856             else
    857             {
    858                 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    859                 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    860             }
    861         }
    862         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE)
    863         {
    864             NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
    865             nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    866         }
    867         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)
    868         {
    869             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    870             nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    871         }
    872         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE)
    873         {
    874             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
    875             nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
    876         }
    877         else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF)
    878         {
    879             nfc_hal_main_close ();
    880         }
    881     }
    882 }
    883 
    884 
    885 /*******************************************************************************
    886 **
    887 ** Function         HAL_NfcSetMaxRfDataCredits
    888 **
    889 ** Description      This function sets the maximum RF data credit for HAL.
    890 **                  If 0, use the value reported from NFCC.
    891 **
    892 ** Returns          none
    893 **
    894 *******************************************************************************/
    895 void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits)
    896 {
    897     HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits);
    898     nfc_hal_cb.max_rf_credits   = max_credits;
    899 }
    900