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 *******************************************************************************/ 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 *****************************************************************************/ 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 *****************************************************************************/ 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 *******************************************************************************/ 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 *****************************************************************************/ 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 *******************************************************************************/ 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 initializing BRCM NFCC */ 539 if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE) 540 { 541 nfc_hal_dm_proc_msg_during_init (p_msg); 542 /* do not send message to NFC task while initializing NFCC */ 543 return (FALSE); 544 } 545 else 546 { 547 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 548 pp = p; 549 NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); 550 NCI_MSG_PRS_HDR1 (p, op_code); 551 payload_len = *p++; 552 553 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) 554 if (mt == NCI_MT_DATA) 555 { 556 if (nfc_hal_cb.hci_cb.hcp_conn_id) 557 { 558 NCI_DATA_PRS_HDR(pp, pbf, cid, data_len); 559 if (cid == nfc_hal_cb.hci_cb.hcp_conn_id) 560 { 561 nfc_hal_hci_handle_hcp_pkt_from_hc (pp); 562 } 563 564 } 565 } 566 567 if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */ 568 { 569 if (mt == NCI_MT_NTF) 570 { 571 if (op_code == NCI_MSG_HCI_NETWK) 572 { 573 nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset); 574 } 575 } 576 } 577 else 578 #endif 579 if (gid == NCI_GID_RF_MANAGE) 580 { 581 if (mt == NCI_MT_NTF) 582 { 583 if (op_code == NCI_MSG_RF_INTF_ACTIVATED) 584 { 585 if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5)) 586 { 587 /* API used wants to limit the RF data credits */ 588 p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */ 589 if (*p > nfc_hal_cb.max_rf_credits) 590 { 591 HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits); 592 *p = nfc_hal_cb.max_rf_credits; 593 } 594 } 595 } 596 } 597 } 598 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) 599 else if (gid == NCI_GID_CORE) 600 { 601 if (mt == NCI_MT_RSP) 602 { 603 if (op_code == NCI_MSG_CORE_CONN_CREATE) 604 { 605 if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp) 606 { 607 p++; /* skip status byte */ 608 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; 609 p++; /* skip buff size */ 610 p++; /* num of buffers */ 611 nfc_hal_cb.hci_cb.hcp_conn_id = *p; 612 } 613 } 614 } 615 } 616 #endif 617 } 618 619 if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) 620 { 621 if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) 622 { 623 /* extend idle timer */ 624 nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT); 625 } 626 } 627 628 return (TRUE); 629 } 630 631 /******************************************************************************* 632 ** 633 ** Function nfc_hal_nci_add_nfc_pkt_type 634 ** 635 ** Description Add packet type (HCIT_TYPE_NFC) 636 ** 637 ** Returns TRUE, if NFCC can receive NCI message 638 ** 639 *******************************************************************************/ 640 void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg) 641 { 642 UINT8 *p; 643 UINT8 hcit; 644 645 /* add packet type in front of NCI header */ 646 if (p_msg->offset > 0) 647 { 648 p_msg->offset--; 649 p_msg->len++; 650 651 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 652 *p = HCIT_TYPE_NFC; 653 } 654 else 655 { 656 HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type"); 657 hcit = HCIT_TYPE_NFC; 658 USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1); 659 } 660 } 661 662 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) 663 /******************************************************************************* 664 ** 665 ** Function nci_brcm_check_cmd_create_hcp_connection 666 ** 667 ** Description Check if this is command to create HCP connection 668 ** 669 ** Returns None 670 ** 671 *******************************************************************************/ 672 static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg) 673 { 674 UINT8 *p; 675 UINT8 mt, pbf, gid, op_code; 676 677 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; 678 679 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 680 681 if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) 682 { 683 NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); 684 NCI_MSG_PRS_HDR1 (p, op_code); 685 686 if (gid == NCI_GID_CORE) 687 { 688 if (mt == NCI_MT_CMD) 689 { 690 if (op_code == NCI_MSG_CORE_CONN_CREATE) 691 { 692 if ( ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++) 693 &&(NCI_DEST_TYPE_NFCEE == *p++) 694 &&(1 == *p++) 695 &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++) 696 &&(2 == *p++) ) 697 { 698 p++; 699 if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p) 700 { 701 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE; 702 return; 703 } 704 } 705 706 } 707 } 708 } 709 } 710 } 711 712 #endif 713 714 /******************************************************************************* 715 ** 716 ** Function nfc_hal_nci_send_cmd 717 ** 718 ** Description Send NCI command to the transport 719 ** 720 ** Returns void 721 ** 722 *******************************************************************************/ 723 void nfc_hal_nci_send_cmd (NFC_HDR *p_buf) 724 { 725 BOOLEAN continue_to_process = TRUE; 726 UINT8 *ps, *pd; 727 UINT16 max_len; 728 UINT16 buf_len, offset; 729 UINT8 *p; 730 UINT8 hdr[NCI_MSG_HDR_SIZE]; 731 UINT8 nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size; 732 UINT8 delta = 0; 733 734 #if (defined(NFC_HAL_HCI_INCLUDED) && (NFC_HAL_HCI_INCLUDED == TRUE)) 735 if ( (nfc_hal_cb.hci_cb.hcp_conn_id == 0) 736 &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE) ) 737 nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf); 738 #endif 739 740 /* check low power mode state */ 741 continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT); 742 743 if (!continue_to_process) 744 { 745 /* save the command to be sent until NFCC is free. */ 746 nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf; 747 return; 748 } 749 750 max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE; 751 buf_len = p_buf->len; 752 offset = p_buf->offset; 753 #ifdef DISP_NCI 754 if (buf_len > max_len) 755 { 756 /* this command needs to be fragmented. display the complete packet first */ 757 DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE); 758 } 759 #endif 760 ps = (UINT8 *) (p_buf + 1) + p_buf->offset; 761 memcpy (hdr, ps, NCI_MSG_HDR_SIZE); 762 while (buf_len > max_len) 763 { 764 HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len); 765 /* the NCI command is bigger than the NFCC Max Control Packet Payload Length 766 * fragment the command */ 767 768 p_buf->len = max_len; 769 ps = (UINT8 *) (p_buf + 1) + p_buf->offset; 770 /* mark the control packet as fragmented */ 771 *ps |= NCI_PBF_ST_CONT; 772 /* adjust the length of this fragment */ 773 ps += 2; 774 *ps = nci_ctrl_size; 775 776 /* add NCI packet type in front of message */ 777 nfc_hal_nci_add_nfc_pkt_type (p_buf); 778 779 /* send this fragment to transport */ 780 p = (UINT8 *) (p_buf + 1) + p_buf->offset; 781 782 #ifdef DISP_NCI 783 delta = p_buf->len - max_len; 784 DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); 785 #endif 786 USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); 787 788 /* adjust the len and offset to reflect that part of the command is already sent */ 789 buf_len -= nci_ctrl_size; 790 offset += nci_ctrl_size; 791 HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len); 792 p_buf->len = buf_len; 793 p_buf->offset = offset; 794 pd = (UINT8 *) (p_buf + 1) + p_buf->offset; 795 /* restore the NCI header */ 796 memcpy (pd, hdr, NCI_MSG_HDR_SIZE); 797 pd += 2; 798 *pd = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE); 799 } 800 801 HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len); 802 803 /* add NCI packet type in front of message */ 804 nfc_hal_nci_add_nfc_pkt_type (p_buf); 805 806 /* send this fragment to transport */ 807 p = (UINT8 *) (p_buf + 1) + p_buf->offset; 808 809 #ifdef DISP_NCI 810 delta = p_buf->len - buf_len; 811 DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); 812 #endif 813 USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); 814 815 GKI_freebuf (p_buf); 816 } 817 818 /******************************************************************************* 819 ** 820 ** Function nfc_hal_nci_cmd_timeout_cback 821 ** 822 ** Description callback function for timeout 823 ** 824 ** Returns void 825 ** 826 *******************************************************************************/ 827 void nfc_hal_nci_cmd_timeout_cback (void *p_tle) 828 { 829 TIMER_LIST_ENT *p_tlent = (TIMER_LIST_ENT *)p_tle; 830 831 HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()"); 832 833 nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; 834 835 if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP) 836 { 837 if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO) 838 { 839 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 840 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 841 } 842 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) 843 { 844 if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE) 845 { 846 nfc_hal_prm_process_timeout (NULL); 847 } 848 else 849 { 850 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 851 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 852 } 853 } 854 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE) 855 { 856 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 857 nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 858 } 859 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE) 860 { 861 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); 862 nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 863 } 864 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE) 865 { 866 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); 867 nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 868 } 869 } 870 } 871 872 873 /******************************************************************************* 874 ** 875 ** Function HAL_NfcSetMaxRfDataCredits 876 ** 877 ** Description This function sets the maximum RF data credit for HAL. 878 ** If 0, use the value reported from NFCC. 879 ** 880 ** Returns none 881 ** 882 *******************************************************************************/ 883 void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits) 884 { 885 HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits); 886 nfc_hal_cb.max_rf_credits = max_credits; 887 } 888