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 *******************************************************************************/
nfc_hal_nci_assemble_nci_msg(void)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 *****************************************************************************/
nfc_hal_nci_receive_nci_msg(tNFC_HAL_NCIT_CB * p_cb,UINT8 byte)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 *****************************************************************************/
nfc_hal_nci_receive_bt_msg(tNFC_HAL_NCIT_CB * p_cb,UINT8 byte)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 *******************************************************************************/
nfc_hal_nci_proc_rx_bt_msg(void)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 *****************************************************************************/
nfc_hal_nci_receive_msg(UINT8 byte)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 *******************************************************************************/
nfc_hal_nci_preproc_rx_nci_msg(NFC_HDR * p_msg)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 *******************************************************************************/
nfc_hal_nci_add_nfc_pkt_type(NFC_HDR * p_msg)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 *******************************************************************************/
nci_brcm_check_cmd_create_hcp_connection(NFC_HDR * p_msg)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 *******************************************************************************/
nfc_hal_nci_send_cmd(NFC_HDR * p_buf)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 *******************************************************************************/
nfc_hal_nci_cmd_timeout_cback(void * p_tle)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 *******************************************************************************/
HAL_NfcSetMaxRfDataCredits(UINT8 max_credits)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