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 2 tag in Reader/Writer
22 * mode.
23 *
24 ******************************************************************************/
25 #include <android-base/logging.h>
26 #include <android-base/stringprintf.h>
27
28 #include <string>
29
30 #include "bt_types.h"
31 #include "gki.h"
32 #include "nci_hmsgs.h"
33 #include "nfc_api.h"
34 #include "nfc_int.h"
35 #include "nfc_target.h"
36 #include "rw_api.h"
37 #include "rw_int.h"
38
39 using android::base::StringPrintf;
40
41 /* Static local functions */
42 static void rw_t2t_proc_data(uint8_t conn_id, tNFC_DATA_CEVT* p_data);
43 static tNFC_STATUS rw_t2t_send_cmd(uint8_t opcode, uint8_t* p_dat);
44 static void rw_t2t_process_error(void);
45 static void rw_t2t_process_frame_error(void);
46 static void rw_t2t_handle_presence_check_rsp(tNFC_STATUS status);
47 static void rw_t2t_resume_op(void);
48
49 static std::string rw_t2t_get_state_name(uint8_t state);
50 static std::string rw_t2t_get_substate_name(uint8_t substate);
51
52 /*******************************************************************************
53 **
54 ** Function rw_t2t_proc_data
55 **
56 ** Description This function handles data evt received from NFC Controller.
57 **
58 ** Returns none
59 **
60 *******************************************************************************/
rw_t2t_proc_data(uint8_t conn_id,tNFC_DATA_CEVT * p_data)61 static void rw_t2t_proc_data(uint8_t conn_id, tNFC_DATA_CEVT* p_data) {
62 tRW_EVENT rw_event = RW_RAW_FRAME_EVT;
63 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
64 NFC_HDR* p_pkt = p_data->p_data;
65 bool b_notify = true;
66 bool b_release = true;
67 uint8_t* p;
68 tRW_READ_DATA evt_data = {};
69 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
70 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
71 tRW_DETECT_NDEF_DATA ndef_data;
72 uint8_t begin_state = p_t2t->state;
73
74 if ((p_t2t->state == RW_T2T_STATE_IDLE) || (p_cmd_rsp_info == nullptr)) {
75 LOG(VERBOSE) << StringPrintf("RW T2T Raw Frame: Len [0x%X] Status [%s]",
76 p_pkt->len,
77 NFC_GetStatusName(p_data->status).c_str());
78 evt_data.status = p_data->status;
79 evt_data.p_data = p_pkt;
80 tRW_DATA rw_data;
81 rw_data.data = evt_data;
82 (*rw_cb.p_cback)(RW_T2T_RAW_FRAME_EVT, &rw_data);
83 return;
84 }
85 #if (RW_STATS_INCLUDED == TRUE)
86 /* Update rx stats */
87 rw_main_update_rx_stats(p_pkt->len);
88 #endif
89 /* Stop timer as response is received */
90 nfc_stop_quick_timer(&p_t2t->t2_timer);
91
92 LOG(VERBOSE) << StringPrintf("RW RECV [%s]:0x%x RSP",
93 t2t_info_to_str(p_cmd_rsp_info),
94 p_cmd_rsp_info->opcode);
95
96 if (((p_pkt->len != p_cmd_rsp_info->rsp_len) &&
97 (p_pkt->len != p_cmd_rsp_info->nack_rsp_len) &&
98 (p_t2t->substate != RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR)) ||
99 (p_t2t->state == RW_T2T_STATE_HALT)) {
100 LOG(ERROR) << StringPrintf("T2T Frame error. state=%s ",
101 rw_t2t_get_state_name(p_t2t->state).c_str());
102 if (p_t2t->state != RW_T2T_STATE_HALT) {
103 /* Retrasmit the last sent command if retry-count < max retry */
104 rw_t2t_process_frame_error();
105 p_t2t->check_tag_halt = false;
106 }
107 GKI_freebuf(p_pkt);
108 return;
109 }
110 rw_cb.cur_retry = 0;
111
112 /* Assume the data is just the response byte sequence */
113 p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
114
115 LOG(VERBOSE) << StringPrintf(
116 "rw_t2t_proc_data State: %u conn_id: %u len: %u data[0]: 0x%02x",
117 p_t2t->state, conn_id, p_pkt->len, *p);
118
119 evt_data.p_data = nullptr;
120
121 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT) {
122 /* The select process happens in two steps */
123 if ((*p & 0x0f) == T2T_RSP_ACK) {
124 if (rw_t2t_sector_change(p_t2t->select_sector) == NFC_STATUS_OK)
125 b_notify = false;
126 else
127 evt_data.status = NFC_STATUS_FAILED;
128 } else {
129 LOG(VERBOSE) << StringPrintf(
130 "rw_t2t_proc_data - Received NACK response(0x%x) to SEC-SELCT CMD",
131 (*p & 0x0f));
132 evt_data.status = NFC_STATUS_REJECTED;
133 }
134 } else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR) {
135 evt_data.status = NFC_STATUS_FAILED;
136 } else if ((p_pkt->len != p_cmd_rsp_info->rsp_len) ||
137 ((p_cmd_rsp_info->opcode == T2T_CMD_WRITE) &&
138 ((*p & 0x0f) != T2T_RSP_ACK))) {
139 /* Received NACK response */
140 evt_data.p_data = p_pkt;
141 if (p_t2t->state == RW_T2T_STATE_READ) b_release = false;
142
143 LOG(VERBOSE) << StringPrintf(
144 "rw_t2t_proc_data - Received NACK response(0x%x)", (*p & 0x0f));
145
146 if (!p_t2t->check_tag_halt) {
147 /* Just received first NACK. Retry just one time to find if tag went in to
148 * HALT State */
149 b_notify = false;
150 rw_t2t_process_error();
151 /* Assume Tag is in HALT State, untill we get response to retry command */
152 p_t2t->check_tag_halt = true;
153 } else {
154 p_t2t->check_tag_halt = false;
155 /* Got consecutive NACK so tag not really halt after first NACK, but
156 * current operation failed */
157 evt_data.status = NFC_STATUS_FAILED;
158 }
159 } else {
160 /* If the response length indicates positive response or cannot be known
161 * from length then assume success */
162 evt_data.status = NFC_STATUS_OK;
163 p_t2t->check_tag_halt = false;
164
165 /* The response data depends on what the current operation was */
166 switch (p_t2t->state) {
167 case RW_T2T_STATE_CHECK_PRESENCE:
168 b_notify = false;
169 rw_t2t_handle_presence_check_rsp(NFC_STATUS_OK);
170 break;
171
172 case RW_T2T_STATE_READ:
173 evt_data.p_data = p_pkt;
174 b_release = false;
175 if (p_t2t->block_read == 0) {
176 p_t2t->b_read_hdr = true;
177 memcpy(p_t2t->tag_hdr, p, T2T_READ_DATA_LEN);
178 }
179 break;
180
181 case RW_T2T_STATE_WRITE:
182 /* Write operation completed successfully */
183 break;
184
185 default:
186 /* NDEF/other Tlv Operation/Format-Tag/Config Tag as Read only */
187 b_notify = false;
188 rw_t2t_handle_rsp(p);
189 break;
190 }
191 }
192
193 if (b_notify) {
194 rw_event = rw_t2t_info_to_event(p_cmd_rsp_info);
195
196 if (rw_event == RW_T2T_NDEF_DETECT_EVT) {
197 ndef_data.status = evt_data.status;
198 ndef_data.protocol = NFC_PROTOCOL_T2T;
199 ndef_data.flags = RW_NDEF_FL_UNKNOWN;
200 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS)
201 ndef_data.flags = RW_NDEF_FL_FORMATED;
202 ndef_data.max_size = 0;
203 ndef_data.cur_size = 0;
204 /* Move back to idle state */
205 rw_t2t_handle_op_complete();
206 tRW_DATA rw_data;
207 rw_data.ndef = ndef_data;
208 (*rw_cb.p_cback)(rw_event, &rw_data);
209 } else {
210 /* Move back to idle state */
211 rw_t2t_handle_op_complete();
212 tRW_DATA rw_data;
213 rw_data.data = evt_data;
214 (*rw_cb.p_cback)(rw_event, &rw_data);
215 }
216 }
217
218 if (b_release) GKI_freebuf(p_pkt);
219
220 if (begin_state != p_t2t->state) {
221 LOG(VERBOSE) << StringPrintf("RW T2T state changed:<%s> -> <%s>",
222 rw_t2t_get_state_name(begin_state).c_str(),
223 rw_t2t_get_state_name(p_t2t->state).c_str());
224 }
225 }
226
227 /*******************************************************************************
228 **
229 ** Function rw_t2t_conn_cback
230 **
231 ** Description This callback function receives events/data from NFCC.
232 **
233 ** Returns none
234 **
235 *******************************************************************************/
rw_t2t_conn_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)236 void rw_t2t_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event,
237 tNFC_CONN* p_data) {
238 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
239 tRW_READ_DATA evt_data;
240
241 LOG(VERBOSE) << StringPrintf("rw_t2t_conn_cback: conn_id=%i, evt=%i", conn_id,
242 event);
243 /* Only handle static conn_id */
244 if (conn_id != NFC_RF_CONN_ID) {
245 return;
246 }
247
248 switch (event) {
249 case NFC_CONN_CREATE_CEVT:
250 case NFC_CONN_CLOSE_CEVT:
251 break;
252
253 case NFC_DEACTIVATE_CEVT:
254 #if (RW_STATS_INCLUDED == TRUE)
255 /* Display stats */
256 rw_main_log_stats();
257 #endif
258 /* Stop t2t timer (if started) */
259 nfc_stop_quick_timer(&p_t2t->t2_timer);
260
261 /* Free cmd buf for retransmissions */
262 if (p_t2t->p_cur_cmd_buf) {
263 GKI_freebuf(p_t2t->p_cur_cmd_buf);
264 p_t2t->p_cur_cmd_buf = nullptr;
265 }
266 /* Free cmd buf used to hold command before sector change */
267 if (p_t2t->p_sec_cmd_buf) {
268 GKI_freebuf(p_t2t->p_sec_cmd_buf);
269 p_t2t->p_sec_cmd_buf = nullptr;
270 }
271
272 p_t2t->state = RW_T2T_STATE_NOT_ACTIVATED;
273 NFC_SetStaticRfCback(nullptr);
274 break;
275
276 case NFC_DATA_CEVT:
277 if (p_data != nullptr) {
278 if ((p_data->data.status == NFC_STATUS_OK) ||
279 (p_data->data.status == NFC_STATUS_CONTINUE)) {
280 rw_t2t_proc_data(conn_id, &(p_data->data));
281 break;
282 } else if (p_data->data.p_data != nullptr) {
283 /* Free the response buffer in case of error response */
284 GKI_freebuf((NFC_HDR*)(p_data->data.p_data));
285 p_data->data.p_data = nullptr;
286 }
287 }
288 /* Data event with error status...fall through to NFC_ERROR_CEVT case */
289 FALLTHROUGH_INTENDED;
290
291 case NFC_ERROR_CEVT:
292 if ((p_t2t->state == RW_T2T_STATE_NOT_ACTIVATED) ||
293 (p_t2t->state == RW_T2T_STATE_IDLE) ||
294 (p_t2t->state == RW_T2T_STATE_HALT)) {
295 #if (RW_STATS_INCLUDED == TRUE)
296 rw_main_update_trans_error_stats();
297 #endif /* RW_STATS_INCLUDED */
298 if (event == NFC_ERROR_CEVT)
299 evt_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
300 else if (p_data)
301 evt_data.status = p_data->status;
302 else
303 evt_data.status = NFC_STATUS_FAILED;
304
305 evt_data.p_data = nullptr;
306 tRW_DATA rw_data;
307 rw_data.data = evt_data;
308 (*rw_cb.p_cback)(RW_T2T_INTF_ERROR_EVT, &rw_data);
309 break;
310 }
311 nfc_stop_quick_timer(&p_t2t->t2_timer);
312 #if (RW_STATS_INCLUDED == TRUE)
313 rw_main_update_trans_error_stats();
314 #endif
315 if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE) {
316 if (p_t2t->check_tag_halt) {
317 p_t2t->state = RW_T2T_STATE_HALT;
318 rw_t2t_handle_presence_check_rsp(NFC_STATUS_REJECTED);
319 } else {
320 /* Move back to idle state */
321 rw_t2t_handle_presence_check_rsp(NFC_STATUS_RF_FRAME_CORRUPTED);
322 }
323 } else {
324 rw_t2t_process_error();
325 }
326 break;
327
328 default:
329 break;
330 }
331 }
332
333 /*******************************************************************************
334 **
335 ** Function rw_t2t_send_cmd
336 **
337 ** Description This function composes a Type 2 Tag command and send it via
338 ** NCI to NFCC.
339 **
340 ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI
341 ** otherwise, error status
342 **
343 *******************************************************************************/
rw_t2t_send_cmd(uint8_t opcode,uint8_t * p_dat)344 tNFC_STATUS rw_t2t_send_cmd(uint8_t opcode, uint8_t* p_dat) {
345 tNFC_STATUS status = NFC_STATUS_FAILED;
346 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
347 const tT2T_CMD_RSP_INFO* p_cmd_rsp_info = t2t_cmd_to_rsp_info(opcode);
348 NFC_HDR* p_data;
349 uint8_t* p;
350
351 if (p_cmd_rsp_info) {
352 /* a valid opcode for RW */
353 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
354 if (p_data) {
355 p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO*)p_cmd_rsp_info;
356 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
357 p = (uint8_t*)(p_data + 1) + p_data->offset;
358
359 UINT8_TO_STREAM(p, opcode);
360
361 if (p_dat) {
362 ARRAY_TO_STREAM(p, p_dat, (p_cmd_rsp_info->cmd_len - 1));
363 }
364
365 p_data->len = p_cmd_rsp_info->cmd_len;
366
367 /* Indicate first attempt to send command, back up cmd buffer in case
368 * needed for retransmission */
369 rw_cb.cur_retry = 0;
370 memcpy(p_t2t->p_cur_cmd_buf, p_data,
371 sizeof(NFC_HDR) + p_data->offset + p_data->len);
372
373 #if (RW_STATS_INCLUDED == TRUE)
374 /* Update stats */
375 rw_main_update_tx_stats(p_data->len, false);
376 #endif
377 LOG(VERBOSE) << StringPrintf("RW SENT [%s]:0x%x CMD",
378 t2t_info_to_str(p_cmd_rsp_info),
379 p_cmd_rsp_info->opcode);
380
381 status = NFC_SendData(NFC_RF_CONN_ID, p_data);
382 if (status == NFC_STATUS_OK) {
383 nfc_start_quick_timer(
384 &p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
385 (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
386 } else {
387 LOG(ERROR) << StringPrintf(
388 "T2T NFC Send data failed. state=%s substate=%s ",
389 rw_t2t_get_state_name(p_t2t->state).c_str(),
390 rw_t2t_get_substate_name(p_t2t->substate).c_str());
391 }
392 } else {
393 status = NFC_STATUS_NO_BUFFERS;
394 }
395 }
396 return status;
397 }
398
399 /*******************************************************************************
400 **
401 ** Function rw_t2t_process_timeout
402 **
403 ** Description handles timeout event
404 **
405 ** Returns none
406 **
407 *******************************************************************************/
rw_t2t_process_timeout()408 void rw_t2t_process_timeout() {
409 tRW_READ_DATA evt_data;
410 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
411
412 if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE) {
413 if (p_t2t->check_tag_halt) {
414 p_t2t->state = RW_T2T_STATE_HALT;
415 rw_t2t_handle_presence_check_rsp(NFC_STATUS_REJECTED);
416 } else {
417 /* Move back to idle state */
418 rw_t2t_handle_presence_check_rsp(NFC_STATUS_RF_FRAME_CORRUPTED);
419 }
420 return;
421 }
422
423 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR) {
424 p_t2t->sector = p_t2t->select_sector;
425 /* Here timeout is an acknowledgment for successfull sector change */
426 if (p_t2t->state == RW_T2T_STATE_SELECT_SECTOR) {
427 /* Notify that select sector op is successfull */
428 rw_t2t_handle_op_complete();
429 evt_data.status = NFC_STATUS_OK;
430 evt_data.p_data = nullptr;
431 tRW_DATA rw_data;
432 rw_data.data = evt_data;
433 (*rw_cb.p_cback)(RW_T2T_SELECT_CPLT_EVT, &rw_data);
434 } else {
435 /* Resume operation from where we stopped before sector change */
436 rw_t2t_resume_op();
437 }
438 } else if (p_t2t->state != RW_T2T_STATE_IDLE) {
439 LOG(ERROR) << StringPrintf("T2T timeout. state=%s ",
440 rw_t2t_get_state_name(p_t2t->state).c_str());
441 /* Handle timeout error as no response to the command sent */
442 rw_t2t_process_error();
443 }
444 }
445
446 /*******************************************************************************
447 **
448 ** Function rw_t2t_process_frame_error
449 **
450 ** Description handles frame crc error
451 **
452 ** Returns none
453 **
454 *******************************************************************************/
rw_t2t_process_frame_error(void)455 static void rw_t2t_process_frame_error(void) {
456 #if (RW_STATS_INCLUDED == TRUE)
457 /* Update stats */
458 rw_main_update_crc_error_stats();
459 #endif
460 /* Process the error */
461 rw_t2t_process_error();
462 }
463
464 /*******************************************************************************
465 **
466 ** Function rw_t2t_process_error
467 **
468 ** Description Process error including Timeout, Frame error. This function
469 ** will retry atleast till RW_MAX_RETRIES before give up and
470 ** sending negative notification to upper layer
471 **
472 ** Returns none
473 **
474 *******************************************************************************/
rw_t2t_process_error(void)475 static void rw_t2t_process_error(void) {
476 tRW_READ_DATA evt_data;
477 tRW_EVENT rw_event;
478 NFC_HDR* p_cmd_buf;
479 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
480 tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
481 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
482 tRW_DETECT_NDEF_DATA ndef_data;
483
484 LOG(VERBOSE) << StringPrintf("State: %u", p_t2t->state);
485
486 /* Retry sending command if retry-count < max */
487 if ((!p_t2t->check_tag_halt) && (rw_cb.cur_retry < RW_MAX_RETRIES)) {
488 /* retry sending the command */
489 rw_cb.cur_retry++;
490
491 LOG(VERBOSE) << StringPrintf("T2T retransmission attempt %i of %i",
492 rw_cb.cur_retry, RW_MAX_RETRIES);
493
494 /* allocate a new buffer for message */
495 p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
496 if (p_cmd_buf != nullptr) {
497 memcpy(p_cmd_buf, p_t2t->p_cur_cmd_buf,
498 sizeof(NFC_HDR) + p_t2t->p_cur_cmd_buf->offset +
499 p_t2t->p_cur_cmd_buf->len);
500 #if (RW_STATS_INCLUDED == TRUE)
501 /* Update stats */
502 rw_main_update_tx_stats(p_cmd_buf->len, true);
503 #endif
504 if (NFC_SendData(NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) {
505 /* Start timer for waiting for response */
506 nfc_start_quick_timer(
507 &p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
508 (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
509
510 return;
511 }
512 }
513 } else {
514 if (p_t2t->check_tag_halt) {
515 LOG(VERBOSE) << StringPrintf("T2T Went to HALT State!");
516 } else {
517 LOG(VERBOSE) << StringPrintf(
518 "T2T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES);
519 }
520 }
521 rw_event = rw_t2t_info_to_event(p_cmd_rsp_info);
522 #if (RW_STATS_INCLUDED == TRUE)
523 /* update failure count */
524 rw_main_update_fail_stats();
525 #endif
526 if (p_t2t->check_tag_halt) {
527 evt_data.status = NFC_STATUS_REJECTED;
528 p_t2t->state = RW_T2T_STATE_HALT;
529 } else {
530 evt_data.status = NFC_STATUS_TIMEOUT;
531 }
532
533 if (rw_event == RW_T2T_NDEF_DETECT_EVT) {
534 ndef_data.status = evt_data.status;
535 ndef_data.protocol = NFC_PROTOCOL_T2T;
536 ndef_data.flags = RW_NDEF_FL_UNKNOWN;
537 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_READ_LOCKS)
538 ndef_data.flags = RW_NDEF_FL_FORMATED;
539 ndef_data.max_size = 0;
540 ndef_data.cur_size = 0;
541 /* If not Halt move to idle state */
542 rw_t2t_handle_op_complete();
543
544 tRW_DATA rw_data;
545 rw_data.ndef = ndef_data;
546 (*rw_cb.p_cback)(rw_event, &rw_data);
547 } else {
548 evt_data.p_data = nullptr;
549 /* If activated and not Halt move to idle state */
550 if (p_t2t->state != RW_T2T_STATE_NOT_ACTIVATED) rw_t2t_handle_op_complete();
551
552 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
553 tRW_DATA rw_data;
554 rw_data.data = evt_data;
555 (*rw_cb.p_cback)(rw_event, &rw_data);
556 }
557 }
558
559 /*****************************************************************************
560 **
561 ** Function rw_t2t_handle_presence_check_rsp
562 **
563 ** Description Handle response to presence check
564 **
565 ** Returns Nothing
566 **
567 *****************************************************************************/
rw_t2t_handle_presence_check_rsp(tNFC_STATUS status)568 void rw_t2t_handle_presence_check_rsp(tNFC_STATUS status) {
569 tRW_DATA rw_data;
570
571 /* Notify, Tag is present or not */
572 rw_data.data.status = status;
573 rw_t2t_handle_op_complete();
574
575 (*rw_cb.p_cback)(RW_T2T_PRESENCE_CHECK_EVT, &rw_data);
576 }
577
578 /*******************************************************************************
579 **
580 ** Function rw_t2t_resume_op
581 **
582 ** Description This function will continue operation after moving to new
583 ** sector
584 **
585 ** Returns tNFC_STATUS
586 **
587 *******************************************************************************/
rw_t2t_resume_op(void)588 static void rw_t2t_resume_op(void) {
589 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
590 tRW_READ_DATA evt_data;
591 NFC_HDR* p_cmd_buf;
592 tRW_EVENT event;
593 const tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
594 (tT2T_CMD_RSP_INFO*)rw_cb.tcb.t2t.p_cmd_rsp_info;
595 uint8_t* p;
596
597 /* Move back to the substate where we were before changing sector */
598 p_t2t->substate = p_t2t->prev_substate;
599
600 p = (uint8_t*)(p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
601 p_cmd_rsp_info = t2t_cmd_to_rsp_info((uint8_t)*p);
602 p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO*)p_cmd_rsp_info;
603
604 /* allocate a new buffer for message */
605 p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
606 if (p_cmd_buf != nullptr) {
607 memcpy(p_cmd_buf, p_t2t->p_sec_cmd_buf,
608 sizeof(NFC_HDR) + p_t2t->p_sec_cmd_buf->offset +
609 p_t2t->p_sec_cmd_buf->len);
610 memcpy(p_t2t->p_cur_cmd_buf, p_t2t->p_sec_cmd_buf,
611 sizeof(NFC_HDR) + p_t2t->p_sec_cmd_buf->offset +
612 p_t2t->p_sec_cmd_buf->len);
613
614 #if (RW_STATS_INCLUDED == TRUE)
615 /* Update stats */
616 rw_main_update_tx_stats(p_cmd_buf->len, true);
617 #endif
618 if (NFC_SendData(NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) {
619 /* Start timer for waiting for response */
620 nfc_start_quick_timer(
621 &p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
622 (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
623 } else {
624 /* failure - could not send buffer */
625 evt_data.p_data = nullptr;
626 evt_data.status = NFC_STATUS_FAILED;
627 event = rw_t2t_info_to_event(p_cmd_rsp_info);
628 rw_t2t_handle_op_complete();
629 tRW_DATA rw_data;
630 rw_data.data = evt_data;
631 (*rw_cb.p_cback)(event, &rw_data);
632 }
633 }
634 }
635
636 /*******************************************************************************
637 **
638 ** Function rw_t2t_sector_change
639 **
640 ** Description This function issues Type 2 Tag SECTOR-SELECT command
641 ** packet 1.
642 **
643 ** Returns tNFC_STATUS
644 **
645 *******************************************************************************/
rw_t2t_sector_change(uint8_t sector)646 tNFC_STATUS rw_t2t_sector_change(uint8_t sector) {
647 tNFC_STATUS status;
648 NFC_HDR* p_data;
649 uint8_t* p;
650 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
651
652 p_data = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
653 if (p_data == nullptr) {
654 LOG(ERROR) << StringPrintf("rw_t2t_sector_change - No buffer");
655 return (NFC_STATUS_NO_BUFFERS);
656 }
657
658 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
659 p = (uint8_t*)(p_data + 1) + p_data->offset;
660
661 UINT8_TO_BE_STREAM(p, sector);
662 UINT8_TO_BE_STREAM(p, 0x00);
663 UINT8_TO_BE_STREAM(p, 0x00);
664 UINT8_TO_BE_STREAM(p, 0x00);
665
666 p_data->len = 4;
667
668 status = NFC_SendData(NFC_RF_CONN_ID, p_data);
669 if (status == NFC_STATUS_OK) {
670 /* Passive rsp command and suppose not to get response to this command */
671 p_t2t->p_cmd_rsp_info = nullptr;
672 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR;
673
674 LOG(VERBOSE) << StringPrintf("rw_t2t_sector_change Sent Second Command");
675 nfc_start_quick_timer(
676 &p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE,
677 (RW_T2T_SEC_SEL_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
678 } else {
679 LOG(ERROR) << StringPrintf(
680 "rw_t2t_sector_change Send failed at rw_t2t_send_cmd, error: %u",
681 status);
682 }
683
684 return status;
685 }
686
687 /*******************************************************************************
688 **
689 ** Function rw_t2t_read
690 **
691 ** Description This function issues Type 2 Tag READ command for the
692 ** specified block. If the specified block is in different
693 ** sector then it first sends command to move to new sector
694 ** and after the tag moves to new sector it issues the read
695 ** command for the block.
696 **
697 ** Returns tNFC_STATUS
698 **
699 *******************************************************************************/
rw_t2t_read(uint16_t block)700 tNFC_STATUS rw_t2t_read(uint16_t block) {
701 tNFC_STATUS status;
702 uint8_t* p;
703 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
704 uint8_t sector_byte2[1];
705 uint8_t read_cmd[1];
706
707 read_cmd[0] = block % T2T_BLOCKS_PER_SECTOR;
708 if (p_t2t->sector != block / T2T_BLOCKS_PER_SECTOR) {
709 sector_byte2[0] = 0xFF;
710 /* First Move to new sector before sending Read command */
711 status = rw_t2t_send_cmd(T2T_CMD_SEC_SEL, sector_byte2);
712 if (status == NFC_STATUS_OK) {
713 /* Prepare command that needs to be sent after sector change op is
714 * completed */
715 p_t2t->select_sector = (uint8_t)(block / T2T_BLOCKS_PER_SECTOR);
716 p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
717
718 p = (uint8_t*)(p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
719 UINT8_TO_BE_STREAM(p, T2T_CMD_READ);
720 UINT8_TO_BE_STREAM(p, read_cmd[0]);
721 p_t2t->p_sec_cmd_buf->len = 2;
722 p_t2t->block_read = block;
723
724 /* Backup the current substate to move back to this substate after
725 * changing sector */
726 p_t2t->prev_substate = p_t2t->substate;
727 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
728 return NFC_STATUS_OK;
729 }
730 return NFC_STATUS_FAILED;
731 }
732
733 /* Send Read command as sector change is not needed */
734 status = rw_t2t_send_cmd(T2T_CMD_READ, (uint8_t*)read_cmd);
735 if (status == NFC_STATUS_OK) {
736 p_t2t->block_read = block;
737 LOG(VERBOSE) << StringPrintf("rw_t2t_read Sent Command for Block: %u", block);
738 }
739
740 return status;
741 }
742
743 /*******************************************************************************
744 **
745 ** Function rw_t2t_write
746 **
747 ** Description This function issues Type 2 Tag WRITE command for the
748 ** specified block. If the specified block is in different
749 ** sector then it first sends command to move to new sector
750 ** and after the tag moves to new sector it issues the write
751 ** command for the block.
752 **
753 ** Returns tNFC_STATUS
754 **
755 *******************************************************************************/
rw_t2t_write(uint16_t block,uint8_t * p_write_data)756 tNFC_STATUS rw_t2t_write(uint16_t block, uint8_t* p_write_data) {
757 tNFC_STATUS status;
758 uint8_t* p;
759 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
760 uint8_t write_cmd[T2T_WRITE_DATA_LEN + 1];
761 uint8_t sector_byte2[1];
762
763 p_t2t->block_written = block;
764 write_cmd[0] = (uint8_t)(block % T2T_BLOCKS_PER_SECTOR);
765 memcpy(&write_cmd[1], p_write_data, T2T_WRITE_DATA_LEN);
766
767 if (p_t2t->sector != block / T2T_BLOCKS_PER_SECTOR) {
768 sector_byte2[0] = 0xFF;
769 /* First Move to new sector before sending Write command */
770 status = rw_t2t_send_cmd(T2T_CMD_SEC_SEL, sector_byte2);
771 if (status == NFC_STATUS_OK) {
772 /* Prepare command that needs to be sent after sector change op is
773 * completed */
774 p_t2t->select_sector = (uint8_t)(block / T2T_BLOCKS_PER_SECTOR);
775 p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
776 p = (uint8_t*)(p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset;
777 UINT8_TO_BE_STREAM(p, T2T_CMD_WRITE);
778 memcpy(p, write_cmd, T2T_WRITE_DATA_LEN + 1);
779 p_t2t->p_sec_cmd_buf->len = 2 + T2T_WRITE_DATA_LEN;
780 p_t2t->block_written = block;
781
782 /* Backup the current substate to move back to this substate after
783 * changing sector */
784 p_t2t->prev_substate = p_t2t->substate;
785 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
786 return NFC_STATUS_OK;
787 }
788 return NFC_STATUS_FAILED;
789 }
790
791 /* Send Write command as sector change is not needed */
792 status = rw_t2t_send_cmd(T2T_CMD_WRITE, write_cmd);
793 if (status == NFC_STATUS_OK) {
794 LOG(VERBOSE) << StringPrintf("rw_t2t_write Sent Command for Block: %u",
795 block);
796 }
797
798 return status;
799 }
800
801 /*******************************************************************************
802 **
803 ** Function rw_t2t_select
804 **
805 ** Description This function selects type 2 tag.
806 **
807 ** Returns Tag selection status
808 **
809 *******************************************************************************/
rw_t2t_select(void)810 tNFC_STATUS rw_t2t_select(void) {
811 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
812
813 p_t2t->state = RW_T2T_STATE_IDLE;
814 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED;
815
816 /* Alloc cmd buf for retransmissions */
817 if (p_t2t->p_cur_cmd_buf == nullptr) {
818 p_t2t->p_cur_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
819 if (p_t2t->p_cur_cmd_buf == nullptr) {
820 LOG(ERROR) << StringPrintf(
821 "rw_t2t_select: unable to allocate buffer for retransmission");
822 return (NFC_STATUS_FAILED);
823 }
824 }
825 /* Alloc cmd buf for holding a command untill sector changes */
826 if (p_t2t->p_sec_cmd_buf == nullptr) {
827 p_t2t->p_sec_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
828 if (p_t2t->p_sec_cmd_buf == nullptr) {
829 LOG(ERROR) << StringPrintf(
830 "rw_t2t_select: unable to allocate buffer used during sector change");
831 return (NFC_STATUS_FAILED);
832 }
833 }
834
835 NFC_SetStaticRfCback(rw_t2t_conn_cback);
836 rw_t2t_handle_op_complete();
837 p_t2t->check_tag_halt = false;
838
839 return NFC_STATUS_OK;
840 }
841
842 /*****************************************************************************
843 **
844 ** Function rw_t2t_handle_op_complete
845 **
846 ** Description Reset to IDLE state
847 **
848 ** Returns Nothing
849 **
850 *****************************************************************************/
rw_t2t_handle_op_complete(void)851 void rw_t2t_handle_op_complete(void) {
852 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
853
854 if ((p_t2t->state == RW_T2T_STATE_READ_NDEF) ||
855 (p_t2t->state == RW_T2T_STATE_WRITE_NDEF)) {
856 p_t2t->b_read_data = false;
857 }
858
859 if (p_t2t->state != RW_T2T_STATE_HALT) p_t2t->state = RW_T2T_STATE_IDLE;
860 p_t2t->substate = RW_T2T_SUBSTATE_NONE;
861 return;
862 }
863
864 /*****************************************************************************
865 **
866 ** Function RW_T2tPresenceCheck
867 **
868 ** Description
869 ** Check if the tag is still in the field.
870 **
871 ** The RW_T2T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
872 ** or non-presence.
873 **
874 ** Returns
875 ** NFC_STATUS_OK, if raw data frame sent
876 ** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
877 ** NFC_STATUS_FAILED: other error
878 **
879 *****************************************************************************/
RW_T2tPresenceCheck(void)880 tNFC_STATUS RW_T2tPresenceCheck(void) {
881 tNFC_STATUS retval = NFC_STATUS_OK;
882 tRW_DATA evt_data;
883 tRW_CB* p_rw_cb = &rw_cb;
884 uint8_t sector_blk = 0; /* block 0 of current sector */
885
886 LOG(VERBOSE) << __func__;
887
888 /* If RW_SelectTagType was not called (no conn_callback) return failure */
889 if (!p_rw_cb->p_cback) {
890 retval = NFC_STATUS_FAILED;
891 }
892 /* If we are not activated, then RW_T2T_PRESENCE_CHECK_EVT status=FAIL */
893 else if (p_rw_cb->tcb.t2t.state == RW_T2T_STATE_NOT_ACTIVATED) {
894 evt_data.status = NFC_STATUS_FAILED;
895 (*p_rw_cb->p_cback)(RW_T2T_PRESENCE_CHECK_EVT, &evt_data);
896 }
897 /* If command is pending, assume tag is still present */
898 else if (p_rw_cb->tcb.t2t.state != RW_T2T_STATE_IDLE) {
899 evt_data.status = NFC_STATUS_OK;
900 (*p_rw_cb->p_cback)(RW_T2T_PRESENCE_CHECK_EVT, &evt_data);
901 } else {
902 /* IDLE state: send a READ command to block 0 of the current sector */
903 retval = rw_t2t_send_cmd(T2T_CMD_READ, §or_blk);
904 if (retval == NFC_STATUS_OK) {
905 p_rw_cb->tcb.t2t.state = RW_T2T_STATE_CHECK_PRESENCE;
906 }
907 }
908
909 return (retval);
910 }
911
912 /*******************************************************************************
913 **
914 ** Function RW_T2tRead
915 **
916 ** Description This function issues the Type 2 Tag READ command. When the
917 ** operation is complete the callback function will be called
918 ** with a RW_T2T_READ_EVT.
919 **
920 ** Returns tNFC_STATUS
921 **
922 *******************************************************************************/
RW_T2tRead(uint16_t block)923 tNFC_STATUS RW_T2tRead(uint16_t block) {
924 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
925 tNFC_STATUS status;
926
927 if (p_t2t->state != RW_T2T_STATE_IDLE) {
928 LOG(ERROR) << StringPrintf(
929 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
930 return (NFC_STATUS_FAILED);
931 }
932
933 status = rw_t2t_read(block);
934 if (status == NFC_STATUS_OK) {
935 p_t2t->state = RW_T2T_STATE_READ;
936 LOG(VERBOSE) << StringPrintf("RW_T2tRead Sent Read command");
937 }
938
939 return status;
940 }
941
942 /*******************************************************************************
943 **
944 ** Function RW_T2tWrite
945 **
946 ** Description This function issues the Type 2 Tag WRITE command. When the
947 ** operation is complete the callback function will be called
948 ** with a RW_T2T_WRITE_EVT.
949 **
950 ** p_new_bytes points to the array of 4 bytes to be written
951 **
952 ** Returns tNFC_STATUS
953 **
954 *******************************************************************************/
RW_T2tWrite(uint16_t block,uint8_t * p_write_data)955 tNFC_STATUS RW_T2tWrite(uint16_t block, uint8_t* p_write_data) {
956 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
957 tNFC_STATUS status;
958
959 if (p_t2t->state != RW_T2T_STATE_IDLE) {
960 LOG(ERROR) << StringPrintf(
961 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
962 return (NFC_STATUS_FAILED);
963 }
964
965 status = rw_t2t_write(block, p_write_data);
966 if (status == NFC_STATUS_OK) {
967 p_t2t->state = RW_T2T_STATE_WRITE;
968 if (block < T2T_FIRST_DATA_BLOCK)
969 p_t2t->b_read_hdr = false;
970 else if (block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS))
971 p_t2t->b_read_data = false;
972 LOG(VERBOSE) << StringPrintf("RW_T2tWrite Sent Write command");
973 }
974
975 return status;
976 }
977
978 /*******************************************************************************
979 **
980 ** Function RW_T2tSectorSelect
981 **
982 ** Description This function issues the Type 2 Tag SECTOR-SELECT command
983 ** packet 1. If a NACK is received as the response, the
984 ** callback function will be called with a
985 ** RW_T2T_SECTOR_SELECT_EVT. If an ACK is received as the
986 ** response, the command packet 2 with the given sector number
987 ** is sent to the peer device. When the response for packet 2
988 ** is received, the callback function will be called with a
989 ** RW_T2T_SECTOR_SELECT_EVT.
990 **
991 ** A sector is 256 contiguous blocks (1024 bytes).
992 **
993 ** Returns tNFC_STATUS
994 **
995 *******************************************************************************/
RW_T2tSectorSelect(uint8_t sector)996 tNFC_STATUS RW_T2tSectorSelect(uint8_t sector) {
997 tNFC_STATUS status;
998 tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
999 uint8_t sector_byte2[1];
1000
1001 if (p_t2t->state != RW_T2T_STATE_IDLE) {
1002 LOG(ERROR) << StringPrintf(
1003 "Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state);
1004 return (NFC_STATUS_FAILED);
1005 }
1006
1007 if (sector >= T2T_MAX_SECTOR) {
1008 LOG(ERROR) << StringPrintf(
1009 "RW_T2tSectorSelect - Invalid sector: %u, T2 Max supported sector "
1010 "value: %u",
1011 sector, T2T_MAX_SECTOR - 1);
1012 return (NFC_STATUS_FAILED);
1013 }
1014
1015 sector_byte2[0] = 0xFF;
1016
1017 status = rw_t2t_send_cmd(T2T_CMD_SEC_SEL, sector_byte2);
1018 if (status == NFC_STATUS_OK) {
1019 p_t2t->state = RW_T2T_STATE_SELECT_SECTOR;
1020 p_t2t->select_sector = sector;
1021 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT;
1022
1023 LOG(VERBOSE) << StringPrintf(
1024 "RW_T2tSectorSelect Sent Sector select first command");
1025 }
1026
1027 return status;
1028 }
1029
1030 /*******************************************************************************
1031 **
1032 ** Function rw_t2t_get_state_name
1033 **
1034 ** Description This function returns the state name.
1035 **
1036 ** NOTE conditionally compiled to save memory.
1037 **
1038 ** Returns string
1039 **
1040 *******************************************************************************/
rw_t2t_get_state_name(uint8_t state)1041 static std::string rw_t2t_get_state_name(uint8_t state) {
1042 switch (state) {
1043 case RW_T2T_STATE_NOT_ACTIVATED:
1044 return "NOT_ACTIVATED";
1045 case RW_T2T_STATE_IDLE:
1046 return "IDLE";
1047 case RW_T2T_STATE_READ:
1048 return "APP_READ";
1049 case RW_T2T_STATE_WRITE:
1050 return "APP_WRITE";
1051 case RW_T2T_STATE_SELECT_SECTOR:
1052 return "SECTOR_SELECT";
1053 case RW_T2T_STATE_DETECT_TLV:
1054 return "TLV_DETECT";
1055 case RW_T2T_STATE_READ_NDEF:
1056 return "READ_NDEF";
1057 case RW_T2T_STATE_WRITE_NDEF:
1058 return "WRITE_NDEF";
1059 case RW_T2T_STATE_SET_TAG_RO:
1060 return "SET_TAG_RO";
1061 case RW_T2T_STATE_CHECK_PRESENCE:
1062 return "CHECK_PRESENCE";
1063 default:
1064 return "???? UNKNOWN STATE";
1065 }
1066 }
1067
1068 /*******************************************************************************
1069 **
1070 ** Function rw_t2t_get_substate_name
1071 **
1072 ** Description This function returns the substate name.
1073 **
1074 ** NOTE conditionally compiled to save memory.
1075 **
1076 ** Returns pointer to the name
1077 **
1078 *******************************************************************************/
rw_t2t_get_substate_name(uint8_t substate)1079 static std::string rw_t2t_get_substate_name(uint8_t substate) {
1080 switch (substate) {
1081 case RW_T2T_SUBSTATE_NONE:
1082 return "RW_T2T_SUBSTATE_NONE";
1083 case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT:
1084 return "RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT";
1085 case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR:
1086 return "RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR";
1087 case RW_T2T_SUBSTATE_WAIT_READ_CC:
1088 return "RW_T2T_SUBSTATE_WAIT_READ_CC";
1089 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT:
1090 return "RW_T2T_SUBSTATE_WAIT_TLV_DETECT";
1091 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN:
1092 return "RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN";
1093 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0:
1094 return "RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0";
1095 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1:
1096 return "RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1";
1097 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE:
1098 return "RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE";
1099 case RW_T2T_SUBSTATE_WAIT_READ_LOCKS:
1100 return "RW_T2T_SUBSTATE_WAIT_READ_LOCKS";
1101 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
1102 return "RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK";
1103 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
1104 return "RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK";
1105 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
1106 return "RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK";
1107 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK:
1108 return "RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK";
1109 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK:
1110 return "RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK";
1111 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK:
1112 return "RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK";
1113 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK:
1114 return "RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK";
1115 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
1116 return "RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK";
1117 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK:
1118 return "RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK";
1119 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
1120 return "RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT";
1121 default:
1122 return "???? UNKNOWN SUBSTATE";
1123 }
1124 }
1125