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