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 the implementation for Type 1 tag in Reader/Writer 22 * mode. 23 * 24 ******************************************************************************/ 25#include <string.h> 26#include "nfc_target.h" 27 28#include "gki.h" 29#include "nci_hmsgs.h" 30#include "nfc_api.h" 31#include "nfc_int.h" 32#include "rw_api.h" 33#include "rw_int.h" 34 35/* Local Functions */ 36static tRW_EVENT rw_t1t_handle_rid_rsp(NFC_HDR* p_pkt); 37static void rw_t1t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event, 38 tNFC_CONN* p_data); 39static void rw_t1t_process_frame_error(void); 40static void rw_t1t_process_error(void); 41static void rw_t1t_handle_presence_check_rsp(tNFC_STATUS status); 42#if (BT_TRACE_VERBOSE == TRUE) 43static char* rw_t1t_get_state_name(uint8_t state); 44static char* rw_t1t_get_sub_state_name(uint8_t sub_state); 45static char* rw_t1t_get_event_name(uint8_t event); 46#endif 47 48/******************************************************************************* 49** 50** Function rw_t1t_data_cback 51** 52** Description This callback function handles data from NFCC. 53** 54** Returns none 55** 56*******************************************************************************/ 57static void rw_t1t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event, 58 tNFC_CONN* p_data) { 59 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 60 tRW_EVENT rw_event = RW_RAW_FRAME_EVT; 61 bool b_notify = true; 62 tRW_DATA evt_data; 63 NFC_HDR* p_pkt; 64 uint8_t* p; 65 tT1T_CMD_RSP_INFO* p_cmd_rsp_info = 66 (tT1T_CMD_RSP_INFO*)rw_cb.tcb.t1t.p_cmd_rsp_info; 67#if (BT_TRACE_VERBOSE == TRUE) 68 uint8_t begin_state = p_t1t->state; 69#endif 70 71 p_pkt = (NFC_HDR*)(p_data->data.p_data); 72 if (p_pkt == NULL) return; 73 /* Assume the data is just the response byte sequence */ 74 p = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 75 76#if (BT_TRACE_VERBOSE == TRUE) 77 RW_TRACE_DEBUG2("rw_t1t_data_cback (): state:%s (%d)", 78 rw_t1t_get_state_name(p_t1t->state), p_t1t->state); 79#else 80 RW_TRACE_DEBUG1("rw_t1t_data_cback (): state=%d", p_t1t->state); 81#endif 82 83 evt_data.status = NFC_STATUS_OK; 84 85 if ((p_t1t->state == RW_T1T_STATE_IDLE) || (!p_cmd_rsp_info)) { 86 /* If previous command was retransmitted and if response is pending to 87 * previous command retransmission, 88 * check if lenght and ADD/ADD8/ADDS field matches the expected value of 89 * previous 90 * retransmited command response. However, ignore ADD field if the command 91 * was RALL/RID 92 */ 93 if ((p_t1t->prev_cmd_rsp_info.pend_retx_rsp) && 94 (p_t1t->prev_cmd_rsp_info.rsp_len == p_pkt->len) && 95 ((p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RID) || 96 (p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RALL) || 97 (p_t1t->prev_cmd_rsp_info.addr == *p))) { 98 /* Response to previous command retransmission */ 99 RW_TRACE_ERROR2( 100 "T1T Response to previous command in Idle state. command=0x%02x, " 101 "Remaining max retx rsp:0x%02x ", 102 p_t1t->prev_cmd_rsp_info.op_code, 103 p_t1t->prev_cmd_rsp_info.pend_retx_rsp - 1); 104 p_t1t->prev_cmd_rsp_info.pend_retx_rsp--; 105 GKI_freebuf(p_pkt); 106 } else { 107 /* Raw frame event */ 108 evt_data.data.p_data = p_pkt; 109 (*rw_cb.p_cback)(RW_T1T_RAW_FRAME_EVT, (tRW_DATA*)&evt_data); 110 } 111 return; 112 } 113 114#if (RW_STATS_INCLUDED == TRUE) 115 /* Update rx stats */ 116 rw_main_update_rx_stats(p_pkt->len); 117#endif /* RW_STATS_INCLUDED */ 118 119 if ((p_pkt->len != p_cmd_rsp_info->rsp_len) || 120 ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && 121 (p_cmd_rsp_info->opcode != T1T_CMD_RID) && (*p != p_t1t->addr))) 122 123 { 124 /* If previous command was retransmitted and if response is pending to 125 * previous command retransmission, 126 * then check if lenght and ADD/ADD8/ADDS field matches the expected value 127 * of previous 128 * retransmited command response. However, ignore ADD field if the command 129 * was RALL/RID 130 */ 131 if ((p_t1t->prev_cmd_rsp_info.pend_retx_rsp) && 132 (p_t1t->prev_cmd_rsp_info.rsp_len == p_pkt->len) && 133 ((p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RID) || 134 (p_t1t->prev_cmd_rsp_info.op_code == T1T_CMD_RALL) || 135 (p_t1t->prev_cmd_rsp_info.addr == *p))) { 136 RW_TRACE_ERROR2( 137 "T1T Response to previous command. command=0x%02x, Remaining max " 138 "retx rsp:0x%02x", 139 p_t1t->prev_cmd_rsp_info.op_code, 140 p_t1t->prev_cmd_rsp_info.pend_retx_rsp - 1); 141 p_t1t->prev_cmd_rsp_info.pend_retx_rsp--; 142 } else { 143 /* Stop timer as some response to current command is received */ 144 nfc_stop_quick_timer(&p_t1t->timer); 145/* Retrasmit the last sent command if retry-count < max retry */ 146#if (BT_TRACE_VERBOSE == TRUE) 147 RW_TRACE_ERROR2("T1T Frame error. state=%s command (opcode) = 0x%02x", 148 rw_t1t_get_state_name(p_t1t->state), 149 p_cmd_rsp_info->opcode); 150#else 151 RW_TRACE_ERROR2("T1T Frame error. state=0x%02x command = 0x%02x ", 152 p_t1t->state, p_cmd_rsp_info->opcode); 153#endif 154 rw_t1t_process_frame_error(); 155 } 156 GKI_freebuf(p_pkt); 157 return; 158 } 159 160 /* Stop timer as response to current command is received */ 161 nfc_stop_quick_timer(&p_t1t->timer); 162 163 RW_TRACE_EVENT2("RW RECV [%s]:0x%x RSP", t1t_info_to_str(p_cmd_rsp_info), 164 p_cmd_rsp_info->opcode); 165 166 /* If we did not receive response to all retransmitted previous command, 167 * dont expect that as response have come for the current command itself. 168 */ 169 if (p_t1t->prev_cmd_rsp_info.pend_retx_rsp) 170 memset(&(p_t1t->prev_cmd_rsp_info), 0, sizeof(tRW_T1T_PREV_CMD_RSP_INFO)); 171 172 if (rw_cb.cur_retry) { 173 /* If the current command was retransmitted to get this response, we might 174 get 175 response later to all or some of the retrasnmission of the current 176 command 177 */ 178 p_t1t->prev_cmd_rsp_info.addr = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && 179 (p_cmd_rsp_info->opcode != T1T_CMD_RID)) 180 ? p_t1t->addr 181 : 0; 182 p_t1t->prev_cmd_rsp_info.rsp_len = p_cmd_rsp_info->rsp_len; 183 p_t1t->prev_cmd_rsp_info.op_code = p_cmd_rsp_info->opcode; 184 p_t1t->prev_cmd_rsp_info.pend_retx_rsp = (uint8_t)rw_cb.cur_retry; 185 } 186 187 rw_cb.cur_retry = 0; 188 189 if (p_cmd_rsp_info->opcode == T1T_CMD_RID) { 190 rw_event = rw_t1t_handle_rid_rsp(p_pkt); 191 } else { 192 rw_event = 193 rw_t1t_handle_rsp(p_cmd_rsp_info, &b_notify, p, &evt_data.status); 194 } 195 196 if (b_notify) { 197 if ((p_t1t->state != RW_T1T_STATE_READ) && 198 (p_t1t->state != RW_T1T_STATE_WRITE)) { 199 GKI_freebuf(p_pkt); 200 evt_data.data.p_data = NULL; 201 } else { 202 evt_data.data.p_data = p_pkt; 203 } 204 rw_t1t_handle_op_complete(); 205 (*rw_cb.p_cback)(rw_event, (tRW_DATA*)&evt_data); 206 } else 207 GKI_freebuf(p_pkt); 208 209#if (BT_TRACE_VERBOSE == TRUE) 210 if (begin_state != p_t1t->state) { 211 RW_TRACE_DEBUG2("RW T1T state changed:<%s> -> <%s>", 212 rw_t1t_get_state_name(begin_state), 213 rw_t1t_get_state_name(p_t1t->state)); 214 } 215#endif 216} 217 218/******************************************************************************* 219** 220** Function rw_t1t_conn_cback 221** 222** Description This callback function receives the events/data from NFCC. 223** 224** Returns none 225** 226*******************************************************************************/ 227void rw_t1t_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event, 228 tNFC_CONN* p_data) { 229 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 230 tRW_READ_DATA evt_data; 231 232 RW_TRACE_DEBUG2("rw_t1t_conn_cback: conn_id=%i, evt=0x%x", conn_id, event); 233 /* Only handle static conn_id */ 234 if (conn_id != NFC_RF_CONN_ID) { 235 RW_TRACE_WARNING1("rw_t1t_conn_cback - Not static connection id: =%i", 236 conn_id); 237 return; 238 } 239 240 switch (event) { 241 case NFC_CONN_CREATE_CEVT: 242 case NFC_CONN_CLOSE_CEVT: 243 break; 244 245 case NFC_DEACTIVATE_CEVT: 246#if (RW_STATS_INCLUDED == TRUE) 247 /* Display stats */ 248 rw_main_log_stats(); 249#endif /* RW_STATS_INCLUDED */ 250 251 /* Stop t1t timer (if started) */ 252 nfc_stop_quick_timer(&p_t1t->timer); 253 254 /* Free cmd buf for retransmissions */ 255 if (p_t1t->p_cur_cmd_buf) { 256 GKI_freebuf(p_t1t->p_cur_cmd_buf); 257 p_t1t->p_cur_cmd_buf = NULL; 258 } 259 260 p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED; 261 NFC_SetStaticRfCback(NULL); 262 break; 263 264 case NFC_DATA_CEVT: 265 if (p_data != NULL) { 266 if (p_data->data.status == NFC_STATUS_OK) { 267 rw_t1t_data_cback(conn_id, event, p_data); 268 break; 269 } else if (p_data->data.p_data != NULL) { 270 /* Free the response buffer in case of error response */ 271 GKI_freebuf((NFC_HDR*)(p_data->data.p_data)); 272 p_data->data.p_data = NULL; 273 } 274 } 275 /* Data event with error status...fall through to NFC_ERROR_CEVT case */ 276 277 case NFC_ERROR_CEVT: 278 if ((p_t1t->state == RW_T1T_STATE_NOT_ACTIVATED) || 279 (p_t1t->state == RW_T1T_STATE_IDLE)) { 280#if (RW_STATS_INCLUDED == TRUE) 281 rw_main_update_trans_error_stats(); 282#endif /* RW_STATS_INCLUDED */ 283 284 if (event == NFC_ERROR_CEVT) 285 evt_data.status = (tNFC_STATUS)(*(uint8_t*)p_data); 286 else if (p_data) 287 evt_data.status = p_data->status; 288 else 289 evt_data.status = NFC_STATUS_FAILED; 290 291 evt_data.p_data = NULL; 292 (*rw_cb.p_cback)(RW_T1T_INTF_ERROR_EVT, (tRW_DATA*)&evt_data); 293 break; 294 } 295 nfc_stop_quick_timer(&p_t1t->timer); 296 297#if (RW_STATS_INCLUDED == TRUE) 298 rw_main_update_trans_error_stats(); 299#endif /* RW_STATS_INCLUDED */ 300 301 if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) { 302 rw_t1t_handle_presence_check_rsp(NFC_STATUS_FAILED); 303 } else { 304 rw_t1t_process_error(); 305 } 306 break; 307 308 default: 309 break; 310 } 311} 312 313/******************************************************************************* 314** 315** Function rw_t1t_send_static_cmd 316** 317** Description This function composes a Type 1 Tag command for static 318** memory and send through NCI to NFCC. 319** 320** Returns NFC_STATUS_OK if the command is successfuly sent to NCI 321** otherwise, error status 322** 323*******************************************************************************/ 324tNFC_STATUS rw_t1t_send_static_cmd(uint8_t opcode, uint8_t add, uint8_t dat) { 325 tNFC_STATUS status = NFC_STATUS_FAILED; 326 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 327 const tT1T_CMD_RSP_INFO* p_cmd_rsp_info = t1t_cmd_to_rsp_info(opcode); 328 NFC_HDR* p_data; 329 uint8_t* p; 330 331 if (p_cmd_rsp_info) { 332 /* a valid opcode for RW */ 333 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID); 334 if (p_data) { 335 p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO*)p_cmd_rsp_info; 336 p_t1t->addr = add; 337 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 338 p = (uint8_t*)(p_data + 1) + p_data->offset; 339 UINT8_TO_BE_STREAM(p, opcode); 340 UINT8_TO_BE_STREAM(p, add); 341 UINT8_TO_BE_STREAM(p, dat); 342 343 ARRAY_TO_STREAM(p, p_t1t->mem, T1T_CMD_UID_LEN); 344 p_data->len = p_cmd_rsp_info->cmd_len; 345 346 /* Indicate first attempt to send command, back up cmd buffer in case 347 * needed for retransmission */ 348 rw_cb.cur_retry = 0; 349 memcpy(p_t1t->p_cur_cmd_buf, p_data, 350 sizeof(NFC_HDR) + p_data->offset + p_data->len); 351 352#if (RW_STATS_INCLUDED == TRUE) 353 /* Update stats */ 354 rw_main_update_tx_stats(p_data->len, false); 355#endif /* RW_STATS_INCLUDED */ 356 357 RW_TRACE_EVENT2("RW SENT [%s]:0x%x CMD", t1t_info_to_str(p_cmd_rsp_info), 358 p_cmd_rsp_info->opcode); 359 status = NFC_SendData(NFC_RF_CONN_ID, p_data); 360 if (status == NFC_STATUS_OK) { 361 nfc_start_quick_timer( 362 &p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, 363 (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 364 } 365 } else { 366 status = NFC_STATUS_NO_BUFFERS; 367 } 368 } 369 return status; 370} 371 372/******************************************************************************* 373** 374** Function rw_t1t_send_dyn_cmd 375** 376** Description This function composes a Type 1 Tag command for dynamic 377** memory and send through NCI to NFCC. 378** 379** Returns NFC_STATUS_OK if the command is successfuly sent to NCI 380** otherwise, error status 381** 382*******************************************************************************/ 383tNFC_STATUS rw_t1t_send_dyn_cmd(uint8_t opcode, uint8_t add, uint8_t* p_dat) { 384 tNFC_STATUS status = NFC_STATUS_FAILED; 385 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 386 const tT1T_CMD_RSP_INFO* p_cmd_rsp_info = t1t_cmd_to_rsp_info(opcode); 387 NFC_HDR* p_data; 388 uint8_t* p; 389 390 if (p_cmd_rsp_info) { 391 /* a valid opcode for RW */ 392 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID); 393 if (p_data) { 394 p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO*)p_cmd_rsp_info; 395 p_t1t->addr = add; 396 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 397 p = (uint8_t*)(p_data + 1) + p_data->offset; 398 UINT8_TO_BE_STREAM(p, opcode); 399 UINT8_TO_BE_STREAM(p, add); 400 401 if (p_dat) { 402 ARRAY_TO_STREAM(p, p_dat, 8); 403 } else { 404 memset(p, 0, 8); 405 p += 8; 406 } 407 ARRAY_TO_STREAM(p, p_t1t->mem, T1T_CMD_UID_LEN); 408 p_data->len = p_cmd_rsp_info->cmd_len; 409 410 /* Indicate first attempt to send command, back up cmd buffer in case 411 * needed for retransmission */ 412 rw_cb.cur_retry = 0; 413 memcpy(p_t1t->p_cur_cmd_buf, p_data, 414 sizeof(NFC_HDR) + p_data->offset + p_data->len); 415 416#if (RW_STATS_INCLUDED == TRUE) 417 /* Update stats */ 418 rw_main_update_tx_stats(p_data->len, false); 419#endif /* RW_STATS_INCLUDED */ 420 421 RW_TRACE_EVENT2("RW SENT [%s]:0x%x CMD", t1t_info_to_str(p_cmd_rsp_info), 422 p_cmd_rsp_info->opcode); 423 424 status = NFC_SendData(NFC_RF_CONN_ID, p_data); 425 if (status == NFC_STATUS_OK) { 426 nfc_start_quick_timer( 427 &p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, 428 (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 429 } 430 } else { 431 status = NFC_STATUS_NO_BUFFERS; 432 } 433 } 434 return status; 435} 436 437/***************************************************************************** 438** 439** Function rw_t1t_handle_rid_rsp 440** 441** Description Handles response to RID: Collects HR, UID, notify up the 442** stack 443** 444** Returns event to notify application 445** 446*****************************************************************************/ 447static tRW_EVENT rw_t1t_handle_rid_rsp(NFC_HDR* p_pkt) { 448 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 449 tRW_DATA evt_data; 450 uint8_t* p_rid_rsp; 451 452 evt_data.status = NFC_STATUS_OK; 453 evt_data.data.p_data = p_pkt; 454 455 /* Assume the data is just the response byte sequence */ 456 p_rid_rsp = (uint8_t*)(p_pkt + 1) + p_pkt->offset; 457 458 /* Response indicates tag is present */ 459 if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) { 460 /* If checking for the presence of the tag then just notify */ 461 return RW_T1T_PRESENCE_CHECK_EVT; 462 } 463 464 /* Extract HR and UID from response */ 465 STREAM_TO_ARRAY(p_t1t->hr, p_rid_rsp, T1T_HR_LEN); 466 467#if (BT_TRACE_VERBOSE == TRUE) 468 RW_TRACE_DEBUG2("hr0:0x%x, hr1:0x%x", p_t1t->hr[0], p_t1t->hr[1]); 469 RW_TRACE_DEBUG4("rw_t1t_handle_rid_rsp (): UID0-3=%02x%02x%02x%02x", 470 p_rid_rsp[0], p_rid_rsp[1], p_rid_rsp[2], p_rid_rsp[3]); 471#else 472 RW_TRACE_DEBUG0("rw_t1t_handle_rid_rsp ()"); 473#endif 474 475 /* Fetch UID0-3 from RID response message */ 476 STREAM_TO_ARRAY(p_t1t->mem, p_rid_rsp, T1T_CMD_UID_LEN); 477 478 /* Notify RID response Event */ 479 return RW_T1T_RID_EVT; 480} 481 482/******************************************************************************* 483** 484** Function rw_t1t_select 485** 486** Description This function will set the callback function to 487** receive data from lower layers and also send rid command 488** 489** Returns none 490** 491*******************************************************************************/ 492tNFC_STATUS rw_t1t_select(uint8_t hr[T1T_HR_LEN], 493 uint8_t uid[T1T_CMD_UID_LEN]) { 494 tNFC_STATUS status = NFC_STATUS_FAILED; 495 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 496 497 p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED; 498 499 /* Alloc cmd buf for retransmissions */ 500 if (p_t1t->p_cur_cmd_buf == NULL) { 501 p_t1t->p_cur_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID); 502 if (p_t1t->p_cur_cmd_buf == NULL) { 503 RW_TRACE_ERROR0( 504 "rw_t1t_select: unable to allocate buffer for retransmission"); 505 return status; 506 } 507 } 508 509 memcpy(p_t1t->hr, hr, T1T_HR_LEN); 510 memcpy(p_t1t->mem, uid, T1T_CMD_UID_LEN); 511 512 NFC_SetStaticRfCback(rw_t1t_conn_cback); 513 514 p_t1t->state = RW_T1T_STATE_IDLE; 515 516 return NFC_STATUS_OK; 517} 518 519/******************************************************************************* 520** 521** Function rw_t1t_process_timeout 522** 523** Description process timeout event 524** 525** Returns none 526** 527*******************************************************************************/ 528void rw_t1t_process_timeout(TIMER_LIST_ENT* p_tle) { 529 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 530 531#if (BT_TRACE_VERBOSE == TRUE) 532 RW_TRACE_ERROR2("T1T timeout. state=%s command (opcode)=0x%02x ", 533 rw_t1t_get_state_name(p_t1t->state), 534 (rw_cb.tcb.t1t.p_cmd_rsp_info)->opcode); 535#else 536 RW_TRACE_ERROR2("T1T timeout. state=0x%02x command=0x%02x ", p_t1t->state, 537 (rw_cb.tcb.t1t.p_cmd_rsp_info)->opcode); 538#endif 539 540 if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) { 541 /* Tag has moved from range */ 542 rw_t1t_handle_presence_check_rsp(NFC_STATUS_FAILED); 543 } else if (p_t1t->state != RW_T1T_STATE_IDLE) { 544 rw_t1t_process_error(); 545 } 546} 547 548/******************************************************************************* 549** 550** Function rw_t1t_process_frame_error 551** 552** Description Process frame crc error 553** 554** Returns none 555** 556*******************************************************************************/ 557static void rw_t1t_process_frame_error(void) { 558#if (RW_STATS_INCLUDED == TRUE) 559 /* Update stats */ 560 rw_main_update_crc_error_stats(); 561#endif /* RW_STATS_INCLUDED */ 562 563 /* Process the error */ 564 rw_t1t_process_error(); 565} 566 567/******************************************************************************* 568** 569** Function rw_t1t_process_error 570** 571** Description process timeout event 572** 573** Returns none 574** 575*******************************************************************************/ 576static void rw_t1t_process_error(void) { 577 tRW_READ_DATA evt_data; 578 tRW_EVENT rw_event; 579 NFC_HDR* p_cmd_buf; 580 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 581 tT1T_CMD_RSP_INFO* p_cmd_rsp_info = 582 (tT1T_CMD_RSP_INFO*)rw_cb.tcb.t1t.p_cmd_rsp_info; 583 tRW_DETECT_NDEF_DATA ndef_data; 584 585 RW_TRACE_DEBUG1("rw_t1t_process_error () State: %u", p_t1t->state); 586 587 /* Retry sending command if retry-count < max */ 588 if (rw_cb.cur_retry < RW_MAX_RETRIES) { 589 /* retry sending the command */ 590 rw_cb.cur_retry++; 591 592 RW_TRACE_DEBUG2("T1T retransmission attempt %i of %i", rw_cb.cur_retry, 593 RW_MAX_RETRIES); 594 595 /* allocate a new buffer for message */ 596 p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID); 597 if (p_cmd_buf != NULL) { 598 memcpy(p_cmd_buf, p_t1t->p_cur_cmd_buf, 599 sizeof(NFC_HDR) + p_t1t->p_cur_cmd_buf->offset + 600 p_t1t->p_cur_cmd_buf->len); 601 602#if (RW_STATS_INCLUDED == TRUE) 603 /* Update stats */ 604 rw_main_update_tx_stats(p_cmd_buf->len, true); 605#endif /* RW_STATS_INCLUDED */ 606 607 if (NFC_SendData(NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) { 608 /* Start timer for waiting for response */ 609 nfc_start_quick_timer( 610 &p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, 611 (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 612 613 return; 614 } 615 } 616 } else { 617 /* we might get response later to all or some of the retrasnmission 618 * of the current command, update previous command response information */ 619 RW_TRACE_DEBUG1("T1T maximum retransmission attempts reached (%i)", 620 RW_MAX_RETRIES); 621 p_t1t->prev_cmd_rsp_info.addr = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) && 622 (p_cmd_rsp_info->opcode != T1T_CMD_RID)) 623 ? p_t1t->addr 624 : 0; 625 p_t1t->prev_cmd_rsp_info.rsp_len = p_cmd_rsp_info->rsp_len; 626 p_t1t->prev_cmd_rsp_info.op_code = p_cmd_rsp_info->opcode; 627 p_t1t->prev_cmd_rsp_info.pend_retx_rsp = RW_MAX_RETRIES; 628 } 629 630#if (RW_STATS_INCLUDED == TRUE) 631 /* update failure count */ 632 rw_main_update_fail_stats(); 633#endif /* RW_STATS_INCLUDED */ 634 635 rw_event = rw_t1t_info_to_event(p_cmd_rsp_info); 636 if (p_t1t->state != RW_T1T_STATE_NOT_ACTIVATED) rw_t1t_handle_op_complete(); 637 638 evt_data.status = NFC_STATUS_TIMEOUT; 639 if (rw_event == RW_T2T_NDEF_DETECT_EVT) { 640 ndef_data.status = evt_data.status; 641 ndef_data.protocol = NFC_PROTOCOL_T1T; 642 ndef_data.flags = RW_NDEF_FL_UNKNOWN; 643 ndef_data.max_size = 0; 644 ndef_data.cur_size = 0; 645 (*rw_cb.p_cback)(rw_event, (tRW_DATA*)&ndef_data); 646 } else { 647 evt_data.p_data = NULL; 648 (*rw_cb.p_cback)(rw_event, (tRW_DATA*)&evt_data); 649 } 650} 651 652/***************************************************************************** 653** 654** Function rw_t1t_handle_presence_check_rsp 655** 656** Description Handle response to presence check 657** 658** Returns Nothing 659** 660*****************************************************************************/ 661void rw_t1t_handle_presence_check_rsp(tNFC_STATUS status) { 662 tRW_READ_DATA evt_data; 663 664 /* Notify, Tag is present or not */ 665 evt_data.status = status; 666 rw_t1t_handle_op_complete(); 667 668 (*(rw_cb.p_cback))(RW_T1T_PRESENCE_CHECK_EVT, (tRW_DATA*)&evt_data); 669} 670 671/***************************************************************************** 672** 673** Function rw_t1t_handle_op_complete 674** 675** Description Reset to IDLE state 676** 677** Returns Nothing 678** 679*****************************************************************************/ 680void rw_t1t_handle_op_complete(void) { 681 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 682 683 p_t1t->state = RW_T1T_STATE_IDLE; 684#if (RW_NDEF_INCLUDED == TRUE) 685 if (p_t1t->state != RW_T1T_STATE_READ_NDEF) { 686 p_t1t->b_update = false; 687 p_t1t->b_rseg = false; 688 } 689 p_t1t->substate = RW_T1T_SUBSTATE_NONE; 690#endif 691 return; 692} 693 694/***************************************************************************** 695** 696** Function RW_T1tPresenceCheck 697** 698** Description 699** Check if the tag is still in the field. 700** 701** The RW_T1T_PRESENCE_CHECK_EVT w/ status is used to indicate presence 702** or non-presence. 703** 704** Returns 705** NFC_STATUS_OK, if raw data frame sent 706** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation 707** NFC_STATUS_FAILED: other error 708** 709*****************************************************************************/ 710tNFC_STATUS RW_T1tPresenceCheck(void) { 711 tNFC_STATUS retval = NFC_STATUS_OK; 712 tRW_DATA evt_data; 713 tRW_CB* p_rw_cb = &rw_cb; 714 715 RW_TRACE_API0("RW_T1tPresenceCheck"); 716 717 /* If RW_SelectTagType was not called (no conn_callback) return failure */ 718 if (!p_rw_cb->p_cback) { 719 retval = NFC_STATUS_FAILED; 720 } 721 /* If we are not activated, then RW_T1T_PRESENCE_CHECK_EVT status=FAIL */ 722 else if (p_rw_cb->tcb.t1t.state == RW_T1T_STATE_NOT_ACTIVATED) { 723 evt_data.status = NFC_STATUS_FAILED; 724 (*p_rw_cb->p_cback)(RW_T1T_PRESENCE_CHECK_EVT, &evt_data); 725 } 726 /* If command is pending, assume tag is still present */ 727 else if (p_rw_cb->tcb.t1t.state != RW_T1T_STATE_IDLE) { 728 evt_data.status = NFC_STATUS_OK; 729 (*p_rw_cb->p_cback)(RW_T1T_PRESENCE_CHECK_EVT, &evt_data); 730 } else { 731 /* IDLE state: send a RID command to the tag to see if it responds */ 732 retval = rw_t1t_send_static_cmd(T1T_CMD_RID, 0, 0); 733 if (retval == NFC_STATUS_OK) { 734 p_rw_cb->tcb.t1t.state = RW_T1T_STATE_CHECK_PRESENCE; 735 } 736 } 737 738 return (retval); 739} 740 741/***************************************************************************** 742** 743** Function RW_T1tRid 744** 745** Description 746** This function sends a RID command for Reader/Writer mode. 747** 748** Returns 749** NFC_STATUS_OK, if raw data frame sent 750** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation 751** NFC_STATUS_FAILED: other error 752** 753*****************************************************************************/ 754tNFC_STATUS RW_T1tRid(void) { 755 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 756 tNFC_STATUS status = NFC_STATUS_FAILED; 757 758 RW_TRACE_API0("RW_T1tRid"); 759 760 if (p_t1t->state != RW_T1T_STATE_IDLE) { 761 RW_TRACE_WARNING1("RW_T1tRid - Busy - State: %u", p_t1t->state); 762 return (NFC_STATUS_BUSY); 763 } 764 765 /* send a RID command */ 766 status = rw_t1t_send_static_cmd(T1T_CMD_RID, 0, 0); 767 if (status == NFC_STATUS_OK) { 768 p_t1t->state = RW_T1T_STATE_READ; 769 } 770 771 return (status); 772} 773 774/******************************************************************************* 775** 776** Function RW_T1tReadAll 777** 778** Description This function sends a RALL command for Reader/Writer mode. 779** 780** Returns tNFC_STATUS 781** 782*******************************************************************************/ 783tNFC_STATUS RW_T1tReadAll(void) { 784 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 785 tNFC_STATUS status = NFC_STATUS_FAILED; 786 787 RW_TRACE_API0("RW_T1tReadAll"); 788 789 if (p_t1t->state != RW_T1T_STATE_IDLE) { 790 RW_TRACE_WARNING1("RW_T1tReadAll - Busy - State: %u", p_t1t->state); 791 return (NFC_STATUS_BUSY); 792 } 793 794 /* send RALL command */ 795 status = rw_t1t_send_static_cmd(T1T_CMD_RALL, 0, 0); 796 if (status == NFC_STATUS_OK) { 797 p_t1t->state = RW_T1T_STATE_READ; 798 } 799 800 return status; 801} 802 803/******************************************************************************* 804** 805** Function RW_T1tRead 806** 807** Description This function sends a READ command for Reader/Writer mode. 808** 809** Returns tNFC_STATUS 810** 811*******************************************************************************/ 812tNFC_STATUS RW_T1tRead(uint8_t block, uint8_t byte) { 813 tNFC_STATUS status = NFC_STATUS_FAILED; 814 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 815 uint8_t addr; 816 817 if (p_t1t->state != RW_T1T_STATE_IDLE) { 818 RW_TRACE_WARNING1("RW_T1tRead - Busy - State: %u", p_t1t->state); 819 return (NFC_STATUS_BUSY); 820 } 821 822 /* send READ command */ 823 RW_T1T_BLD_ADD((addr), (block), (byte)); 824 status = rw_t1t_send_static_cmd(T1T_CMD_READ, addr, 0); 825 if (status == NFC_STATUS_OK) { 826 p_t1t->state = RW_T1T_STATE_READ; 827 } 828 return status; 829} 830 831/******************************************************************************* 832** 833** Function RW_T1tWriteErase 834** 835** Description This function sends a WRITE-E command for Reader/Writer 836** mode. 837** 838** Returns tNFC_STATUS 839** 840*******************************************************************************/ 841tNFC_STATUS RW_T1tWriteErase(uint8_t block, uint8_t byte, uint8_t new_byte) { 842 tNFC_STATUS status = NFC_STATUS_FAILED; 843 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 844 uint8_t addr; 845 846 if (p_t1t->state != RW_T1T_STATE_IDLE) { 847 RW_TRACE_WARNING1("RW_T1tWriteErase - Busy - State: %u", p_t1t->state); 848 return (NFC_STATUS_BUSY); 849 } 850 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) && 851 (block != T1T_CC_BLOCK) && (byte != T1T_CC_RWA_OFFSET)) { 852 RW_TRACE_ERROR0("RW_T1tWriteErase - Tag is in Read only state"); 853 return (NFC_STATUS_REFUSED); 854 } 855 if ((block >= T1T_STATIC_BLOCKS) || (byte >= T1T_BLOCK_SIZE)) { 856 RW_TRACE_ERROR2("RW_T1tWriteErase - Invalid Block/byte: %u / %u", block, 857 byte); 858 return (NFC_STATUS_REFUSED); 859 } 860 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) { 861 RW_TRACE_WARNING1("RW_T1tWriteErase - Cannot write to Locked block: %u", 862 block); 863 return (NFC_STATUS_REFUSED); 864 } 865 /* send WRITE-E command */ 866 RW_T1T_BLD_ADD((addr), (block), (byte)); 867 status = rw_t1t_send_static_cmd(T1T_CMD_WRITE_E, addr, new_byte); 868 if (status == NFC_STATUS_OK) { 869 p_t1t->state = RW_T1T_STATE_WRITE; 870 if (block < T1T_BLOCKS_PER_SEGMENT) { 871 p_t1t->b_update = false; 872 p_t1t->b_rseg = false; 873 } 874 } 875 return status; 876} 877 878/******************************************************************************* 879** 880** Function RW_T1tWriteNoErase 881** 882** Description This function sends a WRITE-NE command for Reader/Writer 883** mode. 884** 885** Returns tNFC_STATUS 886** 887*******************************************************************************/ 888tNFC_STATUS RW_T1tWriteNoErase(uint8_t block, uint8_t byte, uint8_t new_byte) { 889 tNFC_STATUS status = NFC_STATUS_FAILED; 890 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 891 uint8_t addr; 892 893 if (p_t1t->state != RW_T1T_STATE_IDLE) { 894 RW_TRACE_WARNING1("RW_T1tWriteNoErase - Busy - State: %u", p_t1t->state); 895 return (NFC_STATUS_BUSY); 896 } 897 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) && 898 (block != T1T_CC_BLOCK) && (byte != T1T_CC_RWA_OFFSET)) { 899 RW_TRACE_ERROR0("RW_T1tWriteErase - Tag is in Read only state"); 900 return (NFC_STATUS_REFUSED); 901 } 902 if ((block >= T1T_STATIC_BLOCKS) || (byte >= T1T_BLOCK_SIZE)) { 903 RW_TRACE_ERROR2("RW_T1tWriteErase - Invalid Block/byte: %u / %u", block, 904 byte); 905 return (NFC_STATUS_REFUSED); 906 } 907 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) { 908 RW_TRACE_WARNING1("RW_T1tWriteNoErase - Cannot write to Locked block: %u", 909 block); 910 return (NFC_STATUS_REFUSED); 911 } 912 /* send WRITE-NE command */ 913 RW_T1T_BLD_ADD((addr), (block), (byte)); 914 status = rw_t1t_send_static_cmd(T1T_CMD_WRITE_NE, addr, new_byte); 915 if (status == NFC_STATUS_OK) { 916 p_t1t->state = RW_T1T_STATE_WRITE; 917 if (block < T1T_BLOCKS_PER_SEGMENT) { 918 p_t1t->b_update = false; 919 p_t1t->b_rseg = false; 920 } 921 } 922 return status; 923} 924 925/******************************************************************************* 926** 927** Function RW_T1tReadSeg 928** 929** Description This function sends a RSEG command for Reader/Writer mode. 930** 931** Returns tNFC_STATUS 932** 933*******************************************************************************/ 934tNFC_STATUS RW_T1tReadSeg(uint8_t segment) { 935 tNFC_STATUS status = NFC_STATUS_FAILED; 936 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 937 uint8_t adds; 938 939 if (p_t1t->state != RW_T1T_STATE_IDLE) { 940 RW_TRACE_WARNING1("RW_T1tReadSeg - Busy - State: %u", p_t1t->state); 941 return (NFC_STATUS_BUSY); 942 } 943 if (segment >= T1T_MAX_SEGMENTS) { 944 RW_TRACE_ERROR1("RW_T1tReadSeg - Invalid Segment: %u", segment); 945 return (NFC_STATUS_REFUSED); 946 } 947 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0) { 948 /* send RSEG command */ 949 RW_T1T_BLD_ADDS((adds), (segment)); 950 status = rw_t1t_send_dyn_cmd(T1T_CMD_RSEG, adds, NULL); 951 if (status == NFC_STATUS_OK) { 952 p_t1t->state = RW_T1T_STATE_READ; 953 } 954 } 955 return status; 956} 957 958/******************************************************************************* 959** 960** Function RW_T1tRead8 961** 962** Description This function sends a READ8 command for Reader/Writer mode. 963** 964** Returns tNFC_STATUS 965** 966*******************************************************************************/ 967tNFC_STATUS RW_T1tRead8(uint8_t block) { 968 tNFC_STATUS status = NFC_STATUS_FAILED; 969 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 970 971 if (p_t1t->state != RW_T1T_STATE_IDLE) { 972 RW_TRACE_WARNING1("RW_T1tRead8 - Busy - State: %u", p_t1t->state); 973 return (NFC_STATUS_BUSY); 974 } 975 976 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || 977 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) { 978 /* send READ8 command */ 979 status = rw_t1t_send_dyn_cmd(T1T_CMD_READ8, block, NULL); 980 if (status == NFC_STATUS_OK) { 981 p_t1t->state = RW_T1T_STATE_READ; 982 } 983 } 984 return status; 985} 986 987/******************************************************************************* 988** 989** Function RW_T1tWriteErase8 990** 991** Description This function sends a WRITE-E8 command for Reader/Writer 992** mode. 993** 994** Returns tNFC_STATUS 995** 996*******************************************************************************/ 997tNFC_STATUS RW_T1tWriteErase8(uint8_t block, uint8_t* p_new_dat) { 998 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 999 tNFC_STATUS status = NFC_STATUS_FAILED; 1000 1001 if (p_t1t->state != RW_T1T_STATE_IDLE) { 1002 RW_TRACE_WARNING1("RW_T1tWriteErase8 - Busy - State: %u", p_t1t->state); 1003 return (NFC_STATUS_BUSY); 1004 } 1005 1006 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) && 1007 (block != T1T_CC_BLOCK)) { 1008 RW_TRACE_ERROR0("RW_T1tWriteErase8 - Tag is in Read only state"); 1009 return (NFC_STATUS_REFUSED); 1010 } 1011 1012 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) { 1013 RW_TRACE_WARNING1("RW_T1tWriteErase8 - Cannot write to Locked block: %u", 1014 block); 1015 return (NFC_STATUS_REFUSED); 1016 } 1017 1018 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || 1019 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) { 1020 /* send WRITE-E8 command */ 1021 status = rw_t1t_send_dyn_cmd(T1T_CMD_WRITE_E8, block, p_new_dat); 1022 if (status == NFC_STATUS_OK) { 1023 p_t1t->state = RW_T1T_STATE_WRITE; 1024 if (block < T1T_BLOCKS_PER_SEGMENT) { 1025 p_t1t->b_update = false; 1026 p_t1t->b_rseg = false; 1027 } 1028 } 1029 } 1030 return status; 1031} 1032 1033/******************************************************************************* 1034** 1035** Function RW_T1tWriteNoErase8 1036** 1037** Description This function sends a WRITE-NE8 command for Reader/Writer 1038** mode. 1039** 1040** Returns tNFC_STATUS 1041** 1042*******************************************************************************/ 1043tNFC_STATUS RW_T1tWriteNoErase8(uint8_t block, uint8_t* p_new_dat) { 1044 tNFC_STATUS status = NFC_STATUS_FAILED; 1045 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; 1046 1047 if (p_t1t->state != RW_T1T_STATE_IDLE) { 1048 RW_TRACE_WARNING1("RW_T1tWriteNoErase8 - Busy - State: %u", p_t1t->state); 1049 return (NFC_STATUS_BUSY); 1050 } 1051 1052 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) && 1053 (block != T1T_CC_BLOCK)) { 1054 RW_TRACE_ERROR0("RW_T1tWriteNoErase8 - Tag is in Read only state"); 1055 return (NFC_STATUS_REFUSED); 1056 } 1057 1058 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) { 1059 RW_TRACE_WARNING1("RW_T1tWriteNoErase8 - Cannot write to Locked block: %u", 1060 block); 1061 return (NFC_STATUS_REFUSED); 1062 } 1063 1064 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 || 1065 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) { 1066 /* send WRITE-NE command */ 1067 status = rw_t1t_send_dyn_cmd(T1T_CMD_WRITE_NE8, block, p_new_dat); 1068 if (status == NFC_STATUS_OK) { 1069 p_t1t->state = RW_T1T_STATE_WRITE; 1070 if (block < T1T_BLOCKS_PER_SEGMENT) { 1071 p_t1t->b_update = false; 1072 p_t1t->b_rseg = false; 1073 } 1074 } 1075 } 1076 return status; 1077} 1078 1079#if (BT_TRACE_VERBOSE == TRUE) 1080/******************************************************************************* 1081** 1082** Function rw_t1t_get_state_name 1083** 1084** Description This function returns the state name. 1085** 1086** NOTE conditionally compiled to save memory. 1087** 1088** Returns pointer to the name 1089** 1090*******************************************************************************/ 1091static char* rw_t1t_get_state_name(uint8_t state) { 1092 switch (state) { 1093 case RW_T1T_STATE_IDLE: 1094 return ("IDLE"); 1095 case RW_T1T_STATE_NOT_ACTIVATED: 1096 return ("NOT_ACTIVATED"); 1097 case RW_T1T_STATE_READ: 1098 return ("APP_READ"); 1099 case RW_T1T_STATE_WRITE: 1100 return ("APP_WRITE"); 1101 case RW_T1T_STATE_TLV_DETECT: 1102 return ("TLV_DETECTION"); 1103 case RW_T1T_STATE_READ_NDEF: 1104 return ("READING_NDEF"); 1105 case RW_T1T_STATE_WRITE_NDEF: 1106 return ("WRITING_NDEF"); 1107 case RW_T1T_STATE_SET_TAG_RO: 1108 return ("SET_TAG_RO"); 1109 case RW_T1T_STATE_CHECK_PRESENCE: 1110 return ("CHECK_PRESENCE"); 1111 case RW_T1T_STATE_FORMAT_TAG: 1112 return ("FORMAT_TAG"); 1113 default: 1114 return ("???? UNKNOWN STATE"); 1115 } 1116} 1117 1118#endif /* (BT_TRACE_VERBOSE == TRUE) */ 1119