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