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  *
22  *  This file contains the implementation for Type 4 tag in Reader/Writer
23  *  mode.
24  *
25  ******************************************************************************/
26 #include <string.h>
27 #include "nfc_target.h"
28 #include "bt_types.h"
29 #include "trace_api.h"
30 
31 #if (NFC_INCLUDED == TRUE)
32 
33 #include "nfc_api.h"
34 #include "nfc_int.h"
35 #include "rw_api.h"
36 #include "rw_int.h"
37 #include "tags_int.h"
38 #include "gki.h"
39 
40 /* main state */
41 #define RW_T4T_STATE_NOT_ACTIVATED              0x00    /* T4T is not activated                 */
42 #define RW_T4T_STATE_IDLE                       0x01    /* waiting for upper layer API          */
43 #define RW_T4T_STATE_DETECT_NDEF                0x02    /* performing NDEF detection precedure  */
44 #define RW_T4T_STATE_READ_NDEF                  0x03    /* performing read NDEF procedure       */
45 #define RW_T4T_STATE_UPDATE_NDEF                0x04    /* performing update NDEF procedure     */
46 #define RW_T4T_STATE_PRESENCE_CHECK             0x05    /* checking presence of tag             */
47 #define RW_T4T_STATE_SET_READ_ONLY              0x06    /* convert tag to read only             */
48 
49 /* sub state */
50 #define RW_T4T_SUBSTATE_WAIT_SELECT_APP         0x00    /* waiting for response of selecting AID    */
51 #define RW_T4T_SUBSTATE_WAIT_SELECT_CC          0x01    /* waiting for response of selecting CC     */
52 #define RW_T4T_SUBSTATE_WAIT_CC_FILE            0x02    /* waiting for response of reading CC       */
53 #define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE   0x03    /* waiting for response of selecting NDEF   */
54 #define RW_T4T_SUBSTATE_WAIT_READ_NLEN          0x04    /* waiting for response of reading NLEN     */
55 #define RW_T4T_SUBSTATE_WAIT_READ_RESP          0x05    /* waiting for response of reading file     */
56 #define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP        0x06    /* waiting for response of updating file    */
57 #define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN        0x07    /* waiting for response of updating NLEN    */
58 #define RW_T4T_SUBSTATE_WAIT_UPDATE_CC          0x08    /* waiting for response of updating CC      */
59 
60 #if (BT_TRACE_VERBOSE == TRUE)
61 static char *rw_t4t_get_state_name (UINT8 state);
62 static char *rw_t4t_get_sub_state_name (UINT8 sub_state);
63 #endif
64 
65 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu);
66 static BOOLEAN rw_t4t_select_file (UINT16 file_id);
67 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue);
68 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len);
69 static BOOLEAN rw_t4t_update_file (void);
70 static BOOLEAN rw_t4t_update_cc_to_readonly (void);
71 static BOOLEAN rw_t4t_select_application (UINT8 version);
72 static BOOLEAN rw_t4t_validate_cc_file (void);
73 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2);
74 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu);
75 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu);
76 static void rw_t4t_sm_update_ndef (BT_HDR  *p_r_apdu);
77 static void rw_t4t_sm_set_readonly (BT_HDR  *p_r_apdu);
78 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
79 
80 /*******************************************************************************
81 **
82 ** Function         rw_t4t_send_to_lower
83 **
84 ** Description      Send C-APDU to lower layer
85 **
86 ** Returns          TRUE if success
87 **
88 *******************************************************************************/
rw_t4t_send_to_lower(BT_HDR * p_c_apdu)89 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu)
90 {
91 #if (BT_TRACE_PROTOCOL == TRUE)
92     DispRWT4Tags (p_c_apdu, FALSE);
93 #endif
94 
95     if (NFC_SendData (NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK)
96     {
97         RW_TRACE_ERROR0 ("rw_t4t_send_to_lower (): NFC_SendData () failed");
98         return FALSE;
99     }
100 
101     nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE,
102                            (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
103 
104     return TRUE;
105 }
106 
107 /*******************************************************************************
108 **
109 ** Function         rw_t4t_select_file
110 **
111 ** Description      Send Select Command (by File ID) to peer
112 **
113 ** Returns          TRUE if success
114 **
115 *******************************************************************************/
rw_t4t_select_file(UINT16 file_id)116 static BOOLEAN rw_t4t_select_file (UINT16 file_id)
117 {
118     BT_HDR      *p_c_apdu;
119     UINT8       *p;
120 
121     RW_TRACE_DEBUG1 ("rw_t4t_select_file (): File ID:0x%04X", file_id);
122 
123     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
124 
125     if (!p_c_apdu)
126     {
127         RW_TRACE_ERROR0 ("rw_t4t_select_file (): Cannot allocate buffer");
128         return FALSE;
129     }
130 
131     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
132     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
133 
134     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
135     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
136     UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_FILE_ID);
137 
138     /* if current version mapping is V2.0 */
139     if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0)
140     {
141         UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_0CH);
142     }
143     else /* version 1.0 */
144     {
145         UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
146     }
147 
148     UINT8_TO_BE_STREAM (p, T4T_FILE_ID_SIZE);
149     UINT16_TO_BE_STREAM (p, file_id);
150 
151     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE;
152 
153     if (!rw_t4t_send_to_lower (p_c_apdu))
154     {
155         return FALSE;
156     }
157 
158     return TRUE;
159 }
160 
161 /*******************************************************************************
162 **
163 ** Function         rw_t4t_read_file
164 **
165 ** Description      Send ReadBinary Command to peer
166 **
167 ** Returns          TRUE if success
168 **
169 *******************************************************************************/
rw_t4t_read_file(UINT16 offset,UINT16 length,BOOLEAN is_continue)170 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue)
171 {
172     tRW_T4T_CB      *p_t4t = &rw_cb.tcb.t4t;
173     BT_HDR          *p_c_apdu;
174     UINT8           *p;
175 
176     RW_TRACE_DEBUG3 ("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ",
177                       offset, length, is_continue);
178 
179     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
180 
181     if (!p_c_apdu)
182     {
183         RW_TRACE_ERROR0 ("rw_t4t_read_file (): Cannot allocate buffer");
184         return FALSE;
185     }
186 
187     /* if this is the first reading */
188     if (is_continue == FALSE)
189     {
190         /* initialise starting offset and total length */
191         /* these will be updated when receiving response */
192         p_t4t->rw_offset = offset;
193         p_t4t->rw_length = length;
194     }
195 
196     /* adjust reading length if payload is bigger than max size per single command */
197     if (length > p_t4t->max_read_size)
198     {
199         length = (UINT8) (p_t4t->max_read_size);
200     }
201 
202     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
203     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
204 
205     UINT8_TO_BE_STREAM (p, (T4T_CMD_CLASS | rw_cb.tcb.t4t.channel));
206     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_READ_BINARY);
207     UINT16_TO_BE_STREAM (p, offset);
208     UINT8_TO_BE_STREAM (p, length); /* Le */
209 
210     p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
211 
212     if (!rw_t4t_send_to_lower (p_c_apdu))
213     {
214         return FALSE;
215     }
216 
217     return TRUE;
218 }
219 
220 /*******************************************************************************
221 **
222 ** Function         rw_t4t_update_nlen
223 **
224 ** Description      Send UpdateBinary Command to update NLEN to peer
225 **
226 ** Returns          TRUE if success
227 **
228 *******************************************************************************/
rw_t4t_update_nlen(UINT16 ndef_len)229 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len)
230 {
231     BT_HDR          *p_c_apdu;
232     UINT8           *p;
233 
234     RW_TRACE_DEBUG1 ("rw_t4t_update_nlen () NLEN:%d", ndef_len);
235 
236     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
237 
238     if (!p_c_apdu)
239     {
240         RW_TRACE_ERROR0 ("rw_t4t_update_nlen (): Cannot allocate buffer");
241         return FALSE;
242     }
243 
244     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
245     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
246 
247     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
248     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
249     UINT16_TO_BE_STREAM (p, 0x0000);                    /* offset for NLEN */
250     UINT8_TO_BE_STREAM (p, T4T_FILE_LENGTH_SIZE);
251     UINT16_TO_BE_STREAM (p, ndef_len);
252 
253     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE;
254 
255     if (!rw_t4t_send_to_lower (p_c_apdu))
256     {
257         return FALSE;
258     }
259 
260     return TRUE;
261 }
262 
263 /*******************************************************************************
264 **
265 ** Function         rw_t4t_update_file
266 **
267 ** Description      Send UpdateBinary Command to peer
268 **
269 ** Returns          TRUE if success
270 **
271 *******************************************************************************/
rw_t4t_update_file(void)272 static BOOLEAN rw_t4t_update_file (void)
273 {
274     tRW_T4T_CB      *p_t4t = &rw_cb.tcb.t4t;
275     BT_HDR          *p_c_apdu;
276     UINT8           *p;
277     UINT16          length;
278 
279     RW_TRACE_DEBUG2 ("rw_t4t_update_file () rw_offset:%d, rw_length:%d",
280                       p_t4t->rw_offset, p_t4t->rw_length);
281 
282     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
283 
284     if (!p_c_apdu)
285     {
286         RW_TRACE_ERROR0 ("rw_t4t_write_file (): Cannot allocate buffer");
287         return FALSE;
288     }
289 
290     /* try to send all of remaining data */
291     length = p_t4t->rw_length;
292 
293     /* adjust updating length if payload is bigger than max size per single command */
294     if (length > p_t4t->max_update_size)
295     {
296         length = (UINT8) (p_t4t->max_update_size);
297     }
298 
299     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
300     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
301 
302     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
303     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
304     UINT16_TO_BE_STREAM (p, p_t4t->rw_offset);
305     UINT8_TO_BE_STREAM (p, length);
306 
307     memcpy (p, p_t4t->p_update_data, length);
308 
309     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
310 
311     if (!rw_t4t_send_to_lower (p_c_apdu))
312     {
313         return FALSE;
314     }
315 
316     /* adjust offset, length and pointer for remaining data */
317     p_t4t->rw_offset     += length;
318     p_t4t->rw_length     -= length;
319     p_t4t->p_update_data += length;
320 
321     return TRUE;
322 }
323 
324 /*******************************************************************************
325 **
326 ** Function         rw_t4t_update_cc_to_readonly
327 **
328 ** Description      Send UpdateBinary Command for changing Write access
329 **
330 ** Returns          TRUE if success
331 **
332 *******************************************************************************/
rw_t4t_update_cc_to_readonly(void)333 static BOOLEAN rw_t4t_update_cc_to_readonly (void)
334 {
335     BT_HDR          *p_c_apdu;
336     UINT8           *p;
337 
338     RW_TRACE_DEBUG0 ("rw_t4t_update_cc_to_readonly (): Remove Write access from CC");
339 
340     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
341 
342     if (!p_c_apdu)
343     {
344         RW_TRACE_ERROR0 ("rw_t4t_update_cc_to_readonly (): Cannot allocate buffer");
345         return FALSE;
346     }
347 
348     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
349     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
350 
351     /* Add Command Header */
352     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
353     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
354     UINT16_TO_BE_STREAM (p, (T4T_FC_TLV_OFFSET_IN_CC + T4T_FC_WRITE_ACCESS_OFFSET_IN_TLV)); /* Offset for Read Write access byte of CC */
355     UINT8_TO_BE_STREAM (p, 1); /* Length of write access field in cc interms of bytes */
356 
357     /* Remove Write access */
358     UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS);
359 
360 
361     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + 1;
362 
363     if (!rw_t4t_send_to_lower (p_c_apdu))
364     {
365         return FALSE;
366     }
367 
368     return TRUE;
369 }
370 
371 /*******************************************************************************
372 **
373 ** Function         rw_t4t_select_application
374 **
375 ** Description      Select Application
376 **
377 **                  NDEF Tag Application Select - C-APDU
378 **
379 **                        CLA INS P1 P2 Lc Data(AID)      Le
380 **                  V1.0: 00  A4  04 00 07 D2760000850100 -
381 **                  V2.0: 00  A4  04 00 07 D2760000850101 00
382 **
383 ** Returns          TRUE if success
384 **
385 *******************************************************************************/
rw_t4t_select_application(UINT8 version)386 static BOOLEAN rw_t4t_select_application (UINT8 version)
387 {
388     BT_HDR      *p_c_apdu;
389     UINT8       *p;
390 
391     RW_TRACE_DEBUG1 ("rw_t4t_select_application () version:0x%X", version);
392 
393     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
394 
395     if (!p_c_apdu)
396     {
397         RW_TRACE_ERROR0 ("rw_t4t_select_application (): Cannot allocate buffer");
398         return FALSE;
399     }
400 
401     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
402     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
403 
404     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
405     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
406     UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_NAME);
407     UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
408 
409     if (version == T4T_VERSION_1_0)   /* this is for V1.0 */
410     {
411         UINT8_TO_BE_STREAM (p, T4T_V10_NDEF_TAG_AID_LEN);
412 
413         memcpy (p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN);
414 
415         p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN;
416     }
417     else if (version == T4T_VERSION_2_0)   /* this is for V2.0 */
418     {
419         UINT8_TO_BE_STREAM (p, T4T_V20_NDEF_TAG_AID_LEN);
420 
421         memcpy (p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN);
422         p += T4T_V20_NDEF_TAG_AID_LEN;
423 
424         UINT8_TO_BE_STREAM (p, 0x00); /* Le set to 0x00 */
425 
426         p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1;
427     }
428     else
429     {
430         return FALSE;
431     }
432 
433     if (!rw_t4t_send_to_lower (p_c_apdu))
434     {
435         return FALSE;
436     }
437 
438     return TRUE;
439 }
440 
441 /*******************************************************************************
442 **
443 ** Function         rw_t4t_validate_cc_file
444 **
445 ** Description      Validate CC file and mandatory NDEF TLV
446 **
447 ** Returns          TRUE if success
448 **
449 *******************************************************************************/
rw_t4t_validate_cc_file(void)450 static BOOLEAN rw_t4t_validate_cc_file (void)
451 {
452     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
453 
454     RW_TRACE_DEBUG0 ("rw_t4t_validate_cc_file ()");
455 
456     if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN)
457     {
458         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): CCLEN (%d) is too short",
459                          p_t4t->cc_file.cclen);
460         return FALSE;
461     }
462 
463     if (T4T_GET_MAJOR_VERSION (p_t4t->cc_file.version) != T4T_GET_MAJOR_VERSION (p_t4t->version))
464     {
465         RW_TRACE_ERROR2 ("rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours (0x%02X)",
466                          p_t4t->cc_file.version, p_t4t->version);
467         return FALSE;
468     }
469 
470     if (p_t4t->cc_file.max_le < 0x000F)
471     {
472         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLe (%d) is too small",
473                          p_t4t->cc_file.max_le);
474         return FALSE;
475     }
476 
477     if (p_t4t->cc_file.max_lc < 0x0001)
478     {
479         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLc (%d) is too small",
480                          p_t4t->cc_file.max_lc);
481         return FALSE;
482     }
483 
484     if (  (p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID)
485         ||(p_t4t->cc_file.ndef_fc.file_id == 0xE102)
486         ||(p_t4t->cc_file.ndef_fc.file_id == 0xE103)
487         ||((p_t4t->cc_file.ndef_fc.file_id == 0x0000) && (p_t4t->cc_file.version == 0x20))
488         ||(p_t4t->cc_file.ndef_fc.file_id == 0x3F00)
489         ||(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF)
490         ||(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)  )
491     {
492         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid",
493                           p_t4t->cc_file.ndef_fc.file_id);
494         return FALSE;
495     }
496 
497     if (  (p_t4t->cc_file.ndef_fc.max_file_size < 0x0005)
498         ||(p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)  )
499     {
500         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): max_file_size (%d) is reserved",
501                          p_t4t->cc_file.ndef_fc.max_file_size);
502         return FALSE;
503     }
504 
505     if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS)
506     {
507         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid",
508                           p_t4t->cc_file.ndef_fc.read_access);
509         return FALSE;
510     }
511 
512     if (  (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
513         &&(p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS)  )
514     {
515         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid",
516                           p_t4t->cc_file.ndef_fc.write_access);
517         return FALSE;
518     }
519 
520     return TRUE;
521 }
522 
523 /*******************************************************************************
524 **
525 ** Function         rw_t4t_handle_error
526 **
527 ** Description      notify error to application and clean up
528 **
529 ** Returns          none
530 **
531 *******************************************************************************/
rw_t4t_handle_error(tNFC_STATUS status,UINT8 sw1,UINT8 sw2)532 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2)
533 {
534     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
535     tRW_DATA    rw_data;
536     tRW_EVENT   event;
537 
538     RW_TRACE_DEBUG4 ("rw_t4t_handle_error (): status:0x%02X, sw1:0x%02X, sw2:0x%02X, state:0x%X",
539                       status, sw1, sw2, p_t4t->state);
540 
541     nfc_stop_quick_timer (&p_t4t->timer);
542 
543     if (rw_cb.p_cback)
544     {
545         rw_data.status = status;
546 
547         rw_data.t4t_sw.sw1    = sw1;
548         rw_data.t4t_sw.sw2    = sw2;
549 
550         switch (p_t4t->state)
551         {
552         case RW_T4T_STATE_DETECT_NDEF:
553             rw_data.ndef.flags  = RW_NDEF_FL_UNKNOWN;
554             event = RW_T4T_NDEF_DETECT_EVT;
555             break;
556 
557         case RW_T4T_STATE_READ_NDEF:
558             event = RW_T4T_NDEF_READ_FAIL_EVT;
559             break;
560 
561         case RW_T4T_STATE_UPDATE_NDEF:
562             event = RW_T4T_NDEF_UPDATE_FAIL_EVT;
563             break;
564 
565         case RW_T4T_STATE_PRESENCE_CHECK:
566             event = RW_T4T_PRESENCE_CHECK_EVT;
567             rw_data.status = NFC_STATUS_FAILED;
568             break;
569 
570         case RW_T4T_STATE_SET_READ_ONLY:
571             event = RW_T4T_SET_TO_RO_EVT;
572             break;
573 
574         default:
575             event = RW_T4T_MAX_EVT;
576             break;
577         }
578 
579         p_t4t->state = RW_T4T_STATE_IDLE;
580 
581         if (event != RW_T4T_MAX_EVT)
582         {
583             (*(rw_cb.p_cback)) (event, &rw_data);
584         }
585     }
586     else
587     {
588         p_t4t->state = RW_T4T_STATE_IDLE;
589     }
590 }
591 
592 /*******************************************************************************
593 **
594 ** Function         rw_t4t_sm_detect_ndef
595 **
596 ** Description      State machine for NDEF detection procedure
597 **
598 ** Returns          none
599 **
600 *******************************************************************************/
rw_t4t_sm_detect_ndef(BT_HDR * p_r_apdu)601 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu)
602 {
603     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
604     UINT8       *p, type, length;
605     UINT16      status_words, nlen;
606     tRW_DATA    rw_data;
607 
608 #if (BT_TRACE_VERBOSE == TRUE)
609     RW_TRACE_DEBUG2 ("rw_t4t_sm_detect_ndef (): sub_state:%s (%d)",
610                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
611 #else
612     RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): sub_state=%d", p_t4t->sub_state);
613 #endif
614 
615     /* get status words */
616     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
617     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
618     BE_STREAM_TO_UINT16 (status_words, p);
619 
620     if (status_words != T4T_RSP_CMD_CMPLTED)
621     {
622         /* try V1.0 after failing of V2.0 */
623         if (  (p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP)
624             &&(p_t4t->version   == T4T_VERSION_2_0)  )
625         {
626             p_t4t->version = T4T_VERSION_1_0;
627 
628             RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): retry with version=0x%02X",
629                               p_t4t->version);
630 
631             if (!rw_t4t_select_application (T4T_VERSION_1_0))
632             {
633                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
634             }
635             return;
636         }
637 
638         p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
639         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
640         return;
641     }
642 
643     switch (p_t4t->sub_state)
644     {
645     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
646 
647         /* NDEF Tag application has been selected then select CC file */
648         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
649         {
650             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
651         }
652         else
653         {
654             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
655         }
656         break;
657 
658     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
659 
660         /* CC file has been selected then read mandatory part of CC file */
661         if (!rw_t4t_read_file (0x00, T4T_CC_FILE_MIN_LEN, FALSE))
662         {
663             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
664         }
665         else
666         {
667             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
668         }
669         break;
670 
671     case RW_T4T_SUBSTATE_WAIT_CC_FILE:
672 
673         /* CC file has been read then validate and select mandatory NDEF file */
674         if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE)
675         {
676             p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
677 
678             BE_STREAM_TO_UINT16 (p_t4t->cc_file.cclen, p);
679             BE_STREAM_TO_UINT8 (p_t4t->cc_file.version, p);
680             BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_le, p);
681             BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_lc, p);
682 
683             BE_STREAM_TO_UINT8 (type, p);
684             BE_STREAM_TO_UINT8 (length, p);
685 
686             if (  (type == T4T_NDEF_FILE_CONTROL_TYPE)
687                 &&(length == T4T_FILE_CONTROL_LENGTH)  )
688             {
689                 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.file_id, p);
690                 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.max_file_size, p);
691                 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.read_access, p);
692                 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.write_access, p);
693 
694 #if (BT_TRACE_VERBOSE == TRUE)
695                 RW_TRACE_DEBUG0 ("Capability Container (CC) file");
696                 RW_TRACE_DEBUG1 ("  CCLEN:  0x%04X",    p_t4t->cc_file.cclen);
697                 RW_TRACE_DEBUG1 ("  Version:0x%02X",    p_t4t->cc_file.version);
698                 RW_TRACE_DEBUG1 ("  MaxLe:  0x%04X",    p_t4t->cc_file.max_le);
699                 RW_TRACE_DEBUG1 ("  MaxLc:  0x%04X",    p_t4t->cc_file.max_lc);
700                 RW_TRACE_DEBUG0 ("  NDEF File Control TLV");
701                 RW_TRACE_DEBUG1 ("    FileID:      0x%04X", p_t4t->cc_file.ndef_fc.file_id);
702                 RW_TRACE_DEBUG1 ("    MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
703                 RW_TRACE_DEBUG1 ("    ReadAccess:  0x%02X", p_t4t->cc_file.ndef_fc.read_access);
704                 RW_TRACE_DEBUG1 ("    WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
705 #endif
706 
707                 if (rw_t4t_validate_cc_file ())
708                 {
709                     if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
710                     {
711                         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
712                     }
713                     else
714                     {
715                         p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
716                     }
717                     break;
718                 }
719             }
720         }
721 
722         /* invalid response or CC file */
723         p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
724         rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
725         break;
726 
727     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
728 
729         /* NDEF file has been selected then read the first 2 bytes (NLEN) */
730         if (!rw_t4t_read_file (0, T4T_FILE_LENGTH_SIZE, FALSE))
731         {
732             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
733         }
734         else
735         {
736             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
737         }
738         break;
739 
740     case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
741 
742         /* NLEN has been read then report upper layer */
743         if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE)
744         {
745             /* get length of NDEF */
746             p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
747             BE_STREAM_TO_UINT16 (nlen, p);
748 
749             if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE)
750             {
751                 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
752 
753                 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
754                 {
755                     p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
756                 }
757 
758                 /* Get max bytes to read per command */
759                 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ)
760                 {
761                     p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
762                 }
763                 else
764                 {
765                     p_t4t->max_read_size = p_t4t->cc_file.max_le;
766                 }
767 
768                 /* Le: valid range is 0x01 to 0xFF */
769                 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE)
770                 {
771                     p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
772                 }
773 
774                 /* Get max bytes to update per command */
775                 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE)
776                 {
777                     p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
778                 }
779                 else
780                 {
781                     p_t4t->max_update_size = p_t4t->cc_file.max_lc;
782                 }
783 
784                 /* Lc: valid range is 0x01 to 0xFF */
785                 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC)
786                 {
787                     p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
788                 }
789 
790                 p_t4t->ndef_length = nlen;
791                 p_t4t->state       = RW_T4T_STATE_IDLE;
792 
793                 if (rw_cb.p_cback)
794                 {
795                     rw_data.ndef.status   = NFC_STATUS_OK;
796                     rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
797                     rw_data.ndef.max_size = (UINT32) (p_t4t->cc_file.ndef_fc.max_file_size - (UINT16) T4T_FILE_LENGTH_SIZE);
798                     rw_data.ndef.cur_size = nlen;
799                     rw_data.ndef.flags    = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
800                     if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
801                     {
802                         rw_data.ndef.flags    |= RW_NDEF_FL_READ_ONLY;
803                     }
804 
805                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_DETECT_EVT, &rw_data);
806 
807                     RW_TRACE_DEBUG0 ("rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT");
808                 }
809             }
810             else
811             {
812                 /* NLEN should be less than max file size */
813                 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file size (%d)",
814                                  nlen, p_t4t->cc_file.ndef_fc.max_file_size);
815 
816                 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
817                 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
818             }
819         }
820         else
821         {
822             /* response payload size should be T4T_FILE_LENGTH_SIZE */
823             RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d",
824                              p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);
825 
826             p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
827             rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
828         }
829         break;
830 
831     default:
832         RW_TRACE_ERROR1 ("rw_t4t_sm_detect_ndef (): unknown sub_state=%d", p_t4t->sub_state);
833         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
834         break;
835     }
836 }
837 
838 /*******************************************************************************
839 **
840 ** Function         rw_t4t_sm_read_ndef
841 **
842 ** Description      State machine for NDEF read procedure
843 **
844 ** Returns          none
845 **
846 *******************************************************************************/
rw_t4t_sm_read_ndef(BT_HDR * p_r_apdu)847 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu)
848 {
849     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
850     UINT8       *p;
851     UINT16      status_words;
852     tRW_DATA    rw_data;
853 
854 #if (BT_TRACE_VERBOSE == TRUE)
855     RW_TRACE_DEBUG2 ("rw_t4t_sm_read_ndef (): sub_state:%s (%d)",
856                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
857 #else
858     RW_TRACE_DEBUG1 ("rw_t4t_sm_read_ndef (): sub_state=%d", p_t4t->sub_state);
859 #endif
860 
861     /* get status words */
862     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
863     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
864     BE_STREAM_TO_UINT16 (status_words, p);
865 
866     if (status_words != T4T_RSP_CMD_CMPLTED)
867     {
868         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
869         GKI_freebuf (p_r_apdu);
870         return;
871     }
872 
873     switch (p_t4t->sub_state)
874     {
875     case RW_T4T_SUBSTATE_WAIT_READ_RESP:
876 
877         /* Read partial or complete data */
878         p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
879 
880         if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length))
881         {
882             p_t4t->rw_length -= p_r_apdu->len;
883             p_t4t->rw_offset += p_r_apdu->len;
884 
885             if (rw_cb.p_cback)
886             {
887                 rw_data.data.status = NFC_STATUS_OK;
888                 rw_data.data.p_data = p_r_apdu;
889 
890                 /* if need to read more data */
891                 if (p_t4t->rw_length > 0)
892                 {
893                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_EVT, &rw_data);
894 
895                     if (!rw_t4t_read_file (p_t4t->rw_offset, p_t4t->rw_length, TRUE))
896                     {
897                         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
898                     }
899                 }
900                 else
901                 {
902                     p_t4t->state = RW_T4T_STATE_IDLE;
903 
904                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
905 
906                     RW_TRACE_DEBUG0 ("rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT");
907 
908                 }
909 
910                 p_r_apdu = NULL;
911             }
912             else
913             {
914                 p_t4t->rw_length = 0;
915                 p_t4t->state = RW_T4T_STATE_IDLE;
916             }
917         }
918         else
919         {
920             RW_TRACE_ERROR2 ("rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length (%d)",
921                              p_r_apdu->len, p_t4t->rw_length);
922             rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
923         }
924         break;
925 
926     default:
927         RW_TRACE_ERROR1 ("rw_t4t_sm_read_ndef (): unknown sub_state = %d", p_t4t->sub_state);
928         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
929         break;
930     }
931 
932     if (p_r_apdu)
933         GKI_freebuf (p_r_apdu);
934 }
935 
936 /*******************************************************************************
937 **
938 ** Function         rw_t4t_sm_update_ndef
939 **
940 ** Description      State machine for NDEF update procedure
941 **
942 ** Returns          none
943 **
944 *******************************************************************************/
rw_t4t_sm_update_ndef(BT_HDR * p_r_apdu)945 static void rw_t4t_sm_update_ndef (BT_HDR  *p_r_apdu)
946 {
947     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
948     UINT8       *p;
949     UINT16      status_words;
950     tRW_DATA    rw_data;
951 
952 #if (BT_TRACE_VERBOSE == TRUE)
953     RW_TRACE_DEBUG2 ("rw_t4t_sm_update_ndef (): sub_state:%s (%d)",
954                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
955 #else
956     RW_TRACE_DEBUG1 ("rw_t4t_sm_update_ndef (): sub_state=%d", p_t4t->sub_state);
957 #endif
958 
959     /* Get status words */
960     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
961     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
962     BE_STREAM_TO_UINT16 (status_words, p);
963 
964     if (status_words != T4T_RSP_CMD_CMPLTED)
965     {
966         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
967         return;
968     }
969 
970     switch (p_t4t->sub_state)
971     {
972     case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
973 
974         /* NLEN has been updated */
975         /* if need to update data */
976         if (p_t4t->p_update_data)
977         {
978             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;
979 
980             if (!rw_t4t_update_file ())
981             {
982                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
983                 p_t4t->p_update_data = NULL;
984             }
985         }
986         else
987         {
988             p_t4t->state = RW_T4T_STATE_IDLE;
989 
990             /* just finished last step of updating (updating NLEN) */
991             if (rw_cb.p_cback)
992             {
993                 rw_data.status = NFC_STATUS_OK;
994 
995                 (*(rw_cb.p_cback)) (RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
996                 RW_TRACE_DEBUG0 ("rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
997             }
998         }
999         break;
1000 
1001     case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1002 
1003         /* if updating is not completed */
1004         if (p_t4t->rw_length > 0)
1005         {
1006             if (!rw_t4t_update_file ())
1007             {
1008                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1009                 p_t4t->p_update_data = NULL;
1010             }
1011         }
1012         else
1013         {
1014             p_t4t->p_update_data = NULL;
1015 
1016             /* update NLEN as last step of updating file */
1017             if (!rw_t4t_update_nlen (p_t4t->ndef_length))
1018             {
1019                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1020             }
1021             else
1022             {
1023                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1024             }
1025         }
1026         break;
1027 
1028     default:
1029         RW_TRACE_ERROR1 ("rw_t4t_sm_update_ndef (): unknown sub_state = %d", p_t4t->sub_state);
1030         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1031         break;
1032     }
1033 }
1034 
1035 /*******************************************************************************
1036 **
1037 ** Function         rw_t4t_sm_set_readonly
1038 **
1039 ** Description      State machine for CC update procedure
1040 **
1041 ** Returns          none
1042 **
1043 *******************************************************************************/
rw_t4t_sm_set_readonly(BT_HDR * p_r_apdu)1044 static void rw_t4t_sm_set_readonly (BT_HDR  *p_r_apdu)
1045 {
1046     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1047     UINT8       *p;
1048     UINT16      status_words;
1049     tRW_DATA    rw_data;
1050 
1051 #if (BT_TRACE_VERBOSE == TRUE)
1052     RW_TRACE_DEBUG2 ("rw_t4t_sm_set_readonly (): sub_state:%s (%d)",
1053                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1054 #else
1055     RW_TRACE_DEBUG1 ("rw_t4t_sm_set_readonly (): sub_state=%d", p_t4t->sub_state);
1056 #endif
1057 
1058     /* Get status words */
1059     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1060     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1061     BE_STREAM_TO_UINT16 (status_words, p);
1062 
1063     if (status_words != T4T_RSP_CMD_CMPLTED)
1064     {
1065         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1066         return;
1067     }
1068 
1069     switch (p_t4t->sub_state)
1070     {
1071     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1072 
1073         /* CC file has been selected then update write access to read-only in CC file */
1074         if (!rw_t4t_update_cc_to_readonly ())
1075         {
1076             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1077         }
1078         else
1079         {
1080             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC;
1081         }
1082         break;
1083 
1084     case RW_T4T_SUBSTATE_WAIT_UPDATE_CC:
1085         /* CC Updated, Select NDEF File to allow NDEF operation */
1086         p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS;
1087         p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1088 
1089         if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
1090         {
1091             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1092         }
1093         else
1094         {
1095             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1096         }
1097         break;
1098 
1099     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1100         p_t4t->state = RW_T4T_STATE_IDLE;
1101         /* just finished last step of configuring tag read only (Selecting NDEF file CC) */
1102         if (rw_cb.p_cback)
1103         {
1104             rw_data.status = NFC_STATUS_OK;
1105 
1106             RW_TRACE_DEBUG0 ("rw_t4t_sm_set_readonly (): Sent RW_T4T_SET_TO_RO_EVT");
1107             (*(rw_cb.p_cback)) (RW_T4T_SET_TO_RO_EVT, &rw_data);
1108         }
1109         break;
1110 
1111     default:
1112         RW_TRACE_ERROR1 ("rw_t4t_sm_set_readonly (): unknown sub_state = %d", p_t4t->sub_state);
1113         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1114         break;
1115     }
1116 }
1117 
1118 /*******************************************************************************
1119 **
1120 ** Function         rw_t4t_process_timeout
1121 **
1122 ** Description      process timeout event
1123 **
1124 ** Returns          none
1125 **
1126 *******************************************************************************/
rw_t4t_process_timeout(TIMER_LIST_ENT * p_tle)1127 void rw_t4t_process_timeout (TIMER_LIST_ENT *p_tle)
1128 {
1129     RW_TRACE_DEBUG1 ("rw_t4t_process_timeout () event=%d", p_tle->event);
1130 
1131     if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE)
1132     {
1133         rw_t4t_handle_error (NFC_STATUS_TIMEOUT, 0, 0);
1134     }
1135     else
1136     {
1137         RW_TRACE_ERROR1 ("rw_t4t_process_timeout () unknown event=%d", p_tle->event);
1138     }
1139 }
1140 
1141 /*******************************************************************************
1142 **
1143 ** Function         rw_t4t_data_cback
1144 **
1145 ** Description      This callback function receives the data from NFCC.
1146 **
1147 ** Returns          none
1148 **
1149 *******************************************************************************/
rw_t4t_data_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)1150 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
1151 {
1152     tRW_T4T_CB *p_t4t    = &rw_cb.tcb.t4t;
1153     BT_HDR     *p_r_apdu;
1154     tRW_DATA    rw_data;
1155 
1156 #if (BT_TRACE_VERBOSE == TRUE)
1157     UINT8  begin_state   = p_t4t->state;
1158 #endif
1159 
1160     RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event);
1161     nfc_stop_quick_timer (&p_t4t->timer);
1162 
1163     switch (event)
1164     {
1165     case NFC_DEACTIVATE_CEVT:
1166         NFC_SetStaticRfCback (NULL);
1167         p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
1168         return;
1169 
1170     case NFC_ERROR_CEVT:
1171         rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
1172 
1173         if (p_t4t->state != RW_T4T_STATE_IDLE)
1174         {
1175             rw_t4t_handle_error (rw_data.status, 0, 0);
1176         }
1177         else
1178         {
1179             (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data);
1180         }
1181         return;
1182 
1183     case NFC_DATA_CEVT:
1184         p_r_apdu = (BT_HDR *) p_data->data.p_data;
1185         break;
1186 
1187     default:
1188         return;
1189     }
1190 
1191 #if (BT_TRACE_PROTOCOL == TRUE)
1192     if (p_t4t->state != RW_T4T_STATE_IDLE)
1193         DispRWT4Tags (p_r_apdu, TRUE);
1194 #endif
1195 
1196 #if (BT_TRACE_VERBOSE == TRUE)
1197     RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>",
1198                         rw_t4t_get_state_name (p_t4t->state), p_t4t->state);
1199 #else
1200     RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state);
1201 #endif
1202 
1203     switch (p_t4t->state)
1204     {
1205     case RW_T4T_STATE_IDLE:
1206         /* Unexpected R-APDU, it should be raw frame response */
1207         /* forward to upper layer without parsing */
1208 #if (BT_TRACE_VERBOSE == TRUE)
1209         RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len, NFC_GetStatusName (p_data->data.status));
1210 #else
1211         RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [0x%X]", p_r_apdu->len, p_data->data.status);
1212 #endif
1213         if (rw_cb.p_cback)
1214         {
1215             rw_data.raw_frame.status = p_data->data.status;
1216             rw_data.raw_frame.p_data = p_r_apdu;
1217             (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data);
1218             p_r_apdu = NULL;
1219         }
1220         else
1221         {
1222             GKI_freebuf (p_r_apdu);
1223         }
1224         break;
1225     case RW_T4T_STATE_DETECT_NDEF:
1226         rw_t4t_sm_detect_ndef (p_r_apdu);
1227         GKI_freebuf (p_r_apdu);
1228         break;
1229     case RW_T4T_STATE_READ_NDEF:
1230         rw_t4t_sm_read_ndef (p_r_apdu);
1231         /* p_r_apdu may send upper lyaer */
1232         break;
1233     case RW_T4T_STATE_UPDATE_NDEF:
1234         rw_t4t_sm_update_ndef (p_r_apdu);
1235         GKI_freebuf (p_r_apdu);
1236         break;
1237     case RW_T4T_STATE_PRESENCE_CHECK:
1238         /* if any response, send presence check with ok */
1239         rw_data.status = NFC_STATUS_OK;
1240         p_t4t->state = RW_T4T_STATE_IDLE;
1241         (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1242         GKI_freebuf (p_r_apdu);
1243         break;
1244     case RW_T4T_STATE_SET_READ_ONLY:
1245         rw_t4t_sm_set_readonly (p_r_apdu);
1246         GKI_freebuf (p_r_apdu);
1247         break;
1248     default:
1249         RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
1250         GKI_freebuf (p_r_apdu);
1251         break;
1252     }
1253 
1254 #if (BT_TRACE_VERBOSE == TRUE)
1255     if (begin_state != p_t4t->state)
1256     {
1257         RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>",
1258                           rw_t4t_get_state_name (begin_state),
1259                           rw_t4t_get_state_name (p_t4t->state));
1260     }
1261 #endif
1262 }
1263 
1264 
1265 /*******************************************************************************
1266 **
1267 ** Function         rw_t4t_select
1268 **
1269 ** Description      Initialise T4T
1270 **
1271 ** Returns          NFC_STATUS_OK if success
1272 **
1273 *******************************************************************************/
rw_t4t_select(void)1274 tNFC_STATUS rw_t4t_select (void)
1275 {
1276     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1277 
1278     RW_TRACE_DEBUG0 ("rw_t4t_select ()");
1279 
1280     NFC_SetStaticRfCback (rw_t4t_data_cback);
1281 
1282     p_t4t->state   = RW_T4T_STATE_IDLE;
1283     p_t4t->version = T4T_MY_VERSION;
1284 
1285     /* set it min of max R-APDU data size before reading CC file */
1286     p_t4t->cc_file.max_le = T4T_MIN_MLE;
1287 
1288     /* These will be udated during NDEF detection */
1289     p_t4t->max_read_size   = T4T_MAX_LENGTH_LE;
1290     p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1291 
1292     return NFC_STATUS_OK;
1293 }
1294 
1295 /*******************************************************************************
1296 **
1297 ** Function         RW_T4tDetectNDef
1298 **
1299 ** Description      This function performs NDEF detection procedure
1300 **
1301 **                  RW_T4T_NDEF_DETECT_EVT will be returned
1302 **
1303 ** Returns          NFC_STATUS_OK if success
1304 **                  NFC_STATUS_FAILED if T4T is busy or other error
1305 **
1306 *******************************************************************************/
RW_T4tDetectNDef(void)1307 tNFC_STATUS RW_T4tDetectNDef (void)
1308 {
1309     RW_TRACE_API0 ("RW_T4tDetectNDef ()");
1310 
1311     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1312     {
1313         RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)",
1314                           rw_cb.tcb.t4t.state);
1315         return NFC_STATUS_FAILED;
1316     }
1317 
1318     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1319     {
1320         /* NDEF Tag application has been selected then select CC file */
1321         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1322         {
1323             return NFC_STATUS_FAILED;
1324         }
1325         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1326     }
1327     else
1328     {
1329         /* Select NDEF Tag Application */
1330         if (!rw_t4t_select_application (rw_cb.tcb.t4t.version))
1331         {
1332             return NFC_STATUS_FAILED;
1333         }
1334         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1335     }
1336 
1337     rw_cb.tcb.t4t.state     = RW_T4T_STATE_DETECT_NDEF;
1338 
1339     return NFC_STATUS_OK;
1340 }
1341 
1342 /*******************************************************************************
1343 **
1344 ** Function         RW_T4tReadNDef
1345 **
1346 ** Description      This function performs NDEF read procedure
1347 **                  Note: RW_T4tDetectNDef () must be called before using this
1348 **
1349 **                  The following event will be returned
1350 **                      RW_T4T_NDEF_READ_EVT for each segmented NDEF message
1351 **                      RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF
1352 **                      RW_T4T_NDEF_READ_FAIL_EVT for failure
1353 **
1354 ** Returns          NFC_STATUS_OK if success
1355 **                  NFC_STATUS_FAILED if T4T is busy or other error
1356 **
1357 *******************************************************************************/
RW_T4tReadNDef(void)1358 tNFC_STATUS RW_T4tReadNDef (void)
1359 {
1360     RW_TRACE_API0 ("RW_T4tReadNDef ()");
1361 
1362     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1363     {
1364         RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)",
1365                           rw_cb.tcb.t4t.state);
1366         return NFC_STATUS_FAILED;
1367     }
1368 
1369     /* if NDEF has been detected */
1370     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1371     {
1372         /* start reading NDEF */
1373         if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE))
1374         {
1375             return NFC_STATUS_FAILED;
1376         }
1377 
1378         rw_cb.tcb.t4t.state     = RW_T4T_STATE_READ_NDEF;
1379         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
1380 
1381         return NFC_STATUS_OK;
1382     }
1383     else
1384     {
1385         RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected");
1386         return NFC_STATUS_FAILED;
1387     }
1388 }
1389 
1390 /*******************************************************************************
1391 **
1392 ** Function         RW_T4tUpdateNDef
1393 **
1394 ** Description      This function performs NDEF update procedure
1395 **                  Note: RW_T4tDetectNDef () must be called before using this
1396 **                        Updating data must not be removed until returning event
1397 **
1398 **                  The following event will be returned
1399 **                      RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
1400 **                      RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
1401 **
1402 ** Returns          NFC_STATUS_OK if success
1403 **                  NFC_STATUS_FAILED if T4T is busy or other error
1404 **
1405 *******************************************************************************/
RW_T4tUpdateNDef(UINT16 length,UINT8 * p_data)1406 tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data)
1407 {
1408     RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length);
1409 
1410     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1411     {
1412         RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)",
1413                           rw_cb.tcb.t4t.state);
1414         return NFC_STATUS_FAILED;
1415     }
1416 
1417     /* if NDEF has been detected */
1418     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1419     {
1420         /* if read-only */
1421         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1422         {
1423             RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only");
1424             return NFC_STATUS_FAILED;
1425         }
1426 
1427         if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE)
1428         {
1429             RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)",
1430                               length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
1431             return NFC_STATUS_FAILED;
1432         }
1433 
1434         /* store NDEF length and data */
1435         rw_cb.tcb.t4t.ndef_length   = length;
1436         rw_cb.tcb.t4t.p_update_data = p_data;
1437 
1438         rw_cb.tcb.t4t.rw_offset     = T4T_FILE_LENGTH_SIZE;
1439         rw_cb.tcb.t4t.rw_length     = length;
1440 
1441         /* set NLEN to 0x0000 for the first step */
1442         if (!rw_t4t_update_nlen (0x0000))
1443         {
1444             return NFC_STATUS_FAILED;
1445         }
1446 
1447         rw_cb.tcb.t4t.state     = RW_T4T_STATE_UPDATE_NDEF;
1448         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1449 
1450         return NFC_STATUS_OK;
1451     }
1452     else
1453     {
1454         RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected");
1455         return NFC_STATUS_FAILED;
1456     }
1457 }
1458 
1459 /*****************************************************************************
1460 **
1461 ** Function         RW_T4tPresenceCheck
1462 **
1463 ** Description
1464 **      Check if the tag is still in the field.
1465 **
1466 **      The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
1467 **      or non-presence.
1468 **      option is RW_T4T_CHK_EMPTY_I_BLOCK, use empty I block for presence check.
1469 **
1470 ** Returns
1471 **      NFC_STATUS_OK, if raw data frame sent
1472 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
1473 **      NFC_STATUS_FAILED: other error
1474 **
1475 *****************************************************************************/
RW_T4tPresenceCheck(UINT8 option)1476 tNFC_STATUS RW_T4tPresenceCheck (UINT8 option)
1477 {
1478     tNFC_STATUS retval = NFC_STATUS_OK;
1479     tRW_DATA    evt_data;
1480     BOOLEAN     status;
1481     BT_HDR      *p_data;
1482 
1483     RW_TRACE_API1 ("RW_T4tPresenceCheck () %d", option);
1484 
1485     /* If RW_SelectTagType was not called (no conn_callback) return failure */
1486     if (!rw_cb.p_cback)
1487     {
1488         retval = NFC_STATUS_FAILED;
1489     }
1490     /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */
1491     else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED)
1492     {
1493         evt_data.status = NFC_STATUS_FAILED;
1494         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1495     }
1496     /* If command is pending, assume tag is still present */
1497     else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1498     {
1499         evt_data.status = NFC_STATUS_OK;
1500         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1501     }
1502     else
1503     {
1504         status = FALSE;
1505         if (option == RW_T4T_CHK_EMPTY_I_BLOCK)
1506         {
1507             /* use empty I block for presence check */
1508             if ((p_data = (BT_HDR *) GKI_getbuf (NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE)) != NULL)
1509             {
1510                 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1511                 p_data->len    = 0;
1512                 if (NFC_SendData (NFC_RF_CONN_ID, (BT_HDR*) p_data) == NFC_STATUS_OK)
1513                     status = TRUE;
1514             }
1515         }
1516         else
1517         {
1518             /* use read binary on the given channel */
1519             rw_cb.tcb.t4t.channel = 0;
1520             if (option <= RW_T4T_CHK_READ_BINARY_CH3)
1521                 rw_cb.tcb.t4t.channel = option;
1522             status = rw_t4t_read_file (0, 1, FALSE);
1523             rw_cb.tcb.t4t.channel = 0;
1524         }
1525 
1526         if (status == TRUE)
1527         {
1528             rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
1529         }
1530         else
1531         {
1532             retval = NFC_STATUS_NO_BUFFERS;
1533         }
1534     }
1535 
1536     return (retval);
1537 }
1538 
1539 /*****************************************************************************
1540 **
1541 ** Function         RW_T4tSetNDefReadOnly
1542 **
1543 ** Description      This function performs NDEF read-only procedure
1544 **                  Note: RW_T4tDetectNDef() must be called before using this
1545 **
1546 **                  The RW_T4T_SET_TO_RO_EVT event will be returned.
1547 **
1548 ** Returns          NFC_STATUS_OK if success
1549 **                  NFC_STATUS_FAILED if T4T is busy or other error
1550 **
1551 *****************************************************************************/
RW_T4tSetNDefReadOnly(void)1552 tNFC_STATUS RW_T4tSetNDefReadOnly (void)
1553 {
1554     tNFC_STATUS retval = NFC_STATUS_OK;
1555     tRW_DATA    evt_data;
1556 
1557     RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()");
1558 
1559     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1560     {
1561         RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)",
1562                           rw_cb.tcb.t4t.state);
1563         return NFC_STATUS_FAILED;
1564     }
1565 
1566     /* if NDEF has been detected */
1567     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1568     {
1569         /* if read-only */
1570         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1571         {
1572             RW_TRACE_API0 ("RW_T4tSetNDefReadOnly (): NDEF is already read-only");
1573 
1574             evt_data.status = NFC_STATUS_OK;
1575             (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data);
1576             return (retval);
1577         }
1578 
1579         /* NDEF Tag application has been selected then select CC file */
1580         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1581         {
1582             return NFC_STATUS_FAILED;
1583         }
1584 
1585         rw_cb.tcb.t4t.state     = RW_T4T_STATE_SET_READ_ONLY;
1586         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1587 
1588         return NFC_STATUS_OK;
1589     }
1590     else
1591     {
1592         RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected");
1593         return NFC_STATUS_FAILED;
1594     }
1595     return (retval);
1596 }
1597 
1598 #if (BT_TRACE_VERBOSE == TRUE)
1599 /*******************************************************************************
1600 **
1601 ** Function         rw_t4t_get_state_name
1602 **
1603 ** Description      This function returns the state name.
1604 **
1605 ** NOTE             conditionally compiled to save memory.
1606 **
1607 ** Returns          pointer to the name
1608 **
1609 *******************************************************************************/
rw_t4t_get_state_name(UINT8 state)1610 static char *rw_t4t_get_state_name (UINT8 state)
1611 {
1612     switch (state)
1613     {
1614     case RW_T4T_STATE_NOT_ACTIVATED:
1615         return ("NOT_ACTIVATED");
1616     case RW_T4T_STATE_IDLE:
1617         return ("IDLE");
1618     case RW_T4T_STATE_DETECT_NDEF:
1619         return ("NDEF_DETECTION");
1620     case RW_T4T_STATE_READ_NDEF:
1621         return ("READ_NDEF");
1622     case RW_T4T_STATE_UPDATE_NDEF:
1623         return ("UPDATE_NDEF");
1624     case RW_T4T_STATE_PRESENCE_CHECK:
1625         return ("PRESENCE_CHECK");
1626     case RW_T4T_STATE_SET_READ_ONLY:
1627         return ("SET_READ_ONLY");
1628 
1629     default:
1630         return ("???? UNKNOWN STATE");
1631     }
1632 }
1633 
1634 /*******************************************************************************
1635 **
1636 ** Function         rw_t4t_get_sub_state_name
1637 **
1638 ** Description      This function returns the sub_state name.
1639 **
1640 ** NOTE             conditionally compiled to save memory.
1641 **
1642 ** Returns          pointer to the name
1643 **
1644 *******************************************************************************/
rw_t4t_get_sub_state_name(UINT8 sub_state)1645 static char *rw_t4t_get_sub_state_name (UINT8 sub_state)
1646 {
1647     switch (sub_state)
1648     {
1649     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1650         return ("WAIT_SELECT_APP");
1651     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1652         return ("WAIT_SELECT_CC");
1653     case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1654         return ("WAIT_CC_FILE");
1655     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1656         return ("WAIT_SELECT_NDEF_FILE");
1657     case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1658         return ("WAIT_READ_NLEN");
1659 
1660     case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1661         return ("WAIT_READ_RESP");
1662     case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1663         return ("WAIT_UPDATE_RESP");
1664     case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1665         return ("WAIT_UPDATE_NLEN");
1666     default:
1667         return ("???? UNKNOWN SUBSTATE");
1668     }
1669 }
1670 #endif
1671 
1672 #endif /* (NFC_INCLUDED == TRUE) */
1673