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