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