1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-2013 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 ((sizeof (NFC_HDR) + HCIE_PREAMBLE_SIZE + byte) > GKI_get_buf_size (p_cb->p_rcv_msg)) 320 { 321 /* Message cannot fit into buffer */ 322 GKI_freebuf (p_cb->p_rcv_msg); 323 p_cb->p_rcv_msg = NULL; 324 325 HAL_TRACE_ERROR0 ("Invalid length for incoming BT HCI message."); 326 } 327 328 /* Message length is valid */ 329 if (byte) 330 { 331 /* Read rest of message */ 332 p_cb->rcv_state = NFC_HAL_RCV_BT_PAYLOAD_ST; 333 } 334 else 335 { 336 /* Message has no additional parameters. (Entire message has been received) */ 337 msg_received = TRUE; 338 p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; /* Next, wait for packet type of next message */ 339 } 340 } 341 break; 342 343 case NFC_HAL_RCV_BT_PAYLOAD_ST: 344 p_cb->rcv_len--; 345 if (p_cb->p_rcv_msg) 346 { 347 *((UINT8 *) (p_cb->p_rcv_msg + 1) + p_cb->p_rcv_msg->offset + p_cb->p_rcv_msg->len++) = byte; 348 349 if (p_cb->rcv_len > 0) 350 { 351 /* Read in the rest of the message */ 352 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); 353 p_cb->p_rcv_msg->len += len; 354 p_cb->rcv_len -= len; 355 } 356 } 357 358 /* Check if we read in entire message yet */ 359 if (p_cb->rcv_len == 0) 360 { 361 msg_received = TRUE; 362 p_cb->rcv_state = NFC_HAL_RCV_IDLE_ST; /* Next, wait for packet type of next message */ 363 } 364 break; 365 } 366 367 /* If we received entire message */ 368 #if (NFC_HAL_TRACE_PROTOCOL == TRUE) 369 if (msg_received && p_cb->p_rcv_msg) 370 { 371 /* Display protocol trace message */ 372 DispHciEvt (p_cb->p_rcv_msg); 373 } 374 #endif 375 376 return (msg_received); 377 } 378 379 /******************************************************************************* 380 ** 381 ** Function nfc_hal_nci_proc_rx_bt_msg 382 ** 383 ** Description Received BT message from NFCC 384 ** 385 ** Notify command complete if initializing NFCC 386 ** Forward BT message to NFC task 387 ** 388 ** Returns void 389 ** 390 *******************************************************************************/ 391 static void nfc_hal_nci_proc_rx_bt_msg (void) 392 { 393 UINT8 *p; 394 NFC_HDR *p_msg; 395 UINT16 opcode, old_opcode; 396 tNFC_HAL_BTVSC_CPLT vcs_cplt_params; 397 tNFC_HAL_BTVSC_CPLT_CBACK *p_cback = NULL; 398 399 /* if complete BT message is received successfully */ 400 if (nfc_hal_cb.ncit_cb.p_rcv_msg) 401 { 402 p_msg = nfc_hal_cb.ncit_cb.p_rcv_msg; 403 HAL_TRACE_DEBUG1 ("nfc_hal_nci_proc_rx_bt_msg (): GOT an BT msgs init_sta:%d", nfc_hal_cb.dev_cb.initializing_state); 404 HAL_TRACE_DEBUG2 ("event: 0x%x, wait_rsp:0x%x", p_msg->event, nfc_hal_cb.ncit_cb.nci_wait_rsp); 405 /* increase the cmd window here */ 406 if (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_PROP) 407 { 408 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 409 if (*p == HCI_COMMAND_COMPLETE_EVT) 410 { 411 p += 3; /* code, len, cmd window */ 412 STREAM_TO_UINT16 (opcode, p); 413 p = nfc_hal_cb.ncit_cb.last_hdr; 414 STREAM_TO_UINT16 (old_opcode, p); 415 if (opcode == old_opcode) 416 { 417 nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; 418 p_cback = (tNFC_HAL_BTVSC_CPLT_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback; 419 nfc_hal_cb.ncit_cb.p_vsc_cback = NULL; 420 nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer); 421 } 422 } 423 } 424 425 /* if initializing BRCM NFCC */ 426 if ((nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) || 427 (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE)) 428 { 429 /* this is command complete event for baud rate update or download patch */ 430 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 431 432 p += 1; /* skip opcode */ 433 STREAM_TO_UINT8 (vcs_cplt_params.param_len, p); 434 435 p += 1; /* skip num command packets */ 436 STREAM_TO_UINT16 (vcs_cplt_params.opcode, p); 437 438 vcs_cplt_params.param_len -= 3; 439 vcs_cplt_params.p_param_buf = p; 440 441 if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE) 442 { 443 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); 444 nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_OK); 445 } 446 if (p_cback) 447 { 448 nfc_hal_cb.ncit_cb.p_vsc_cback = NULL; 449 (*p_cback) (&vcs_cplt_params); 450 } 451 452 /* do not BT send message to NFC task */ 453 GKI_freebuf (p_msg); 454 } 455 else 456 { 457 /* do not BT send message to NFC task */ 458 GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); 459 } 460 nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; 461 } 462 } 463 464 /***************************************************************************** 465 ** 466 ** Function nfc_hal_nci_receive_msg 467 ** 468 ** Description 469 ** Handle incoming data (NCI events) from the serial port. 470 ** 471 ** If there is data waiting from the serial port, this funciton reads the 472 ** data and parses it. Once an entire NCI message has been read, it sends 473 ** the message the the NFC_TASK for processing 474 ** 475 *****************************************************************************/ 476 BOOLEAN nfc_hal_nci_receive_msg (UINT8 byte) 477 { 478 tNFC_HAL_NCIT_CB *p_cb = &(nfc_hal_cb.ncit_cb); 479 BOOLEAN msg_received = FALSE; 480 481 if (p_cb->rcv_state == NFC_HAL_RCV_IDLE_ST) 482 { 483 /* if this is NCI message */ 484 if (byte == HCIT_TYPE_NFC) 485 { 486 p_cb->rcv_state = NFC_HAL_RCV_NCI_MSG_ST; 487 } 488 /* if this is BT message */ 489 else if (byte == HCIT_TYPE_EVENT) 490 { 491 p_cb->rcv_state = NFC_HAL_RCV_BT_MSG_ST; 492 } 493 else 494 { 495 HAL_TRACE_ERROR1 ("Unknown packet type drop this byte 0x%x", byte); 496 } 497 } 498 else if (p_cb->rcv_state <= NFC_HAL_RCV_NCI_PAYLOAD_ST) 499 { 500 msg_received = nfc_hal_nci_receive_nci_msg (p_cb, byte); 501 } 502 else 503 { 504 if (nfc_hal_nci_receive_bt_msg (p_cb, byte)) 505 { 506 /* received BT message */ 507 nfc_hal_nci_proc_rx_bt_msg (); 508 } 509 } 510 511 return (msg_received); 512 } 513 514 /******************************************************************************* 515 ** 516 ** Function nfc_hal_nci_preproc_rx_nci_msg 517 ** 518 ** Description NFCC sends NCI message to DH while initializing NFCC 519 ** processing low power mode 520 ** 521 ** Returns TRUE, if NFC task need to receive NCI message 522 ** 523 *******************************************************************************/ 524 BOOLEAN nfc_hal_nci_preproc_rx_nci_msg (NFC_HDR *p_msg) 525 { 526 UINT8 *p, *pp, cid; 527 UINT8 mt, pbf, gid, op_code; 528 UINT8 payload_len; 529 UINT16 data_len; 530 531 HAL_TRACE_DEBUG0 ("nfc_hal_nci_preproc_rx_nci_msg()"); 532 533 /* if initializing BRCM NFCC */ 534 if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE) 535 { 536 nfc_hal_dm_proc_msg_during_init (p_msg); 537 /* do not send message to NFC task while initializing NFCC */ 538 return (FALSE); 539 } 540 else 541 { 542 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 543 pp = p; 544 NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); 545 NCI_MSG_PRS_HDR1 (p, op_code); 546 payload_len = *p++; 547 548 if (mt == NCI_MT_DATA) 549 { 550 if (nfc_hal_cb.hci_cb.hcp_conn_id) 551 { 552 NCI_DATA_PRS_HDR(pp, pbf, cid, data_len); 553 if (cid == nfc_hal_cb.hci_cb.hcp_conn_id) 554 { 555 nfc_hal_hci_handle_hcp_pkt_from_hc (pp); 556 } 557 558 } 559 } 560 561 if (gid == NCI_GID_PROP) /* this is for hci netwk ntf */ 562 { 563 if (mt == NCI_MT_NTF) 564 { 565 if (op_code == NCI_MSG_HCI_NETWK) 566 { 567 nfc_hal_hci_handle_hci_netwk_info ((UINT8 *) (p_msg + 1) + p_msg->offset); 568 } 569 } 570 } 571 else if (gid == NCI_GID_RF_MANAGE) 572 { 573 if (mt == NCI_MT_NTF) 574 { 575 if (op_code == NCI_MSG_RF_INTF_ACTIVATED) 576 { 577 if ((nfc_hal_cb.max_rf_credits) && (payload_len > 5)) 578 { 579 /* API used wants to limit the RF data credits */ 580 p += 5; /* skip RF disc id, interface, protocol, tech&mode, payload size */ 581 if (*p > nfc_hal_cb.max_rf_credits) 582 { 583 HAL_TRACE_DEBUG2 ("RfDataCredits %d->%d", *p, nfc_hal_cb.max_rf_credits); 584 *p = nfc_hal_cb.max_rf_credits; 585 } 586 } 587 } 588 } 589 } 590 else if (gid == NCI_GID_CORE) 591 { 592 if (mt == NCI_MT_RSP) 593 { 594 if (op_code == NCI_MSG_CORE_CONN_CREATE) 595 { 596 if (nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp) 597 { 598 p++; /* skip status byte */ 599 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; 600 p++; /* skip buff size */ 601 p++; /* num of buffers */ 602 nfc_hal_cb.hci_cb.hcp_conn_id = *p; 603 } 604 } 605 } 606 } 607 } 608 609 if (nfc_hal_cb.dev_cb.power_mode == NFC_HAL_POWER_MODE_FULL) 610 { 611 if (nfc_hal_cb.dev_cb.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE) 612 { 613 /* extend idle timer */ 614 nfc_hal_dm_power_mode_execute (NFC_HAL_LP_RX_DATA_EVT); 615 } 616 } 617 618 return (TRUE); 619 } 620 621 /******************************************************************************* 622 ** 623 ** Function nfc_hal_nci_add_nfc_pkt_type 624 ** 625 ** Description Add packet type (HCIT_TYPE_NFC) 626 ** 627 ** Returns TRUE, if NFCC can receive NCI message 628 ** 629 *******************************************************************************/ 630 void nfc_hal_nci_add_nfc_pkt_type (NFC_HDR *p_msg) 631 { 632 UINT8 *p; 633 UINT8 hcit; 634 635 /* add packet type in front of NCI header */ 636 if (p_msg->offset > 0) 637 { 638 p_msg->offset--; 639 p_msg->len++; 640 641 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 642 *p = HCIT_TYPE_NFC; 643 } 644 else 645 { 646 HAL_TRACE_ERROR0 ("nfc_hal_nci_add_nfc_pkt_type () : No space for packet type"); 647 hcit = HCIT_TYPE_NFC; 648 USERIAL_Write (USERIAL_NFC_PORT, &hcit, 1); 649 } 650 } 651 652 /******************************************************************************* 653 ** 654 ** Function nci_brcm_check_cmd_create_hcp_connection 655 ** 656 ** Description Check if this is command to create HCP connection 657 ** 658 ** Returns None 659 ** 660 *******************************************************************************/ 661 static void nci_brcm_check_cmd_create_hcp_connection (NFC_HDR *p_msg) 662 { 663 UINT8 *p; 664 UINT8 mt, pbf, gid, op_code; 665 666 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = FALSE; 667 668 p = (UINT8 *) (p_msg + 1) + p_msg->offset; 669 670 if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_IDLE) 671 { 672 NCI_MSG_PRS_HDR0 (p, mt, pbf, gid); 673 NCI_MSG_PRS_HDR1 (p, op_code); 674 675 if (gid == NCI_GID_CORE) 676 { 677 if (mt == NCI_MT_CMD) 678 { 679 if (op_code == NCI_MSG_CORE_CONN_CREATE) 680 { 681 if ( ((NCI_CORE_PARAM_SIZE_CON_CREATE + 4) == *p++) 682 &&(NCI_DEST_TYPE_NFCEE == *p++) 683 &&(1 == *p++) 684 &&(NCI_CON_CREATE_TAG_NFCEE_VAL == *p++) 685 &&(2 == *p++) ) 686 { 687 p++; 688 if (NCI_NFCEE_INTERFACE_HCI_ACCESS == *p) 689 { 690 nfc_hal_cb.hci_cb.b_wait_hcp_conn_create_rsp = TRUE; 691 return; 692 } 693 } 694 695 } 696 } 697 } 698 } 699 } 700 701 /******************************************************************************* 702 ** 703 ** Function nfc_hal_nci_send_cmd 704 ** 705 ** Description Send NCI command to the transport 706 ** 707 ** Returns void 708 ** 709 *******************************************************************************/ 710 void nfc_hal_nci_send_cmd (NFC_HDR *p_buf) 711 { 712 BOOLEAN continue_to_process = TRUE; 713 UINT8 *ps, *pd; 714 UINT16 max_len; 715 UINT16 buf_len, offset; 716 UINT8 *p; 717 UINT8 hdr[NCI_MSG_HDR_SIZE]; 718 UINT8 nci_ctrl_size = nfc_hal_cb.ncit_cb.nci_ctrl_size; 719 UINT8 delta = 0; 720 721 if ( (nfc_hal_cb.hci_cb.hcp_conn_id == 0) 722 &&(nfc_hal_cb.nvm_cb.nvm_type != NCI_SPD_NVM_TYPE_NONE) ) 723 nci_brcm_check_cmd_create_hcp_connection ((NFC_HDR*) p_buf); 724 725 /* check low power mode state */ 726 continue_to_process = nfc_hal_dm_power_mode_execute (NFC_HAL_LP_TX_DATA_EVT); 727 728 if (!continue_to_process) 729 { 730 /* save the command to be sent until NFCC is free. */ 731 nfc_hal_cb.ncit_cb.p_pend_cmd = p_buf; 732 return; 733 } 734 735 max_len = nci_ctrl_size + NCI_MSG_HDR_SIZE; 736 buf_len = p_buf->len; 737 offset = p_buf->offset; 738 #ifdef DISP_NCI 739 if (buf_len > max_len) 740 { 741 /* this command needs to be fragmented. display the complete packet first */ 742 DISP_NCI ((UINT8 *) (p_buf + 1) + p_buf->offset, p_buf->len, FALSE); 743 } 744 #endif 745 ps = (UINT8 *) (p_buf + 1) + p_buf->offset; 746 memcpy (hdr, ps, NCI_MSG_HDR_SIZE); 747 while (buf_len > max_len) 748 { 749 HAL_TRACE_DEBUG2 ("buf_len (%d) > max_len (%d)", buf_len, max_len); 750 /* the NCI command is bigger than the NFCC Max Control Packet Payload Length 751 * fragment the command */ 752 753 p_buf->len = max_len; 754 ps = (UINT8 *) (p_buf + 1) + p_buf->offset; 755 /* mark the control packet as fragmented */ 756 *ps |= NCI_PBF_ST_CONT; 757 /* adjust the length of this fragment */ 758 ps += 2; 759 *ps = nci_ctrl_size; 760 761 /* add NCI packet type in front of message */ 762 nfc_hal_nci_add_nfc_pkt_type (p_buf); 763 764 /* send this fragment to transport */ 765 p = (UINT8 *) (p_buf + 1) + p_buf->offset; 766 767 #ifdef DISP_NCI 768 delta = p_buf->len - max_len; 769 DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); 770 #endif 771 USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); 772 773 /* adjust the len and offset to reflect that part of the command is already sent */ 774 buf_len -= nci_ctrl_size; 775 offset += nci_ctrl_size; 776 HAL_TRACE_DEBUG2 ("p_buf->len: %d buf_len (%d)", p_buf->len, buf_len); 777 p_buf->len = buf_len; 778 p_buf->offset = offset; 779 pd = (UINT8 *) (p_buf + 1) + p_buf->offset; 780 /* restore the NCI header */ 781 memcpy (pd, hdr, NCI_MSG_HDR_SIZE); 782 pd += 2; 783 *pd = (UINT8) (p_buf->len - NCI_MSG_HDR_SIZE); 784 } 785 786 HAL_TRACE_DEBUG1 ("p_buf->len: %d", p_buf->len); 787 788 /* add NCI packet type in front of message */ 789 nfc_hal_nci_add_nfc_pkt_type (p_buf); 790 791 /* send this fragment to transport */ 792 p = (UINT8 *) (p_buf + 1) + p_buf->offset; 793 794 #ifdef DISP_NCI 795 delta = p_buf->len - buf_len; 796 DISP_NCI (p + delta, (UINT16) (p_buf->len - delta), FALSE); 797 #endif 798 USERIAL_Write (USERIAL_NFC_PORT, p, p_buf->len); 799 800 GKI_freebuf (p_buf); 801 } 802 803 /******************************************************************************* 804 ** 805 ** Function nfc_hal_nci_cmd_timeout_cback 806 ** 807 ** Description callback function for timeout 808 ** 809 ** Returns void 810 ** 811 *******************************************************************************/ 812 void nfc_hal_nci_cmd_timeout_cback (void *p_tle) 813 { 814 TIMER_LIST_ENT *p_tlent = (TIMER_LIST_ENT *)p_tle; 815 816 HAL_TRACE_DEBUG0 ("nfc_hal_nci_cmd_timeout_cback ()"); 817 818 nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE; 819 820 if (p_tlent->event == NFC_HAL_TTYPE_NCI_WAIT_RSP) 821 { 822 if (nfc_hal_cb.dev_cb.initializing_state <= NFC_HAL_INIT_STATE_W4_PATCH_INFO) 823 { 824 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 825 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 826 } 827 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_APP_COMPLETE) 828 { 829 if (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_IDLE) 830 { 831 nfc_hal_prm_process_timeout (NULL); 832 } 833 else 834 { 835 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 836 nfc_hal_main_pre_init_done (HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 837 } 838 } 839 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_POST_INIT_DONE) 840 { 841 NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE); 842 nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 843 } 844 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_CONTROL_DONE) 845 { 846 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); 847 nfc_hal_cb.p_stack_cback (HAL_NFC_RELEASE_CONTROL_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 848 } 849 else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE) 850 { 851 NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE); 852 nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT); 853 } 854 } 855 } 856 857 858 /******************************************************************************* 859 ** 860 ** Function HAL_NfcSetMaxRfDataCredits 861 ** 862 ** Description This function sets the maximum RF data credit for HAL. 863 ** If 0, use the value reported from NFCC. 864 ** 865 ** Returns none 866 ** 867 *******************************************************************************/ 868 void HAL_NfcSetMaxRfDataCredits (UINT8 max_credits) 869 { 870 HAL_TRACE_DEBUG2 ("HAL_NfcSetMaxRfDataCredits %d->%d", nfc_hal_cb.max_rf_credits, max_credits); 871 nfc_hal_cb.max_rf_credits = max_credits; 872 } 873