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