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 */
36static tRW_EVENT rw_t1t_handle_rid_rsp(NFC_HDR* p_pkt);
37static void rw_t1t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
38                              tNFC_CONN* p_data);
39static void rw_t1t_process_frame_error(void);
40static void rw_t1t_process_error(void);
41static void rw_t1t_handle_presence_check_rsp(tNFC_STATUS status);
42#if (BT_TRACE_VERBOSE == TRUE)
43static char* rw_t1t_get_state_name(uint8_t state);
44static char* rw_t1t_get_sub_state_name(uint8_t sub_state);
45static 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*******************************************************************************/
57static 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*******************************************************************************/
227void 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*******************************************************************************/
324tNFC_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*******************************************************************************/
383tNFC_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*****************************************************************************/
447static 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*******************************************************************************/
492tNFC_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*******************************************************************************/
528void 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*******************************************************************************/
557static 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*******************************************************************************/
576static 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*****************************************************************************/
661void 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*****************************************************************************/
680void 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*****************************************************************************/
710tNFC_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*****************************************************************************/
754tNFC_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*******************************************************************************/
783tNFC_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*******************************************************************************/
812tNFC_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*******************************************************************************/
841tNFC_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*******************************************************************************/
888tNFC_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*******************************************************************************/
934tNFC_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*******************************************************************************/
967tNFC_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*******************************************************************************/
997tNFC_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*******************************************************************************/
1043tNFC_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*******************************************************************************/
1091static 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