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