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*******************************************************************************/
52void 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*****************************************************************************/
179static 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*****************************************************************************/
276static 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*******************************************************************************/
392static 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*****************************************************************************/
478BOOLEAN 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*******************************************************************************/
526BOOLEAN 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*******************************************************************************/
648void 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*******************************************************************************/
680static 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*******************************************************************************/
731void 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*******************************************************************************/
835void 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*******************************************************************************/
895void 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