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