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