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