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("%s: state=%s (%d)", __func__,
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 "%s: T1T Response to previous command in Idle state. command=0x%02x, "
100 "Remaining max retx rsp=0x%02x ",
101 __func__, 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 "%s: T1T Response to previous command. command=0x%02x, Remaining max "
137 "retx rsp=0x%02x",
138 __func__, 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 "%s: T1T Frame error. state=%s command (opcode) = 0x%02x", __func__,
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("%s: RW RECV [%s]=0x%x RSP", __func__,
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("%s: RW T1T state changed:<%s> -> <%s>",
206 __func__,
207 rw_t1t_get_state_name(begin_state).c_str(),
208 rw_t1t_get_state_name(p_t1t->state).c_str());
209 }
210 }
211
212 /*******************************************************************************
213 **
214 ** Function rw_t1t_conn_cback
215 **
216 ** Description This callback function receives the events/data from NFCC.
217 **
218 ** Returns none
219 **
220 *******************************************************************************/
rw_t1t_conn_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)221 void rw_t1t_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event,
222 tNFC_CONN* p_data) {
223 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
224
225 LOG(VERBOSE) << StringPrintf("%s: conn_id=%i, evt=0x%x", __func__, conn_id,
226 event);
227 /* Only handle static conn_id */
228 if (conn_id != NFC_RF_CONN_ID) {
229 LOG(WARNING) << StringPrintf("%s: Not static connection id: =%i", __func__,
230 conn_id);
231 return;
232 }
233
234 switch (event) {
235 case NFC_CONN_CREATE_CEVT:
236 case NFC_CONN_CLOSE_CEVT:
237 break;
238
239 case NFC_DEACTIVATE_CEVT:
240 #if (RW_STATS_INCLUDED == TRUE)
241 /* Display stats */
242 rw_main_log_stats();
243 #endif /* RW_STATS_INCLUDED */
244
245 /* Stop t1t timer (if started) */
246 nfc_stop_quick_timer(&p_t1t->timer);
247
248 /* Free cmd buf for retransmissions */
249 if (p_t1t->p_cur_cmd_buf) {
250 GKI_freebuf(p_t1t->p_cur_cmd_buf);
251 p_t1t->p_cur_cmd_buf = nullptr;
252 }
253
254 p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;
255 NFC_SetStaticRfCback(nullptr);
256 break;
257
258 case NFC_DATA_CEVT:
259 if (p_data != nullptr) {
260 if (p_data->data.status == NFC_STATUS_OK) {
261 rw_t1t_data_cback(conn_id, event, p_data);
262 break;
263 } else if (p_data->data.p_data != nullptr) {
264 /* Free the response buffer in case of error response */
265 GKI_freebuf((NFC_HDR*)(p_data->data.p_data));
266 p_data->data.p_data = nullptr;
267 }
268 }
269 /* Data event with error status...fall through to NFC_ERROR_CEVT case */
270 FALLTHROUGH_INTENDED;
271
272 case NFC_ERROR_CEVT:
273 if ((p_t1t->state == RW_T1T_STATE_NOT_ACTIVATED) ||
274 (p_t1t->state == RW_T1T_STATE_IDLE)) {
275 #if (RW_STATS_INCLUDED == TRUE)
276 rw_main_update_trans_error_stats();
277 #endif /* RW_STATS_INCLUDED */
278
279 tRW_READ_DATA evt_data;
280 if (event == NFC_ERROR_CEVT)
281 evt_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
282 else if (p_data)
283 evt_data.status = p_data->status;
284 else
285 evt_data.status = NFC_STATUS_FAILED;
286
287 evt_data.p_data = nullptr;
288 tRW_DATA rw_data;
289 rw_data.data = evt_data;
290 (*rw_cb.p_cback)(RW_T1T_INTF_ERROR_EVT, &rw_data);
291 break;
292 }
293 nfc_stop_quick_timer(&p_t1t->timer);
294
295 #if (RW_STATS_INCLUDED == TRUE)
296 rw_main_update_trans_error_stats();
297 #endif /* RW_STATS_INCLUDED */
298
299 if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) {
300 rw_t1t_handle_presence_check_rsp(NFC_STATUS_RF_FRAME_CORRUPTED);
301 } else {
302 rw_t1t_process_error();
303 }
304 break;
305
306 default:
307 break;
308 }
309 }
310
311 /*******************************************************************************
312 **
313 ** Function rw_t1t_send_static_cmd
314 **
315 ** Description This function composes a Type 1 Tag command for static
316 ** memory and send through NCI to NFCC.
317 **
318 ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI
319 ** otherwise, error status
320 **
321 *******************************************************************************/
rw_t1t_send_static_cmd(uint8_t opcode,uint8_t add,uint8_t dat)322 tNFC_STATUS rw_t1t_send_static_cmd(uint8_t opcode, uint8_t add, uint8_t dat) {
323 tNFC_STATUS status = NFC_STATUS_FAILED;
324 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
325 const tT1T_CMD_RSP_INFO* p_cmd_rsp_info = t1t_cmd_to_rsp_info(opcode);
326 NFC_HDR* p_data;
327 uint8_t* p;
328
329 if (p_cmd_rsp_info) {
330 /* a valid opcode for RW */
331 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
332 if (p_data) {
333 p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO*)p_cmd_rsp_info;
334 p_t1t->addr = add;
335 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
336 p = (uint8_t*)(p_data + 1) + p_data->offset;
337 UINT8_TO_BE_STREAM(p, opcode);
338 UINT8_TO_BE_STREAM(p, add);
339 UINT8_TO_BE_STREAM(p, dat);
340
341 ARRAY_TO_STREAM(p, p_t1t->mem, T1T_CMD_UID_LEN);
342 p_data->len = p_cmd_rsp_info->cmd_len;
343
344 /* Indicate first attempt to send command, back up cmd buffer in case
345 * needed for retransmission */
346 rw_cb.cur_retry = 0;
347 memcpy(p_t1t->p_cur_cmd_buf, p_data,
348 sizeof(NFC_HDR) + p_data->offset + p_data->len);
349
350 #if (RW_STATS_INCLUDED == TRUE)
351 /* Update stats */
352 rw_main_update_tx_stats(p_data->len, false);
353 #endif /* RW_STATS_INCLUDED */
354
355 LOG(VERBOSE) << StringPrintf("%s: RW SENT [%s]=0x%x CMD", __func__,
356 t1t_info_to_str(p_cmd_rsp_info),
357 p_cmd_rsp_info->opcode);
358 status = NFC_SendData(NFC_RF_CONN_ID, p_data);
359 if (status == NFC_STATUS_OK) {
360 nfc_start_quick_timer(
361 &p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE,
362 (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
363 }
364 } else {
365 status = NFC_STATUS_NO_BUFFERS;
366 }
367 }
368 return status;
369 }
370
371 /*******************************************************************************
372 **
373 ** Function rw_t1t_send_dyn_cmd
374 **
375 ** Description This function composes a Type 1 Tag command for dynamic
376 ** memory and send through NCI to NFCC.
377 **
378 ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI
379 ** otherwise, error status
380 **
381 *******************************************************************************/
rw_t1t_send_dyn_cmd(uint8_t opcode,uint8_t add,uint8_t * p_dat)382 tNFC_STATUS rw_t1t_send_dyn_cmd(uint8_t opcode, uint8_t add, uint8_t* p_dat) {
383 tNFC_STATUS status = NFC_STATUS_FAILED;
384 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
385 const tT1T_CMD_RSP_INFO* p_cmd_rsp_info = t1t_cmd_to_rsp_info(opcode);
386 NFC_HDR* p_data;
387 uint8_t* p;
388
389 if (p_cmd_rsp_info) {
390 /* a valid opcode for RW */
391 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
392 if (p_data) {
393 p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO*)p_cmd_rsp_info;
394 p_t1t->addr = add;
395 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
396 p = (uint8_t*)(p_data + 1) + p_data->offset;
397 UINT8_TO_BE_STREAM(p, opcode);
398 UINT8_TO_BE_STREAM(p, add);
399
400 if (p_dat) {
401 ARRAY_TO_STREAM(p, p_dat, 8);
402 } else {
403 memset(p, 0, 8);
404 p += 8;
405 }
406 ARRAY_TO_STREAM(p, p_t1t->mem, T1T_CMD_UID_LEN);
407 p_data->len = p_cmd_rsp_info->cmd_len;
408
409 /* Indicate first attempt to send command, back up cmd buffer in case
410 * needed for retransmission */
411 rw_cb.cur_retry = 0;
412 memcpy(p_t1t->p_cur_cmd_buf, p_data,
413 sizeof(NFC_HDR) + p_data->offset + p_data->len);
414
415 #if (RW_STATS_INCLUDED == TRUE)
416 /* Update stats */
417 rw_main_update_tx_stats(p_data->len, false);
418 #endif /* RW_STATS_INCLUDED */
419
420 LOG(VERBOSE) << StringPrintf("%s: RW SENT [%s]=0x%x CMD", __func__,
421 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 *****************************************************************************/
rw_t1t_handle_rid_rsp(NFC_HDR * p_pkt)447 static 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 LOG(VERBOSE) << StringPrintf("%s: hr0=0x%x, hr1=0x%x", __func__, p_t1t->hr[0],
468 p_t1t->hr[1]);
469 LOG(VERBOSE) << StringPrintf("%s: UID0-3=%02x%02x%02x%02x", __func__,
470 p_rid_rsp[0], p_rid_rsp[1], p_rid_rsp[2],
471 p_rid_rsp[3]);
472
473 /* Fetch UID0-3 from RID response message */
474 STREAM_TO_ARRAY(p_t1t->mem, p_rid_rsp, T1T_CMD_UID_LEN);
475
476 /* Notify RID response Event */
477 return RW_T1T_RID_EVT;
478 }
479
480 /*******************************************************************************
481 **
482 ** Function rw_t1t_select
483 **
484 ** Description This function will set the callback function to
485 ** receive data from lower layers and also send rid command
486 **
487 ** Returns none
488 **
489 *******************************************************************************/
rw_t1t_select(uint8_t hr[T1T_HR_LEN],uint8_t uid[T1T_CMD_UID_LEN])490 tNFC_STATUS rw_t1t_select(uint8_t hr[T1T_HR_LEN],
491 uint8_t uid[T1T_CMD_UID_LEN]) {
492 tNFC_STATUS status = NFC_STATUS_FAILED;
493 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
494
495 p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED;
496
497 /* Alloc cmd buf for retransmissions */
498 if (p_t1t->p_cur_cmd_buf == nullptr) {
499 p_t1t->p_cur_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
500 if (p_t1t->p_cur_cmd_buf == nullptr) {
501 LOG(ERROR) << StringPrintf(
502 "%s: unable to allocate buffer for retransmission", __func__);
503 return status;
504 }
505 }
506
507 memcpy(p_t1t->hr, hr, T1T_HR_LEN);
508 memcpy(p_t1t->mem, uid, T1T_CMD_UID_LEN);
509
510 NFC_SetStaticRfCback(rw_t1t_conn_cback);
511
512 p_t1t->state = RW_T1T_STATE_IDLE;
513
514 return NFC_STATUS_OK;
515 }
516
517 /*******************************************************************************
518 **
519 ** Function rw_t1t_process_timeout
520 **
521 ** Description process timeout event
522 **
523 ** Returns none
524 **
525 *******************************************************************************/
rw_t1t_process_timeout(TIMER_LIST_ENT * p_tle)526 void rw_t1t_process_timeout(__attribute__((unused)) TIMER_LIST_ENT* p_tle) {
527 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
528
529 LOG(ERROR) << StringPrintf("%s: state=%s command (opcode)=0x%02x ", __func__,
530 rw_t1t_get_state_name(p_t1t->state).c_str(),
531 (rw_cb.tcb.t1t.p_cmd_rsp_info)->opcode);
532
533 if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) {
534 /* Tag has moved from range */
535 rw_t1t_handle_presence_check_rsp(NFC_STATUS_RF_FRAME_CORRUPTED);
536 } else if (p_t1t->state != RW_T1T_STATE_IDLE) {
537 rw_t1t_process_error();
538 }
539 }
540
541 /*******************************************************************************
542 **
543 ** Function rw_t1t_process_frame_error
544 **
545 ** Description Process frame crc error
546 **
547 ** Returns none
548 **
549 *******************************************************************************/
rw_t1t_process_frame_error(void)550 static void rw_t1t_process_frame_error(void) {
551 #if (RW_STATS_INCLUDED == TRUE)
552 /* Update stats */
553 rw_main_update_crc_error_stats();
554 #endif /* RW_STATS_INCLUDED */
555
556 /* Process the error */
557 rw_t1t_process_error();
558 }
559
560 /*******************************************************************************
561 **
562 ** Function rw_t1t_process_error
563 **
564 ** Description process timeout event
565 **
566 ** Returns none
567 **
568 *******************************************************************************/
rw_t1t_process_error(void)569 static void rw_t1t_process_error(void) {
570 tRW_EVENT rw_event;
571 NFC_HDR* p_cmd_buf;
572 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
573 tT1T_CMD_RSP_INFO* p_cmd_rsp_info =
574 (tT1T_CMD_RSP_INFO*)rw_cb.tcb.t1t.p_cmd_rsp_info;
575
576 LOG(VERBOSE) << StringPrintf("%s: State=%u", __func__, p_t1t->state);
577
578 /* Retry sending command if retry-count < max */
579 if (rw_cb.cur_retry < RW_MAX_RETRIES) {
580 /* retry sending the command */
581 rw_cb.cur_retry++;
582
583 LOG(VERBOSE) << StringPrintf("%s: T1T retransmission attempt %i of %i",
584 __func__, rw_cb.cur_retry, RW_MAX_RETRIES);
585
586 /* allocate a new buffer for message */
587 p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
588 if (p_cmd_buf != nullptr) {
589 memcpy(p_cmd_buf, p_t1t->p_cur_cmd_buf,
590 sizeof(NFC_HDR) + p_t1t->p_cur_cmd_buf->offset +
591 p_t1t->p_cur_cmd_buf->len);
592
593 #if (RW_STATS_INCLUDED == TRUE)
594 /* Update stats */
595 rw_main_update_tx_stats(p_cmd_buf->len, true);
596 #endif /* RW_STATS_INCLUDED */
597
598 if (NFC_SendData(NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) {
599 /* Start timer for waiting for response */
600 nfc_start_quick_timer(
601 &p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE,
602 (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
603
604 return;
605 }
606 }
607 } else {
608 /* we might get response later to all or some of the retrasnmission
609 * of the current command, update previous command response information */
610 LOG(VERBOSE) << StringPrintf(
611 "%s: T1T maximum retransmission attempts reached (%i)", __func__,
612 RW_MAX_RETRIES);
613 p_t1t->prev_cmd_rsp_info.addr = ((p_cmd_rsp_info->opcode != T1T_CMD_RALL) &&
614 (p_cmd_rsp_info->opcode != T1T_CMD_RID))
615 ? p_t1t->addr
616 : 0;
617 p_t1t->prev_cmd_rsp_info.rsp_len = p_cmd_rsp_info->rsp_len;
618 p_t1t->prev_cmd_rsp_info.op_code = p_cmd_rsp_info->opcode;
619 p_t1t->prev_cmd_rsp_info.pend_retx_rsp = RW_MAX_RETRIES;
620 }
621
622 #if (RW_STATS_INCLUDED == TRUE)
623 /* update failure count */
624 rw_main_update_fail_stats();
625 #endif /* RW_STATS_INCLUDED */
626
627 rw_event = rw_t1t_info_to_event(p_cmd_rsp_info);
628 if (p_t1t->state != RW_T1T_STATE_NOT_ACTIVATED) rw_t1t_handle_op_complete();
629
630 if (rw_event == RW_T1T_NDEF_DETECT_EVT) {
631 tRW_DETECT_NDEF_DATA ndef_data;
632 ndef_data.status = NFC_STATUS_TIMEOUT;
633 ndef_data.protocol = NFC_PROTOCOL_T1T;
634 ndef_data.flags = RW_NDEF_FL_UNKNOWN;
635 ndef_data.max_size = 0;
636 ndef_data.cur_size = 0;
637 tRW_DATA rw_data;
638 rw_data.ndef = ndef_data;
639 (*rw_cb.p_cback)(rw_event, &rw_data);
640 } else {
641 tRW_READ_DATA evt_data;
642 evt_data.status = NFC_STATUS_TIMEOUT;
643 evt_data.p_data = nullptr;
644 tRW_DATA rw_data;
645 rw_data.data = evt_data;
646 (*rw_cb.p_cback)(rw_event, &rw_data);
647 }
648 }
649
650 /*****************************************************************************
651 **
652 ** Function rw_t1t_handle_presence_check_rsp
653 **
654 ** Description Handle response to presence check
655 **
656 ** Returns Nothing
657 **
658 *****************************************************************************/
rw_t1t_handle_presence_check_rsp(tNFC_STATUS status)659 void rw_t1t_handle_presence_check_rsp(tNFC_STATUS status) {
660 tRW_DATA rw_data;
661
662 /* Notify, Tag is present or not */
663 rw_data.data.status = status;
664 LOG(VERBOSE) << StringPrintf("%s: T1T rsp status = %d ", __func__, status);
665 rw_t1t_handle_op_complete();
666
667 (*(rw_cb.p_cback))(RW_T1T_PRESENCE_CHECK_EVT, &rw_data);
668 }
669
670 /*****************************************************************************
671 **
672 ** Function rw_t1t_handle_op_complete
673 **
674 ** Description Reset to IDLE state
675 **
676 ** Returns Nothing
677 **
678 *****************************************************************************/
rw_t1t_handle_op_complete(void)679 void rw_t1t_handle_op_complete(void) {
680 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
681
682 p_t1t->state = RW_T1T_STATE_IDLE;
683 #if (RW_NDEF_INCLUDED == TRUE)
684 if (appl_dta_mode_flag == 0 && (p_t1t->state != RW_T1T_STATE_READ_NDEF)) {
685 p_t1t->b_update = false;
686 p_t1t->b_rseg = false;
687 }
688 p_t1t->substate = RW_T1T_SUBSTATE_NONE;
689 #endif
690 return;
691 }
692
693 /*****************************************************************************
694 **
695 ** Function RW_T1tPresenceCheck
696 **
697 ** Description
698 ** Check if the tag is still in the field.
699 **
700 ** The RW_T1T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
701 ** or non-presence.
702 **
703 ** Returns
704 ** NFC_STATUS_OK, if raw data frame sent
705 ** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
706 ** NFC_STATUS_FAILED: other error
707 **
708 *****************************************************************************/
RW_T1tPresenceCheck(void)709 tNFC_STATUS RW_T1tPresenceCheck(void) {
710 tNFC_STATUS retval = NFC_STATUS_OK;
711 tRW_DATA evt_data;
712 tRW_CB* p_rw_cb = &rw_cb;
713
714 LOG(VERBOSE) << __func__;
715
716 /* If RW_SelectTagType was not called (no conn_callback) return failure */
717 if (!p_rw_cb->p_cback) {
718 retval = NFC_STATUS_FAILED;
719 }
720 /* If we are not activated, then RW_T1T_PRESENCE_CHECK_EVT status=FAIL */
721 else if (p_rw_cb->tcb.t1t.state == RW_T1T_STATE_NOT_ACTIVATED) {
722 evt_data.status = NFC_STATUS_FAILED;
723 (*p_rw_cb->p_cback)(RW_T1T_PRESENCE_CHECK_EVT, &evt_data);
724 }
725 /* If command is pending, assume tag is still present */
726 else if (p_rw_cb->tcb.t1t.state != RW_T1T_STATE_IDLE) {
727 evt_data.status = NFC_STATUS_OK;
728 (*p_rw_cb->p_cback)(RW_T1T_PRESENCE_CHECK_EVT, &evt_data);
729 } else {
730 /* IDLE state: send a RID command to the tag to see if it responds */
731 retval = rw_t1t_send_static_cmd(T1T_CMD_RID, 0, 0);
732 if (retval == NFC_STATUS_OK) {
733 p_rw_cb->tcb.t1t.state = RW_T1T_STATE_CHECK_PRESENCE;
734 }
735 }
736
737 return (retval);
738 }
739
740 /*****************************************************************************
741 **
742 ** Function RW_T1tRid
743 **
744 ** Description
745 ** This function sends a RID command for Reader/Writer mode.
746 **
747 ** Returns
748 ** NFC_STATUS_OK, if raw data frame sent
749 ** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
750 ** NFC_STATUS_FAILED: other error
751 **
752 *****************************************************************************/
RW_T1tRid(void)753 tNFC_STATUS RW_T1tRid(void) {
754 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
755 tNFC_STATUS status = NFC_STATUS_FAILED;
756
757 LOG(VERBOSE) << __func__;
758
759 if (p_t1t->state != RW_T1T_STATE_IDLE) {
760 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
761 return (NFC_STATUS_BUSY);
762 }
763
764 /* send a RID command */
765 status = rw_t1t_send_static_cmd(T1T_CMD_RID, 0, 0);
766 if (status == NFC_STATUS_OK) {
767 p_t1t->state = RW_T1T_STATE_READ;
768 }
769
770 return (status);
771 }
772
773 /*******************************************************************************
774 **
775 ** Function RW_T1tReadAll
776 **
777 ** Description This function sends a RALL command for Reader/Writer mode.
778 **
779 ** Returns tNFC_STATUS
780 **
781 *******************************************************************************/
RW_T1tReadAll(void)782 tNFC_STATUS RW_T1tReadAll(void) {
783 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
784 tNFC_STATUS status = NFC_STATUS_FAILED;
785
786 LOG(VERBOSE) << __func__;
787
788 if (p_t1t->state != RW_T1T_STATE_IDLE) {
789 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
790 return (NFC_STATUS_BUSY);
791 }
792
793 /* send RALL command */
794 status = rw_t1t_send_static_cmd(T1T_CMD_RALL, 0, 0);
795 if (status == NFC_STATUS_OK) {
796 p_t1t->state = RW_T1T_STATE_READ;
797 }
798
799 return status;
800 }
801
802 /*******************************************************************************
803 **
804 ** Function RW_T1tRead
805 **
806 ** Description This function sends a READ command for Reader/Writer mode.
807 **
808 ** Returns tNFC_STATUS
809 **
810 *******************************************************************************/
RW_T1tRead(uint8_t block,uint8_t byte)811 tNFC_STATUS RW_T1tRead(uint8_t block, uint8_t byte) {
812 tNFC_STATUS status = NFC_STATUS_FAILED;
813 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
814 uint8_t addr;
815
816 if (p_t1t->state != RW_T1T_STATE_IDLE) {
817 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
818 return (NFC_STATUS_BUSY);
819 }
820
821 /* send READ command */
822 RW_T1T_BLD_ADD((addr), (block), (byte));
823 status = rw_t1t_send_static_cmd(T1T_CMD_READ, addr, 0);
824 if (status == NFC_STATUS_OK) {
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
835 ** mode.
836 **
837 ** Returns tNFC_STATUS
838 **
839 *******************************************************************************/
RW_T1tWriteErase(uint8_t block,uint8_t byte,uint8_t new_byte)840 tNFC_STATUS RW_T1tWriteErase(uint8_t block, uint8_t byte, uint8_t new_byte) {
841 tNFC_STATUS status = NFC_STATUS_FAILED;
842 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
843 uint8_t addr;
844
845 if (p_t1t->state != RW_T1T_STATE_IDLE) {
846 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
847 return (NFC_STATUS_BUSY);
848 }
849 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) &&
850 (block != T1T_CC_BLOCK) && (byte != T1T_CC_RWA_OFFSET)) {
851 LOG(ERROR) << StringPrintf("%s: Tag is in Read only state", __func__);
852 return (NFC_STATUS_REFUSED);
853 }
854 if ((block >= T1T_STATIC_BLOCKS) || (byte >= T1T_BLOCK_SIZE)) {
855 LOG(ERROR) << StringPrintf("%s: Invalid Block/byte=%u / %u", __func__,
856 block, byte);
857 return (NFC_STATUS_REFUSED);
858 }
859 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) {
860 LOG(WARNING) << StringPrintf("%s: Cannot write to Locked block=%u",
861 __func__, block);
862 return (NFC_STATUS_REFUSED);
863 }
864 /* send WRITE-E command */
865 RW_T1T_BLD_ADD((addr), (block), (byte));
866 status = rw_t1t_send_static_cmd(T1T_CMD_WRITE_E, addr, new_byte);
867 if (status == NFC_STATUS_OK) {
868 p_t1t->state = RW_T1T_STATE_WRITE;
869 if (block < T1T_BLOCKS_PER_SEGMENT) {
870 p_t1t->b_update = false;
871 p_t1t->b_rseg = false;
872 }
873 }
874 return status;
875 }
876
877 /*******************************************************************************
878 **
879 ** Function RW_T1tWriteNoErase
880 **
881 ** Description This function sends a WRITE-NE command for Reader/Writer
882 ** mode.
883 **
884 ** Returns tNFC_STATUS
885 **
886 *******************************************************************************/
RW_T1tWriteNoErase(uint8_t block,uint8_t byte,uint8_t new_byte)887 tNFC_STATUS RW_T1tWriteNoErase(uint8_t block, uint8_t byte, uint8_t new_byte) {
888 tNFC_STATUS status = NFC_STATUS_FAILED;
889 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
890 uint8_t addr;
891
892 if (p_t1t->state != RW_T1T_STATE_IDLE) {
893 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
894 return (NFC_STATUS_BUSY);
895 }
896 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) &&
897 (block != T1T_CC_BLOCK) && (byte != T1T_CC_RWA_OFFSET)) {
898 LOG(ERROR) << StringPrintf("%s: Tag is in Read only state", __func__);
899 return (NFC_STATUS_REFUSED);
900 }
901 if ((block >= T1T_STATIC_BLOCKS) || (byte >= T1T_BLOCK_SIZE)) {
902 LOG(ERROR) << StringPrintf("%s: Invalid Block/byte=%u / %u", __func__,
903 block, byte);
904 return (NFC_STATUS_REFUSED);
905 }
906 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) {
907 LOG(WARNING) << StringPrintf("%s: Cannot write to Locked block=%u",
908 __func__, block);
909 return (NFC_STATUS_REFUSED);
910 }
911 /* send WRITE-NE command */
912 RW_T1T_BLD_ADD((addr), (block), (byte));
913 status = rw_t1t_send_static_cmd(T1T_CMD_WRITE_NE, addr, new_byte);
914 if (status == NFC_STATUS_OK) {
915 p_t1t->state = RW_T1T_STATE_WRITE;
916 if (block < T1T_BLOCKS_PER_SEGMENT) {
917 p_t1t->b_update = false;
918 p_t1t->b_rseg = false;
919 }
920 }
921 return status;
922 }
923
924 /*******************************************************************************
925 **
926 ** Function RW_T1tReadSeg
927 **
928 ** Description This function sends a RSEG command for Reader/Writer mode.
929 **
930 ** Returns tNFC_STATUS
931 **
932 *******************************************************************************/
RW_T1tReadSeg(uint8_t segment)933 tNFC_STATUS RW_T1tReadSeg(uint8_t segment) {
934 tNFC_STATUS status = NFC_STATUS_FAILED;
935 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
936 uint8_t adds;
937
938 if (p_t1t->state != RW_T1T_STATE_IDLE) {
939 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
940 return (NFC_STATUS_BUSY);
941 }
942 if (segment >= T1T_MAX_SEGMENTS) {
943 LOG(ERROR) << StringPrintf("%s: Invalid Segment=%u", __func__, 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("%s: Busy - State=%u", __func__, p_t1t->state);
972 return (NFC_STATUS_BUSY);
973 }
974
975 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 ||
976 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) {
977 /* send READ8 command */
978 status = rw_t1t_send_dyn_cmd(T1T_CMD_READ8, block, nullptr);
979 if (status == NFC_STATUS_OK) {
980 p_t1t->state = RW_T1T_STATE_READ;
981 }
982 }
983 return status;
984 }
985
986 /*******************************************************************************
987 **
988 ** Function RW_T1tWriteErase8
989 **
990 ** Description This function sends a WRITE-E8 command for Reader/Writer
991 ** mode.
992 **
993 ** Returns tNFC_STATUS
994 **
995 *******************************************************************************/
RW_T1tWriteErase8(uint8_t block,uint8_t * p_new_dat)996 tNFC_STATUS RW_T1tWriteErase8(uint8_t block, uint8_t* p_new_dat) {
997 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
998 tNFC_STATUS status = NFC_STATUS_FAILED;
999
1000 if (p_t1t->state != RW_T1T_STATE_IDLE) {
1001 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
1002 return (NFC_STATUS_BUSY);
1003 }
1004
1005 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) &&
1006 (block != T1T_CC_BLOCK)) {
1007 LOG(ERROR) << StringPrintf("%s: Tag is in Read only state", __func__);
1008 return (NFC_STATUS_REFUSED);
1009 }
1010
1011 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) {
1012 LOG(WARNING) << StringPrintf("%s: Cannot write to Locked block=%u",
1013 __func__, block);
1014 return (NFC_STATUS_REFUSED);
1015 }
1016
1017 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 ||
1018 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) {
1019 /* send WRITE-E8 command */
1020 status = rw_t1t_send_dyn_cmd(T1T_CMD_WRITE_E8, block, p_new_dat);
1021 if (status == NFC_STATUS_OK) {
1022 p_t1t->state = RW_T1T_STATE_WRITE;
1023 if (block < T1T_BLOCKS_PER_SEGMENT) {
1024 p_t1t->b_update = false;
1025 p_t1t->b_rseg = false;
1026 }
1027 }
1028 }
1029 return status;
1030 }
1031
1032 /*******************************************************************************
1033 **
1034 ** Function RW_T1tWriteNoErase8
1035 **
1036 ** Description This function sends a WRITE-NE8 command for Reader/Writer
1037 ** mode.
1038 **
1039 ** Returns tNFC_STATUS
1040 **
1041 *******************************************************************************/
RW_T1tWriteNoErase8(uint8_t block,uint8_t * p_new_dat)1042 tNFC_STATUS RW_T1tWriteNoErase8(uint8_t block, uint8_t* p_new_dat) {
1043 tNFC_STATUS status = NFC_STATUS_FAILED;
1044 tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t;
1045
1046 if (p_t1t->state != RW_T1T_STATE_IDLE) {
1047 LOG(WARNING) << StringPrintf("%s: Busy - State=%u", __func__, p_t1t->state);
1048 return (NFC_STATUS_BUSY);
1049 }
1050
1051 if ((p_t1t->tag_attribute == RW_T1_TAG_ATTRB_READ_ONLY) &&
1052 (block != T1T_CC_BLOCK)) {
1053 LOG(ERROR) << StringPrintf("%s: Tag is in Read only state", __func__);
1054 return (NFC_STATUS_REFUSED);
1055 }
1056
1057 if ((block == T1T_UID_BLOCK) || (block == T1T_RES_BLOCK)) {
1058 LOG(WARNING) << StringPrintf("%s: Cannot write to Locked block=%u",
1059 __func__, block);
1060 return (NFC_STATUS_REFUSED);
1061 }
1062
1063 if (rw_cb.tcb.t1t.hr[0] != T1T_STATIC_HR0 ||
1064 rw_cb.tcb.t1t.hr[1] >= RW_T1T_HR1_MIN) {
1065 /* send WRITE-NE command */
1066 status = rw_t1t_send_dyn_cmd(T1T_CMD_WRITE_NE8, block, p_new_dat);
1067 if (status == NFC_STATUS_OK) {
1068 p_t1t->state = RW_T1T_STATE_WRITE;
1069 if (block < T1T_BLOCKS_PER_SEGMENT) {
1070 p_t1t->b_update = false;
1071 p_t1t->b_rseg = false;
1072 }
1073 }
1074 }
1075 return status;
1076 }
1077
1078 /*******************************************************************************
1079 **
1080 ** Function rw_t1t_get_state_name
1081 **
1082 ** Description This function returns the state name.
1083 **
1084 ** NOTE conditionally compiled to save memory.
1085 **
1086 ** Returns pointer to the name
1087 **
1088 *******************************************************************************/
rw_t1t_get_state_name(uint8_t state)1089 static std::string rw_t1t_get_state_name(uint8_t state) {
1090 switch (state) {
1091 case RW_T1T_STATE_IDLE:
1092 return "IDLE";
1093 case RW_T1T_STATE_NOT_ACTIVATED:
1094 return "NOT_ACTIVATED";
1095 case RW_T1T_STATE_READ:
1096 return "APP_READ";
1097 case RW_T1T_STATE_WRITE:
1098 return "APP_WRITE";
1099 case RW_T1T_STATE_TLV_DETECT:
1100 return "TLV_DETECTION";
1101 case RW_T1T_STATE_READ_NDEF:
1102 return "READING_NDEF";
1103 case RW_T1T_STATE_WRITE_NDEF:
1104 return "WRITING_NDEF";
1105 case RW_T1T_STATE_SET_TAG_RO:
1106 return "SET_TAG_RO";
1107 case RW_T1T_STATE_CHECK_PRESENCE:
1108 return "CHECK_PRESENCE";
1109 case RW_T1T_STATE_FORMAT_TAG:
1110 return "FORMAT_TAG";
1111 default:
1112 return "???? UNKNOWN STATE";
1113 }
1114 }
1115