1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19/****************************************************************************** 20 * 21 * This file contains function of the NFC unit to receive/process NCI 22 * commands. 23 * 24 ******************************************************************************/ 25#include <string.h> 26#include "bt_types.h" 27#include "gki.h" 28#include "nfc_target.h" 29 30#include "nci_defs.h" 31#include "nci_hmsgs.h" 32#include "nfc_api.h" 33#include "nfc_int.h" 34 35/******************************************************************************* 36** 37** Function nci_proc_core_rsp 38** 39** Description Process NCI responses in the CORE group 40** 41** Returns TRUE-caller of this function to free the GKI buffer p_msg 42** 43*******************************************************************************/ 44bool nci_proc_core_rsp(NFC_HDR* p_msg) { 45 uint8_t* p; 46 uint8_t *pp, len, op_code; 47 bool free = true; 48 uint8_t* p_old = nfc_cb.last_cmd; 49 50 /* find the start of the NCI message and parse the NCI header */ 51 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 52 pp = p + 1; 53 NCI_MSG_PRS_HDR1(pp, op_code); 54 NFC_TRACE_DEBUG1("nci_proc_core_rsp opcode:0x%x", op_code); 55 len = *pp++; 56 57 /* process the message based on the opcode and message type */ 58 switch (op_code) { 59 case NCI_MSG_CORE_RESET: 60 nfc_ncif_proc_reset_rsp(pp, false); 61 break; 62 63 case NCI_MSG_CORE_INIT: 64 nfc_ncif_proc_init_rsp(p_msg); 65 free = false; 66 break; 67 68 case NCI_MSG_CORE_GET_CONFIG: 69 nfc_ncif_proc_get_config_rsp(p_msg); 70 break; 71 72 case NCI_MSG_CORE_SET_CONFIG: 73 nfc_ncif_set_config_status(pp, len); 74 break; 75 76 case NCI_MSG_CORE_CONN_CREATE: 77 nfc_ncif_proc_conn_create_rsp(p, p_msg->len, *p_old); 78 break; 79 80 case NCI_MSG_CORE_CONN_CLOSE: 81 nfc_ncif_report_conn_close_evt(*p_old, *pp); 82 break; 83 84 default: 85 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 86 break; 87 } 88 89 return free; 90} 91 92/******************************************************************************* 93** 94** Function nci_proc_core_ntf 95** 96** Description Process NCI notifications in the CORE group 97** 98** Returns void 99** 100*******************************************************************************/ 101void nci_proc_core_ntf(NFC_HDR* p_msg) { 102 uint8_t* p; 103 uint8_t *pp, len, op_code; 104 uint8_t conn_id; 105 106 /* find the start of the NCI message and parse the NCI header */ 107 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 108 pp = p + 1; 109 NCI_MSG_PRS_HDR1(pp, op_code); 110 NFC_TRACE_DEBUG1("nci_proc_core_ntf opcode:0x%x", op_code); 111 len = *pp++; 112 113 /* process the message based on the opcode and message type */ 114 switch (op_code) { 115 case NCI_MSG_CORE_RESET: 116 nfc_ncif_proc_reset_rsp(pp, true); 117 break; 118 119 case NCI_MSG_CORE_GEN_ERR_STATUS: 120 /* process the error ntf */ 121 /* in case of timeout: notify the static connection callback */ 122 nfc_ncif_event_status(NFC_GEN_ERROR_REVT, *pp); 123 nfc_ncif_error_status(NFC_RF_CONN_ID, *pp); 124 break; 125 126 case NCI_MSG_CORE_INTF_ERR_STATUS: 127 conn_id = *(pp + 1); 128 nfc_ncif_error_status(conn_id, *pp); 129 break; 130 131 case NCI_MSG_CORE_CONN_CREDITS: 132 nfc_ncif_proc_credits(pp, len); 133 break; 134 135 default: 136 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 137 break; 138 } 139} 140 141/******************************************************************************* 142** 143** Function nci_proc_rf_management_rsp 144** 145** Description Process NCI responses in the RF Management group 146** 147** Returns void 148** 149*******************************************************************************/ 150void nci_proc_rf_management_rsp(NFC_HDR* p_msg) { 151 uint8_t* p; 152 uint8_t *pp, len, op_code; 153 uint8_t* p_old = nfc_cb.last_cmd; 154 155 /* find the start of the NCI message and parse the NCI header */ 156 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 157 pp = p + 1; 158 NCI_MSG_PRS_HDR1(pp, op_code); 159 len = *pp++; 160 161 switch (op_code) { 162 case NCI_MSG_RF_DISCOVER: 163 nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_RSP); 164 nfc_ncif_rf_management_status(NFC_START_DEVT, *pp); 165 break; 166 167 case NCI_MSG_RF_DISCOVER_SELECT: 168 nfc_ncif_rf_management_status(NFC_SELECT_DEVT, *pp); 169 break; 170 171 case NCI_MSG_RF_T3T_POLLING: 172 break; 173 174 case NCI_MSG_RF_DISCOVER_MAP: 175 nfc_ncif_rf_management_status(NFC_MAP_DEVT, *pp); 176 break; 177 178 case NCI_MSG_RF_DEACTIVATE: 179 if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_RSP) == false) { 180 return; 181 } 182 nfc_ncif_proc_deactivate(*pp, *p_old, false); 183 break; 184 185#if (NFC_NFCEE_INCLUDED == TRUE) 186#if (NFC_RW_ONLY == FALSE) 187 188 case NCI_MSG_RF_SET_ROUTING: 189 nfc_ncif_event_status(NFC_SET_ROUTING_REVT, *pp); 190 break; 191 192 case NCI_MSG_RF_GET_ROUTING: 193 if (*pp != NFC_STATUS_OK) 194 nfc_ncif_event_status(NFC_GET_ROUTING_REVT, *pp); 195 break; 196#endif 197#endif 198 199 case NCI_MSG_RF_PARAMETER_UPDATE: 200 nfc_ncif_event_status(NFC_RF_COMM_PARAMS_UPDATE_REVT, *pp); 201 break; 202 203 default: 204 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 205 break; 206 } 207} 208 209/******************************************************************************* 210** 211** Function nci_proc_rf_management_ntf 212** 213** Description Process NCI notifications in the RF Management group 214** 215** Returns void 216** 217*******************************************************************************/ 218void nci_proc_rf_management_ntf(NFC_HDR* p_msg) { 219 uint8_t* p; 220 uint8_t *pp, len, op_code; 221 222 /* find the start of the NCI message and parse the NCI header */ 223 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 224 pp = p + 1; 225 NCI_MSG_PRS_HDR1(pp, op_code); 226 len = *pp++; 227 228 switch (op_code) { 229 case NCI_MSG_RF_DISCOVER: 230 nfc_ncif_proc_discover_ntf(p, p_msg->len); 231 break; 232 233 case NCI_MSG_RF_DEACTIVATE: 234 if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_NTF) == false) { 235 return; 236 } 237 nfc_ncif_proc_deactivate(NFC_STATUS_OK, *pp, true); 238 break; 239 240 case NCI_MSG_RF_INTF_ACTIVATED: 241 if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_NTF) == false) { 242 return; 243 } 244 nfc_ncif_proc_activate(pp, len); 245 break; 246 247 case NCI_MSG_RF_FIELD: 248 nfc_ncif_proc_rf_field_ntf(*pp); 249 break; 250 251 case NCI_MSG_RF_T3T_POLLING: 252 nfc_ncif_proc_t3t_polling_ntf(pp, len); 253 break; 254 255#if (NFC_NFCEE_INCLUDED == TRUE) 256#if (NFC_RW_ONLY == FALSE) 257 258 case NCI_MSG_RF_GET_ROUTING: 259 nfc_ncif_proc_get_routing(pp, len); 260 break; 261 262 case NCI_MSG_RF_EE_ACTION: 263 nfc_ncif_proc_ee_action(pp, len); 264 break; 265 266 case NCI_MSG_RF_EE_DISCOVERY_REQ: 267 nfc_ncif_proc_ee_discover_req(pp, len); 268 break; 269#endif 270#endif 271 272 default: 273 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 274 break; 275 } 276} 277 278#if (NFC_NFCEE_INCLUDED == TRUE) 279#if (NFC_RW_ONLY == FALSE) 280 281/******************************************************************************* 282** 283** Function nci_proc_ee_management_rsp 284** 285** Description Process NCI responses in the NFCEE Management group 286** 287** Returns void 288** 289*******************************************************************************/ 290void nci_proc_ee_management_rsp(NFC_HDR* p_msg) { 291 uint8_t* p; 292 uint8_t *pp, len, op_code; 293 tNFC_RESPONSE_CBACK* p_cback = nfc_cb.p_resp_cback; 294 tNFC_NFCEE_DISCOVER_REVT nfcee_discover; 295 tNFC_NFCEE_INFO_REVT nfcee_info; 296 tNFC_NFCEE_MODE_SET_REVT mode_set; 297 tNFC_RESPONSE* p_evt = (tNFC_RESPONSE*)&nfcee_info; 298 tNFC_RESPONSE_EVT event = NFC_NFCEE_INFO_REVT; 299 uint8_t* p_old = nfc_cb.last_cmd; 300 301 /* find the start of the NCI message and parse the NCI header */ 302 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 303 pp = p + 1; 304 NCI_MSG_PRS_HDR1(pp, op_code); 305 NFC_TRACE_DEBUG1("nci_proc_ee_management_rsp opcode:0x%x", op_code); 306 len = *pp++; 307 308 switch (op_code) { 309 case NCI_MSG_NFCEE_DISCOVER: 310 p_evt = (tNFC_RESPONSE*)&nfcee_discover; 311 nfcee_discover.status = *pp++; 312 nfcee_discover.num_nfcee = *pp++; 313 314 if (nfcee_discover.status != NFC_STATUS_OK) nfcee_discover.num_nfcee = 0; 315 316 event = NFC_NFCEE_DISCOVER_REVT; 317 break; 318 319 case NCI_MSG_NFCEE_MODE_SET: 320 p_evt = (tNFC_RESPONSE*)&mode_set; 321 mode_set.status = *pp; 322 mode_set.nfcee_id = 0; 323 event = NFC_NFCEE_MODE_SET_REVT; 324 mode_set.nfcee_id = *p_old++; 325 mode_set.mode = *p_old++; 326 break; 327 328 default: 329 p_cback = NULL; 330 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 331 break; 332 } 333 334 if (p_cback) (*p_cback)(event, p_evt); 335} 336 337/******************************************************************************* 338** 339** Function nci_proc_ee_management_ntf 340** 341** Description Process NCI notifications in the NFCEE Management group 342** 343** Returns void 344** 345*******************************************************************************/ 346void nci_proc_ee_management_ntf(NFC_HDR* p_msg) { 347 uint8_t* p; 348 uint8_t *pp, len, op_code; 349 tNFC_RESPONSE_CBACK* p_cback = nfc_cb.p_resp_cback; 350 tNFC_NFCEE_INFO_REVT nfcee_info; 351 tNFC_RESPONSE* p_evt = (tNFC_RESPONSE*)&nfcee_info; 352 tNFC_RESPONSE_EVT event = NFC_NFCEE_INFO_REVT; 353 uint8_t xx; 354 uint8_t yy; 355 uint8_t ee_status; 356 tNFC_NFCEE_TLV* p_tlv; 357 358 /* find the start of the NCI message and parse the NCI header */ 359 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 360 pp = p + 1; 361 NCI_MSG_PRS_HDR1(pp, op_code); 362 NFC_TRACE_DEBUG1("nci_proc_ee_management_ntf opcode:0x%x", op_code); 363 len = *pp++; 364 365 if (op_code == NCI_MSG_NFCEE_DISCOVER) { 366 nfcee_info.nfcee_id = *pp++; 367 ee_status = *pp++; 368 369 nfcee_info.ee_status = ee_status; 370 yy = *pp; 371 nfcee_info.num_interface = *pp++; 372 p = pp; 373 374 if (nfcee_info.num_interface > NFC_MAX_EE_INTERFACE) 375 nfcee_info.num_interface = NFC_MAX_EE_INTERFACE; 376 377 for (xx = 0; xx < nfcee_info.num_interface; xx++) { 378 nfcee_info.ee_interface[xx] = *pp++; 379 } 380 381 pp = p + yy; 382 nfcee_info.num_tlvs = *pp++; 383 NFC_TRACE_DEBUG4("nfcee_id: 0x%x num_interface:0x%x/0x%x, num_tlvs:0x%x", 384 nfcee_info.nfcee_id, nfcee_info.num_interface, yy, 385 nfcee_info.num_tlvs); 386 387 if (nfcee_info.num_tlvs > NFC_MAX_EE_TLVS) 388 nfcee_info.num_tlvs = NFC_MAX_EE_TLVS; 389 390 p_tlv = &nfcee_info.ee_tlv[0]; 391 392 for (xx = 0; xx < nfcee_info.num_tlvs; xx++, p_tlv++) { 393 p_tlv->tag = *pp++; 394 p_tlv->len = yy = *pp++; 395 NFC_TRACE_DEBUG2("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len); 396 if (p_tlv->len > NFC_MAX_EE_INFO) p_tlv->len = NFC_MAX_EE_INFO; 397 p = pp; 398 STREAM_TO_ARRAY(p_tlv->info, pp, p_tlv->len); 399 pp = p += yy; 400 } 401 } else { 402 p_cback = NULL; 403 NFC_TRACE_ERROR1("unknown opcode:0x%x", op_code); 404 } 405 406 if (p_cback) (*p_cback)(event, p_evt); 407} 408 409#endif 410#endif 411 412/******************************************************************************* 413** 414** Function nci_proc_prop_rsp 415** 416** Description Process NCI responses in the Proprietary group 417** 418** Returns void 419** 420*******************************************************************************/ 421void nci_proc_prop_rsp(NFC_HDR* p_msg) { 422 uint8_t* p; 423 uint8_t* p_evt; 424 uint8_t *pp, len, op_code; 425 tNFC_VS_CBACK* p_cback = (tNFC_VS_CBACK*)nfc_cb.p_vsc_cback; 426 427 /* find the start of the NCI message and parse the NCI header */ 428 p = p_evt = (uint8_t*)(p_msg + 1) + p_msg->offset; 429 pp = p + 1; 430 NCI_MSG_PRS_HDR1(pp, op_code); 431 len = *pp++; 432 433 /*If there's a pending/stored command, restore the associated address of the 434 * callback function */ 435 if (p_cback) 436 (*p_cback)((tNFC_VS_EVT)(NCI_RSP_BIT | op_code), p_msg->len, p_evt); 437} 438 439/******************************************************************************* 440** 441** Function nci_proc_prop_ntf 442** 443** Description Process NCI notifications in the Proprietary group 444** 445** Returns void 446** 447*******************************************************************************/ 448void nci_proc_prop_ntf(NFC_HDR* p_msg) { 449 uint8_t* p; 450 uint8_t* p_evt; 451 uint8_t *pp, len, op_code; 452 int i; 453 454 /* find the start of the NCI message and parse the NCI header */ 455 p = p_evt = (uint8_t*)(p_msg + 1) + p_msg->offset; 456 pp = p + 1; 457 NCI_MSG_PRS_HDR1(pp, op_code); 458 len = *pp++; 459 460 for (i = 0; i < NFC_NUM_VS_CBACKS; i++) { 461 if (nfc_cb.p_vs_cb[i]) { 462 (*nfc_cb.p_vs_cb[i])((tNFC_VS_EVT)(NCI_NTF_BIT | op_code), p_msg->len, 463 p_evt); 464 } 465 } 466} 467