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