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 #define RW_T4T_STATE_NDEF_FORMAT                0x07    /* performing NDEF format               */
50 
51 /* sub state */
52 #define RW_T4T_SUBSTATE_WAIT_SELECT_APP         0x00    /* waiting for response of selecting AID    */
53 #define RW_T4T_SUBSTATE_WAIT_SELECT_CC          0x01    /* waiting for response of selecting CC     */
54 #define RW_T4T_SUBSTATE_WAIT_CC_FILE            0x02    /* waiting for response of reading CC       */
55 #define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE   0x03    /* waiting for response of selecting NDEF   */
56 #define RW_T4T_SUBSTATE_WAIT_READ_NLEN          0x04    /* waiting for response of reading NLEN     */
57 #define RW_T4T_SUBSTATE_WAIT_READ_RESP          0x05    /* waiting for response of reading file     */
58 #define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP        0x06    /* waiting for response of updating file    */
59 #define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN        0x07    /* waiting for response of updating NLEN    */
60 #define RW_T4T_SUBSTATE_WAIT_UPDATE_CC          0x08    /* waiting for response of updating CC      */
61 
62 #define RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION     0x09
63 #define RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION     0x0A
64 #define RW_T4T_SUBSTATE_WAIT_GET_UID            0x0B
65 #define RW_T4T_SUBSTATE_WAIT_CREATE_APP         0x0C
66 #define RW_T4T_SUBSTATE_WAIT_CREATE_CC          0x0D
67 #define RW_T4T_SUBSTATE_WAIT_CREATE_NDEF        0x0E
68 #define RW_T4T_SUBSTATE_WAIT_WRITE_CC           0x0F
69 #define RW_T4T_SUBSTATE_WAIT_WRITE_NDEF         0x10
70 
71 #if (BT_TRACE_VERBOSE == TRUE)
72 static char *rw_t4t_get_state_name (UINT8 state);
73 static char *rw_t4t_get_sub_state_name (UINT8 sub_state);
74 #endif
75 
76 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu);
77 static BOOLEAN rw_t4t_select_file (UINT16 file_id);
78 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue);
79 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len);
80 static BOOLEAN rw_t4t_update_file (void);
81 static BOOLEAN rw_t4t_update_cc_to_readonly (void);
82 static BOOLEAN rw_t4t_select_application (UINT8 version);
83 static BOOLEAN rw_t4t_validate_cc_file (void);
84 
85 static BOOLEAN rw_t4t_get_hw_version (void);
86 static BOOLEAN rw_t4t_get_sw_version (void);
87 static BOOLEAN rw_t4t_create_app (void);
88 static BOOLEAN rw_t4t_select_app (void);
89 static BOOLEAN rw_t4t_create_ccfile (void);
90 static BOOLEAN rw_t4t_create_ndef (void);
91 static BOOLEAN rw_t4t_write_cc (void);
92 static BOOLEAN rw_t4t_write_ndef (void);
93 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2);
94 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu);
95 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu);
96 static void rw_t4t_sm_update_ndef (BT_HDR  *p_r_apdu);
97 static void rw_t4t_sm_set_readonly (BT_HDR  *p_r_apdu);
98 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
99 static void rw_t4t_sm_ndef_format (BT_HDR  *p_r_apdu);
100 
101 /*******************************************************************************
102 **
103 ** Function         rw_t4t_send_to_lower
104 **
105 ** Description      Send C-APDU to lower layer
106 **
107 ** Returns          TRUE if success
108 **
109 *******************************************************************************/
rw_t4t_send_to_lower(BT_HDR * p_c_apdu)110 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu)
111 {
112 #if (BT_TRACE_PROTOCOL == TRUE)
113     DispRWT4Tags (p_c_apdu, FALSE);
114 #endif
115 
116     if (NFC_SendData (NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK)
117     {
118         RW_TRACE_ERROR0 ("rw_t4t_send_to_lower (): NFC_SendData () failed");
119         return FALSE;
120     }
121 
122     nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE,
123             (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
124 
125     return TRUE;
126 }
127 
128 /*******************************************************************************
129 **
130 ** Function         rw_t4t_get_hw_version
131 **
132 ** Description      Send get hw version cmd to peer
133 **
134 ** Returns          TRUE if success
135 **
136 *******************************************************************************/
rw_t4t_get_hw_version(void)137 static BOOLEAN rw_t4t_get_hw_version (void)
138 {
139     BT_HDR      *p_c_apdu;
140     UINT8       *p;
141 
142     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
143 
144     if (!p_c_apdu)
145     {
146         RW_TRACE_ERROR0 ("rw_t4t_get_hw_version (): Cannot allocate buffer");
147         return FALSE;
148     }
149 
150     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
151     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
152 
153     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
154     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_GET_HW_VERSION);
155     UINT16_TO_BE_STREAM (p, 0x0000);
156     UINT8_TO_BE_FIELD (p, 0x00);
157 
158     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
159 
160     if (!rw_t4t_send_to_lower (p_c_apdu))
161     {
162         return FALSE;
163     }
164 
165     return TRUE;
166 }
167 
168 /*******************************************************************************
169 **
170 ** Function         rw_t4t_get_sw_version
171 **
172 ** Description      Send get sw version cmd to peer
173 **
174 ** Returns          TRUE if success
175 **
176 *******************************************************************************/
rw_t4t_get_sw_version(void)177 static BOOLEAN rw_t4t_get_sw_version (void)
178 {
179     BT_HDR      *p_c_apdu;
180     UINT8       *p;
181 
182     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
183 
184     if (!p_c_apdu)
185     {
186         RW_TRACE_ERROR0 ("rw_t4t_get_sw_version (): Cannot allocate buffer");
187         return FALSE;
188     }
189 
190     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
191     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
192 
193     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
194     UINT8_TO_BE_STREAM (p, T4T_ADDI_FRAME_RESP);
195     UINT16_TO_BE_STREAM (p, 0x0000);
196     UINT8_TO_BE_FIELD (p, 0x00);
197 
198     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
199 
200     if (!rw_t4t_send_to_lower (p_c_apdu))
201     {
202         return FALSE;
203     }
204 
205     return TRUE;
206 }
207 
208 /*******************************************************************************
209 **
210 ** Function         rw_t4t_update_version_details
211 **
212 ** Description      Updates the size of the card
213 **
214 ** Returns          TRUE if success
215 **
216 *******************************************************************************/
rw_t4t_update_version_details(BT_HDR * p_r_apdu)217 static BOOLEAN rw_t4t_update_version_details (BT_HDR *p_r_apdu)
218 {
219     tRW_T4T_CB      *p_t4t = &rw_cb.tcb.t4t;
220     UINT8           *p;
221     UINT16          major_version, minor_version;
222 
223     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
224     major_version = *(p + 3);
225     minor_version = *(p + 4);
226 
227     if ((T4T_DESEV0_MAJOR_VERSION == major_version) &&
228         (T4T_DESEV0_MINOR_VERSION == minor_version))
229     {
230         p_t4t->card_size = 0xEDE;
231     }
232     else if (major_version >= T4T_DESEV1_MAJOR_VERSION)
233     {
234         p_t4t->card_type = T4T_TYPE_DESFIRE_EV1;
235         switch (*(p + 5))
236         {
237         case T4T_SIZE_IDENTIFIER_2K:
238             p_t4t->card_size = 2048;
239             break;
240         case T4T_SIZE_IDENTIFIER_4K:
241             p_t4t->card_size = 4096;
242             break;
243         case T4T_SIZE_IDENTIFIER_8K:
244             p_t4t->card_size = 7680;
245             break;
246         default:
247             return FALSE;
248         }
249     }
250     else
251     {
252         return FALSE;
253     }
254 
255     return TRUE;
256 }
257 
258 /*******************************************************************************
259 **
260 ** Function         rw_t4t_get_uid_details
261 **
262 ** Description      Send get uid cmd to peer
263 **
264 ** Returns          TRUE if success
265 **
266 *******************************************************************************/
rw_t4t_get_uid_details(void)267 static BOOLEAN rw_t4t_get_uid_details (void)
268 {
269     BT_HDR      *p_c_apdu;
270     UINT8       *p;
271 
272     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
273 
274     if (!p_c_apdu)
275     {
276         RW_TRACE_ERROR0 ("rw_t4t_get_uid_details (): Cannot allocate buffer");
277         return FALSE;
278     }
279 
280     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
281     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
282 
283     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
284     UINT8_TO_BE_STREAM (p, T4T_ADDI_FRAME_RESP);
285     UINT16_TO_BE_STREAM (p, 0x0000);
286     UINT8_TO_BE_FIELD (p, 0x00);
287 
288     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE;
289 
290     if (!rw_t4t_send_to_lower (p_c_apdu))
291     {
292         return FALSE;
293     }
294 
295     return TRUE;
296 }
297 
298 /*******************************************************************************
299 **
300 ** Function         rw_t4t_create_app
301 **
302 ** Description      Send create application cmd to peer
303 **
304 ** Returns          TRUE if success
305 **
306 *******************************************************************************/
rw_t4t_create_app(void)307 static BOOLEAN rw_t4t_create_app (void)
308 {
309     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
310     BT_HDR      *p_c_apdu;
311     UINT8       *p;
312     UINT8       df_name[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
313 
314     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
315 
316     if (!p_c_apdu)
317     {
318         RW_TRACE_ERROR0 ("rw_t4t_create_app (): Cannot allocate buffer");
319         return FALSE;
320     }
321 
322     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
323     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
324 
325     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
326     UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_AID);
327     UINT16_TO_BE_STREAM (p, 0x0000);
328     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
329     {
330         UINT8_TO_BE_STREAM (p, (T4T_CMD_MAX_HDR_SIZE + sizeof(df_name) + 2));
331         UINT24_TO_BE_STREAM (p, T4T_DES_EV1_NFC_APP_ID);
332         UINT16_TO_BE_STREAM (p, 0x0F21);                  /*Key settings and no.of keys */
333         UINT16_TO_BE_STREAM (p, 0x05E1);                  /* ISO file ID */
334         ARRAY_TO_BE_STREAM (p, df_name, sizeof(df_name));   /*DF file name */
335         UINT8_TO_BE_STREAM (p, 0x00);                      /* Le */
336         p_c_apdu->len = 20;
337     }
338     else
339     {
340         UINT8_TO_BE_STREAM (p, T4T_CMD_MAX_HDR_SIZE);
341         UINT24_TO_BE_STREAM (p, T4T_DES_EV0_NFC_APP_ID);
342         UINT16_TO_BE_STREAM (p, 0x0F01);                  /*Key settings and no.of keys */
343         UINT8_TO_BE_STREAM (p, 0x00);                      /* Le */
344         p_c_apdu->len = 11;
345     }
346 
347     if (!rw_t4t_send_to_lower (p_c_apdu))
348     {
349         return FALSE;
350     }
351 
352     return TRUE;
353 }
354 
355 /*******************************************************************************
356 **
357 ** Function         rw_t4t_select_app
358 **
359 ** Description      Select application cmd to peer
360 **
361 ** Returns          TRUE if success
362 **
363 *******************************************************************************/
rw_t4t_select_app(void)364 static BOOLEAN rw_t4t_select_app (void)
365 {
366     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
367     BT_HDR      *p_c_apdu;
368     UINT8       *p;
369 
370     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
371 
372     if (!p_c_apdu)
373     {
374         RW_TRACE_ERROR0 ("rw_t4t_select_app (): Cannot allocate buffer");
375         return FALSE;
376     }
377 
378     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
379     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
380 
381     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
382     UINT8_TO_BE_STREAM (p, T4T_CMD_SELECT_APP);
383     UINT16_TO_BE_STREAM (p, 0x0000);
384     UINT8_TO_BE_STREAM (p, 0x03);                      /* Lc: length of wrapped data */
385     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
386     {
387         UINT24_TO_BE_STREAM (p, T4T_DES_EV1_NFC_APP_ID);
388     }
389     else
390     {
391         UINT24_TO_BE_STREAM(p, T4T_DES_EV0_NFC_APP_ID);
392     }
393 
394     UINT8_TO_BE_STREAM (p, 0x00);                      /* Le */
395 
396     p_c_apdu->len = 9;
397 
398     if (!rw_t4t_send_to_lower (p_c_apdu))
399     {
400         return FALSE;
401     }
402 
403     return TRUE;
404 }
405 
406 /*******************************************************************************
407 **
408 ** Function         rw_t4t_create_ccfile
409 **
410 ** Description      create capability container file cmd to peer
411 **
412 ** Returns          TRUE if success
413 **
414 *******************************************************************************/
rw_t4t_create_ccfile(void)415 static BOOLEAN rw_t4t_create_ccfile (void)
416 {
417     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
418     BT_HDR      *p_c_apdu;
419     UINT8       *p;
420 
421     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
422 
423     if (!p_c_apdu)
424     {
425         RW_TRACE_ERROR0 ("rw_t4t_create_ccfile (): Cannot allocate buffer");
426         return FALSE;
427     }
428 
429     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
430     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
431 
432     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
433     UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_DATAFILE);
434     UINT16_TO_BE_STREAM (p, 0x0000);
435     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
436     {
437         UINT8_TO_BE_STREAM (p, 0x09);                    /* Lc: length of wrapped data */
438         UINT8_TO_BE_STREAM (p, 0x01);                    /* EV1 CC file id             */
439         UINT16_TO_BE_STREAM (p, 0x03E1);                 /* ISO file id                */
440     }
441     else
442     {
443         UINT8_TO_BE_STREAM (p, 0x07);               /* Lc: length of wrapped data */
444         UINT8_TO_BE_STREAM (p, 0x03);               /* DESFire CC file id         */
445     }
446 
447     UINT8_TO_BE_STREAM (p, 0x00);                   /* COMM settings              */
448     UINT16_TO_BE_STREAM (p, 0xEEEE);                /* Access rights              */
449     UINT24_TO_BE_STREAM (p, 0x0F0000);              /* Set file size              */
450     UINT8_TO_BE_STREAM (p, 0x00);                   /* Le                         */
451 
452     p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
453 
454     if (!rw_t4t_send_to_lower (p_c_apdu))
455     {
456         return FALSE;
457     }
458 
459     return TRUE;
460 }
461 
462 /*******************************************************************************
463 **
464 ** Function         rw_t4t_create_ndef
465 **
466 ** Description      creates an ndef file cmd to peer
467 **
468 ** Returns          TRUE if success
469 **
470 *******************************************************************************/
rw_t4t_create_ndef(void)471 static BOOLEAN rw_t4t_create_ndef (void)
472 {
473     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
474     BT_HDR      *p_c_apdu;
475     UINT8       *p;
476 
477     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
478 
479     if (!p_c_apdu)
480     {
481         RW_TRACE_ERROR0 ("rw_t4t_create_ndef (): Cannot allocate buffer");
482         return FALSE;
483     }
484 
485     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
486     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
487 
488     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
489     UINT8_TO_BE_STREAM (p, T4T_CMD_CREATE_DATAFILE);
490     UINT16_TO_BE_STREAM (p, 0x0000);
491     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
492     {
493         UINT8_TO_BE_STREAM (p, 0x09);                   /* Lc: length of wrapped data */
494         UINT8_TO_BE_STREAM (p, 0x02);                   /* DESFEv1 NDEF file id       */
495         UINT16_TO_BE_STREAM (p, 0x04E1);                /* ISO file id                */
496     }
497     else
498     {
499         UINT8_TO_BE_STREAM (p, 0x07);
500         UINT8_TO_BE_STREAM (p, 0x04);                   /* DESF4 NDEF file id        */
501     }
502 
503     UINT8_TO_BE_STREAM (p, 0x00);                       /* COMM settings              */
504     UINT16_TO_BE_STREAM (p, 0xEEEE);                    /* Access rights              */
505     UINT16_TO_STREAM (p, p_t4t->card_size);
506     UINT8_TO_BE_STREAM (p, 0x00);                       /* Set card size              */
507     UINT8_TO_BE_STREAM (p, 0x00);                       /* Le                         */
508 
509     p_c_apdu->len = (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1) ? 15 : 13;
510 
511     if (!rw_t4t_send_to_lower (p_c_apdu))
512     {
513         return FALSE;
514     }
515 
516     return TRUE;
517 }
518 
519 /*******************************************************************************
520 **
521 ** Function         rw_t4t_write_cc
522 **
523 ** Description      sends write cc file cmd to peer
524 **
525 ** Returns          TRUE if success
526 **
527 *******************************************************************************/
rw_t4t_write_cc(void)528 static BOOLEAN rw_t4t_write_cc (void)
529 {
530     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
531     BT_HDR      *p_c_apdu;
532     UINT8       *p;
533     UINT8       CCFileBytes[] = {0x00, 0x0F, 0x10, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x04, 0x00, 0x00, 0x00};
534 
535     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
536 
537     if (!p_c_apdu)
538     {
539         RW_TRACE_ERROR0 ("rw_t4t_write_cc (): Cannot allocate buffer");
540         return FALSE;
541     }
542 
543     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
544     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
545 
546     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
547     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_WRITE);
548     UINT16_TO_BE_STREAM (p, 0x0000);
549     UINT8_TO_BE_STREAM (p, 0x16);                    /* Lc: length of wrapped data  */
550     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
551     {
552         CCFileBytes[2]  = 0x20;
553         CCFileBytes[11] = p_t4t->card_size >> 8;
554         CCFileBytes[12] = (UINT8) p_t4t->card_size;
555         UINT8_TO_BE_STREAM (p, 0x01);               /* CC file id                  */
556     }
557     else
558     {
559         UINT8_TO_BE_STREAM (p, 0x03);
560     }
561 
562     UINT24_TO_BE_STREAM (p, 0x000000);              /* Set the offset              */
563     UINT24_TO_BE_STREAM (p, 0x0F0000);              /* Set available length        */
564     ARRAY_TO_BE_STREAM (p, CCFileBytes, sizeof(CCFileBytes));
565     UINT8_TO_BE_STREAM (p, 0x00);                    /* Le                         */
566 
567     p_c_apdu->len = 28;
568 
569     if (!rw_t4t_send_to_lower (p_c_apdu))
570     {
571         return FALSE;
572     }
573 
574     return TRUE;
575 }
576 
577 /*******************************************************************************
578 **
579 ** Function         rw_t4t_write_ndef
580 **
581 ** Description      sends write ndef file cmd to peer
582 **
583 ** Returns          TRUE if success
584 **
585 *******************************************************************************/
rw_t4t_write_ndef(void)586 static BOOLEAN rw_t4t_write_ndef (void)
587 {
588     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
589     BT_HDR      *p_c_apdu;
590     UINT8       *p;
591 
592     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
593 
594     if (!p_c_apdu)
595     {
596         RW_TRACE_ERROR0 ("rw_t4t_write_ndef (): Cannot allocate buffer");
597         return FALSE;
598     }
599 
600     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
601     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
602 
603     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_CLASS);
604     UINT8_TO_BE_STREAM (p, T4T_CMD_DES_WRITE);
605     UINT16_TO_BE_STREAM (p, 0x0000);
606     UINT8_TO_BE_STREAM (p, 0x09);                    /* Lc: length of wrapped data  */
607     if (p_t4t->card_type == T4T_TYPE_DESFIRE_EV1)
608     {
609         UINT8_TO_BE_STREAM (p, 0x02);               /* DESFEv1 Ndef file id        */
610     }
611     else
612     {
613         UINT8_TO_BE_STREAM (p, 0x04);
614     }
615 
616     UINT24_TO_BE_STREAM (p, 0x000000);              /* Set the offset              */
617     UINT24_TO_BE_STREAM (p, 0x020000);              /* Set available length        */
618     UINT16_TO_BE_STREAM (p, 0x0000);                /* Ndef file bytes             */
619     UINT8_TO_BE_STREAM (p, 0x00);                    /* Le                          */
620 
621     p_c_apdu->len = 15;
622 
623     if (!rw_t4t_send_to_lower (p_c_apdu))
624     {
625         return FALSE;
626     }
627 
628     return TRUE;
629 }
630 
631 /*******************************************************************************
632 **
633 ** Function         rw_t4t_select_file
634 **
635 ** Description      Send Select Command (by File ID) to peer
636 **
637 ** Returns          TRUE if success
638 **
639 *******************************************************************************/
rw_t4t_select_file(UINT16 file_id)640 static BOOLEAN rw_t4t_select_file (UINT16 file_id)
641 {
642     BT_HDR      *p_c_apdu;
643     UINT8       *p;
644 
645     RW_TRACE_DEBUG1 ("rw_t4t_select_file (): File ID:0x%04X", file_id);
646 
647     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
648 
649     if (!p_c_apdu)
650     {
651         RW_TRACE_ERROR0 ("rw_t4t_select_file (): Cannot allocate buffer");
652         return FALSE;
653     }
654 
655     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
656     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
657 
658     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
659     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
660     UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_FILE_ID);
661 
662     /* if current version mapping is V2.0 */
663     if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0)
664     {
665         UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_0CH);
666     }
667     else /* version 1.0 */
668     {
669         UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
670     }
671 
672     UINT8_TO_BE_STREAM (p, T4T_FILE_ID_SIZE);
673     UINT16_TO_BE_STREAM (p, file_id);
674 
675     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE;
676 
677     if (!rw_t4t_send_to_lower (p_c_apdu))
678     {
679         return FALSE;
680     }
681 
682     return TRUE;
683 }
684 
685 /*******************************************************************************
686 **
687 ** Function         rw_t4t_read_file
688 **
689 ** Description      Send ReadBinary Command to peer
690 **
691 ** Returns          TRUE if success
692 **
693 *******************************************************************************/
rw_t4t_read_file(UINT16 offset,UINT16 length,BOOLEAN is_continue)694 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue)
695 {
696     tRW_T4T_CB      *p_t4t = &rw_cb.tcb.t4t;
697     BT_HDR          *p_c_apdu;
698     UINT8           *p;
699 
700     RW_TRACE_DEBUG3 ("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ",
701                       offset, length, is_continue);
702 
703     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
704 
705     if (!p_c_apdu)
706     {
707         RW_TRACE_ERROR0 ("rw_t4t_read_file (): Cannot allocate buffer");
708         return FALSE;
709     }
710 
711     /* if this is the first reading */
712     if (is_continue == FALSE)
713     {
714         /* initialise starting offset and total length */
715         /* these will be updated when receiving response */
716         p_t4t->rw_offset = offset;
717         p_t4t->rw_length = length;
718     }
719 
720     /* adjust reading length if payload is bigger than max size per single command */
721     if (length > p_t4t->max_read_size)
722     {
723         length = (UINT8) (p_t4t->max_read_size);
724     }
725 
726     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
727     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
728 
729     UINT8_TO_BE_STREAM (p, (T4T_CMD_CLASS | rw_cb.tcb.t4t.channel));
730     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_READ_BINARY);
731     UINT16_TO_BE_STREAM (p, offset);
732     UINT8_TO_BE_STREAM (p, length); /* Le */
733 
734     p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
735 
736     if (!rw_t4t_send_to_lower (p_c_apdu))
737     {
738         return FALSE;
739     }
740 
741     return TRUE;
742 }
743 
744 /*******************************************************************************
745 **
746 ** Function         rw_t4t_update_nlen
747 **
748 ** Description      Send UpdateBinary Command to update NLEN to peer
749 **
750 ** Returns          TRUE if success
751 **
752 *******************************************************************************/
rw_t4t_update_nlen(UINT16 ndef_len)753 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len)
754 {
755     BT_HDR          *p_c_apdu;
756     UINT8           *p;
757 
758     RW_TRACE_DEBUG1 ("rw_t4t_update_nlen () NLEN:%d", ndef_len);
759 
760     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
761 
762     if (!p_c_apdu)
763     {
764         RW_TRACE_ERROR0 ("rw_t4t_update_nlen (): Cannot allocate buffer");
765         return FALSE;
766     }
767 
768     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
769     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
770 
771     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
772     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
773     UINT16_TO_BE_STREAM (p, 0x0000);                    /* offset for NLEN */
774     UINT8_TO_BE_STREAM (p, T4T_FILE_LENGTH_SIZE);
775     UINT16_TO_BE_STREAM (p, ndef_len);
776 
777     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE;
778 
779     if (!rw_t4t_send_to_lower (p_c_apdu))
780     {
781         return FALSE;
782     }
783 
784     return TRUE;
785 }
786 
787 /*******************************************************************************
788 **
789 ** Function         rw_t4t_update_file
790 **
791 ** Description      Send UpdateBinary Command to peer
792 **
793 ** Returns          TRUE if success
794 **
795 *******************************************************************************/
rw_t4t_update_file(void)796 static BOOLEAN rw_t4t_update_file (void)
797 {
798     tRW_T4T_CB      *p_t4t = &rw_cb.tcb.t4t;
799     BT_HDR          *p_c_apdu;
800     UINT8           *p;
801     UINT16          length;
802 
803     RW_TRACE_DEBUG2 ("rw_t4t_update_file () rw_offset:%d, rw_length:%d",
804                       p_t4t->rw_offset, p_t4t->rw_length);
805 
806     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
807 
808     if (!p_c_apdu)
809     {
810         RW_TRACE_ERROR0 ("rw_t4t_write_file (): Cannot allocate buffer");
811         return FALSE;
812     }
813 
814     /* try to send all of remaining data */
815     length = p_t4t->rw_length;
816 
817     /* adjust updating length if payload is bigger than max size per single command */
818     if (length > p_t4t->max_update_size)
819     {
820         length = (UINT8) (p_t4t->max_update_size);
821     }
822 
823     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
824     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
825 
826     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
827     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
828     UINT16_TO_BE_STREAM (p, p_t4t->rw_offset);
829     UINT8_TO_BE_STREAM (p, length);
830 
831     memcpy (p, p_t4t->p_update_data, length);
832 
833     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
834 
835     if (!rw_t4t_send_to_lower (p_c_apdu))
836     {
837         return FALSE;
838     }
839 
840     /* adjust offset, length and pointer for remaining data */
841     p_t4t->rw_offset     += length;
842     p_t4t->rw_length     -= length;
843     p_t4t->p_update_data += length;
844 
845     return TRUE;
846 }
847 
848 /*******************************************************************************
849 **
850 ** Function         rw_t4t_update_cc_to_readonly
851 **
852 ** Description      Send UpdateBinary Command for changing Write access
853 **
854 ** Returns          TRUE if success
855 **
856 *******************************************************************************/
rw_t4t_update_cc_to_readonly(void)857 static BOOLEAN rw_t4t_update_cc_to_readonly (void)
858 {
859     BT_HDR          *p_c_apdu;
860     UINT8           *p;
861 
862     RW_TRACE_DEBUG0 ("rw_t4t_update_cc_to_readonly (): Remove Write access from CC");
863 
864     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
865 
866     if (!p_c_apdu)
867     {
868         RW_TRACE_ERROR0 ("rw_t4t_update_cc_to_readonly (): Cannot allocate buffer");
869         return FALSE;
870     }
871 
872     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
873     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
874 
875     /* Add Command Header */
876     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
877     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
878     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 */
879     UINT8_TO_BE_STREAM (p, 1); /* Length of write access field in cc interms of bytes */
880 
881     /* Remove Write access */
882     UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS);
883 
884 
885     p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + 1;
886 
887     if (!rw_t4t_send_to_lower (p_c_apdu))
888     {
889         return FALSE;
890     }
891 
892     return TRUE;
893 }
894 
895 /*******************************************************************************
896 **
897 ** Function         rw_t4t_select_application
898 **
899 ** Description      Select Application
900 **
901 **                  NDEF Tag Application Select - C-APDU
902 **
903 **                        CLA INS P1 P2 Lc Data(AID)      Le
904 **                  V1.0: 00  A4  04 00 07 D2760000850100 -
905 **                  V2.0: 00  A4  04 00 07 D2760000850101 00
906 **
907 ** Returns          TRUE if success
908 **
909 *******************************************************************************/
rw_t4t_select_application(UINT8 version)910 static BOOLEAN rw_t4t_select_application (UINT8 version)
911 {
912     BT_HDR      *p_c_apdu;
913     UINT8       *p;
914 
915     RW_TRACE_DEBUG1 ("rw_t4t_select_application () version:0x%X", version);
916 
917     p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
918 
919     if (!p_c_apdu)
920     {
921         RW_TRACE_ERROR0 ("rw_t4t_select_application (): Cannot allocate buffer");
922         return FALSE;
923     }
924 
925     p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
926     p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
927 
928     UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
929     UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
930     UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_NAME);
931     UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
932 
933     if (version == T4T_VERSION_1_0)   /* this is for V1.0 */
934     {
935         UINT8_TO_BE_STREAM (p, T4T_V10_NDEF_TAG_AID_LEN);
936 
937         memcpy (p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN);
938 
939         p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN;
940     }
941     else if (version == T4T_VERSION_2_0)   /* this is for V2.0 */
942     {
943         UINT8_TO_BE_STREAM (p, T4T_V20_NDEF_TAG_AID_LEN);
944 
945         memcpy (p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN);
946         p += T4T_V20_NDEF_TAG_AID_LEN;
947 
948         UINT8_TO_BE_STREAM (p, 0x00); /* Le set to 0x00 */
949 
950         p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1;
951     }
952     else
953     {
954         return FALSE;
955     }
956 
957     if (!rw_t4t_send_to_lower (p_c_apdu))
958     {
959         return FALSE;
960     }
961 
962     return TRUE;
963 }
964 
965 /*******************************************************************************
966 **
967 ** Function         rw_t4t_validate_cc_file
968 **
969 ** Description      Validate CC file and mandatory NDEF TLV
970 **
971 ** Returns          TRUE if success
972 **
973 *******************************************************************************/
rw_t4t_validate_cc_file(void)974 static BOOLEAN rw_t4t_validate_cc_file (void)
975 {
976     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
977 
978     RW_TRACE_DEBUG0 ("rw_t4t_validate_cc_file ()");
979 
980     if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN)
981     {
982         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): CCLEN (%d) is too short",
983                          p_t4t->cc_file.cclen);
984         return FALSE;
985     }
986 
987     if (T4T_GET_MAJOR_VERSION (p_t4t->cc_file.version) != T4T_GET_MAJOR_VERSION (p_t4t->version))
988     {
989         RW_TRACE_ERROR2 ("rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours (0x%02X)",
990                          p_t4t->cc_file.version, p_t4t->version);
991         return FALSE;
992     }
993 
994     if (p_t4t->cc_file.max_le < 0x000F)
995     {
996         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLe (%d) is too small",
997                          p_t4t->cc_file.max_le);
998         return FALSE;
999     }
1000 
1001     if (p_t4t->cc_file.max_lc < 0x0001)
1002     {
1003         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLc (%d) is too small",
1004                          p_t4t->cc_file.max_lc);
1005         return FALSE;
1006     }
1007 
1008     if (  (p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID)
1009         ||(p_t4t->cc_file.ndef_fc.file_id == 0xE102)
1010         ||(p_t4t->cc_file.ndef_fc.file_id == 0xE103)
1011         ||((p_t4t->cc_file.ndef_fc.file_id == 0x0000) && (p_t4t->cc_file.version == 0x20))
1012         ||(p_t4t->cc_file.ndef_fc.file_id == 0x3F00)
1013         ||(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF)
1014         ||(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)  )
1015     {
1016         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid",
1017                           p_t4t->cc_file.ndef_fc.file_id);
1018         return FALSE;
1019     }
1020 
1021     if (  (p_t4t->cc_file.ndef_fc.max_file_size < 0x0005)
1022         ||(p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)  )
1023     {
1024         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): max_file_size (%d) is reserved",
1025                          p_t4t->cc_file.ndef_fc.max_file_size);
1026         return FALSE;
1027     }
1028 
1029     if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS)
1030     {
1031         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid",
1032                           p_t4t->cc_file.ndef_fc.read_access);
1033         return FALSE;
1034     }
1035 
1036     if (  (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
1037         &&(p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS)  )
1038     {
1039         RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid",
1040                           p_t4t->cc_file.ndef_fc.write_access);
1041         return FALSE;
1042     }
1043 
1044     return TRUE;
1045 }
1046 
1047 /*******************************************************************************
1048 **
1049 ** Function         rw_t4t_handle_error
1050 **
1051 ** Description      notify error to application and clean up
1052 **
1053 ** Returns          none
1054 **
1055 *******************************************************************************/
rw_t4t_handle_error(tNFC_STATUS status,UINT8 sw1,UINT8 sw2)1056 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2)
1057 {
1058     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1059     tRW_DATA    rw_data;
1060     tRW_EVENT   event;
1061 
1062     RW_TRACE_DEBUG4 ("rw_t4t_handle_error (): status:0x%02X, sw1:0x%02X, sw2:0x%02X, state:0x%X",
1063                       status, sw1, sw2, p_t4t->state);
1064 
1065     nfc_stop_quick_timer (&p_t4t->timer);
1066 
1067     if (rw_cb.p_cback)
1068     {
1069         rw_data.status = status;
1070 
1071         rw_data.t4t_sw.sw1    = sw1;
1072         rw_data.t4t_sw.sw2    = sw2;
1073 
1074         switch (p_t4t->state)
1075         {
1076         case RW_T4T_STATE_DETECT_NDEF:
1077             rw_data.ndef.flags  = RW_NDEF_FL_UNKNOWN;
1078             event = RW_T4T_NDEF_DETECT_EVT;
1079             break;
1080 
1081         case RW_T4T_STATE_READ_NDEF:
1082             event = RW_T4T_NDEF_READ_FAIL_EVT;
1083             break;
1084 
1085         case RW_T4T_STATE_UPDATE_NDEF:
1086             event = RW_T4T_NDEF_UPDATE_FAIL_EVT;
1087             break;
1088 
1089         case RW_T4T_STATE_PRESENCE_CHECK:
1090             event = RW_T4T_PRESENCE_CHECK_EVT;
1091             rw_data.status = NFC_STATUS_FAILED;
1092             break;
1093 
1094         case RW_T4T_STATE_SET_READ_ONLY:
1095             event = RW_T4T_SET_TO_RO_EVT;
1096             break;
1097 
1098         case RW_T4T_STATE_NDEF_FORMAT:
1099             event = RW_T4T_NDEF_FORMAT_CPLT_EVT;
1100             rw_data.status = NFC_STATUS_FAILED;
1101             break;
1102 
1103         default:
1104             event = RW_T4T_MAX_EVT;
1105             break;
1106         }
1107 
1108         p_t4t->state = RW_T4T_STATE_IDLE;
1109 
1110         if (event != RW_T4T_MAX_EVT)
1111         {
1112             (*(rw_cb.p_cback)) (event, &rw_data);
1113         }
1114     }
1115     else
1116     {
1117         p_t4t->state = RW_T4T_STATE_IDLE;
1118     }
1119 }
1120 
1121 /*******************************************************************************
1122 **
1123 ** Function         rw_t4t_sm_ndef_format
1124 **
1125 ** Description      State machine for NDEF format procedure
1126 **
1127 ** Returns          none
1128 **
1129 *******************************************************************************/
rw_t4t_sm_ndef_format(BT_HDR * p_r_apdu)1130 static void rw_t4t_sm_ndef_format (BT_HDR *p_r_apdu)
1131 {
1132     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1133     UINT8       *p, type, length;
1134     UINT16      status_words, nlen;
1135     tRW_DATA    rw_data;
1136 
1137 #if (BT_TRACE_VERBOSE == TRUE)
1138     RW_TRACE_DEBUG2 ("rw_t4t_sm_ndef_format (): sub_state:%s (%d)",
1139                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1140 #else
1141     RW_TRACE_DEBUG1 ("rw_t4t_sm_ndef_format (): sub_state=%d", p_t4t->sub_state);
1142 #endif
1143 
1144     /* get status words */
1145     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1146 
1147     switch (p_t4t->sub_state)
1148     {
1149     case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
1150         p += (p_r_apdu->len - 1);
1151         if (*(p) == T4T_ADDI_FRAME_RESP)
1152         {
1153             if (!rw_t4t_get_sw_version ())
1154             {
1155                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1156             }
1157             else
1158             {
1159                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION;
1160             }
1161         }
1162         else
1163         {
1164             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1165         }
1166         break;
1167 
1168     case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
1169         p += (p_r_apdu->len - 1);
1170         if (*(p) == T4T_ADDI_FRAME_RESP)
1171         {
1172             if (!rw_t4t_update_version_details (p_r_apdu))
1173             {
1174                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1175             }
1176 
1177             if (!rw_t4t_get_uid_details ())
1178             {
1179                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1180             }
1181 
1182             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_UID;
1183         }
1184         else
1185         {
1186             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1187         }
1188         break;
1189 
1190     case RW_T4T_SUBSTATE_WAIT_GET_UID:
1191         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1192         BE_STREAM_TO_UINT16 (status_words, p);
1193         if (status_words != 0x9100)
1194         {
1195             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1196         }
1197         else
1198         {
1199             if (!rw_t4t_create_app ())
1200             {
1201                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1202             }
1203             else
1204             {
1205                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_APP;
1206             }
1207 
1208         }
1209         break;
1210 
1211     case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
1212         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1213         BE_STREAM_TO_UINT16 (status_words, p);
1214         if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1215         {
1216             status_words = 0x9100;
1217         }
1218 
1219         if (status_words != 0x9100)
1220         {
1221             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1222         }
1223         else
1224         {
1225             if (!rw_t4t_select_app ())
1226             {
1227                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1228             }
1229             else
1230             {
1231                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1232             }
1233         }
1234         break;
1235 
1236     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1237         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1238         BE_STREAM_TO_UINT16 (status_words, p);
1239         if (status_words != 0x9100)
1240         {
1241             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1242         }
1243         else
1244         {
1245             if (!rw_t4t_create_ccfile ())
1246             {
1247                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1248             }
1249             else
1250             {
1251                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_CC;
1252             }
1253 
1254         }
1255         break;
1256 
1257     case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
1258         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1259         BE_STREAM_TO_UINT16 (status_words, p);
1260         if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1261         {
1262             status_words = 0x9100;
1263         }
1264 
1265         if (status_words != 0x9100)
1266         {
1267             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1268         }
1269         else
1270         {
1271             if (!rw_t4t_create_ndef ())
1272             {
1273                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1274             }
1275             else
1276             {
1277                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_NDEF;
1278             }
1279         }
1280         break;
1281 
1282     case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
1283         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1284         BE_STREAM_TO_UINT16 (status_words, p);
1285         if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1286         {
1287             status_words = 0x9100;
1288         }
1289 
1290         if (status_words != 0x9100)
1291         {
1292             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1293         }
1294         else
1295         {
1296             if (!rw_t4t_write_cc ())
1297             {
1298                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1299             }
1300             else
1301             {
1302                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_CC;
1303             }
1304         }
1305         break;
1306 
1307     case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
1308         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1309         BE_STREAM_TO_UINT16 (status_words, p);
1310         if (status_words != 0x9100)
1311         {
1312             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1313         }
1314         else
1315         {
1316             if (!rw_t4t_write_ndef ())
1317             {
1318                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1319             }
1320             else
1321             {
1322                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_NDEF;
1323             }
1324         }
1325         break;
1326 
1327     case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
1328         p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1329         BE_STREAM_TO_UINT16 (status_words, p);
1330         if (status_words != 0x9100)
1331         {
1332             rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1333         }
1334         else
1335         {
1336             p_t4t->state = RW_T4T_STATE_IDLE;
1337             if (rw_cb.p_cback)
1338             {
1339                 rw_data.ndef.status   = NFC_STATUS_OK;
1340                 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1341                 rw_data.ndef.max_size = p_t4t->card_size;
1342                 rw_data.ndef.cur_size = 0x00;
1343 
1344                 (*(rw_cb.p_cback)) (RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
1345 
1346                 RW_TRACE_DEBUG0 ("rw_t4t_ndef_format (): Sent RW_T4T_NDEF_FORMAT_CPLT_EVT");
1347             }
1348         }
1349         break;
1350 
1351     default:
1352         RW_TRACE_ERROR1 ("rw_t4t_sm_ndef_format (): unknown sub_state=%d", p_t4t->sub_state);
1353         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1354         break;
1355     }
1356 }
1357 
1358 /*******************************************************************************
1359 **
1360 ** Function         rw_t4t_sm_detect_ndef
1361 **
1362 ** Description      State machine for NDEF detection procedure
1363 **
1364 ** Returns          none
1365 **
1366 *******************************************************************************/
rw_t4t_sm_detect_ndef(BT_HDR * p_r_apdu)1367 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu)
1368 {
1369     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1370     UINT8       *p, type, length;
1371     UINT16      status_words, nlen;
1372     tRW_DATA    rw_data;
1373 
1374 #if (BT_TRACE_VERBOSE == TRUE)
1375     RW_TRACE_DEBUG2 ("rw_t4t_sm_detect_ndef (): sub_state:%s (%d)",
1376                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1377 #else
1378     RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): sub_state=%d", p_t4t->sub_state);
1379 #endif
1380 
1381     /* get status words */
1382     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1383     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1384     BE_STREAM_TO_UINT16 (status_words, p);
1385 
1386     if (status_words != T4T_RSP_CMD_CMPLTED)
1387     {
1388         /* try V1.0 after failing of V2.0 */
1389         if (  (p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP)
1390             &&(p_t4t->version   == T4T_VERSION_2_0)  )
1391         {
1392             p_t4t->version = T4T_VERSION_1_0;
1393 
1394             RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): retry with version=0x%02X",
1395                               p_t4t->version);
1396 
1397             if (!rw_t4t_select_application (T4T_VERSION_1_0))
1398             {
1399                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1400             }
1401             return;
1402         }
1403 
1404         p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1405         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1406         return;
1407     }
1408 
1409     switch (p_t4t->sub_state)
1410     {
1411     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1412 
1413         /* NDEF Tag application has been selected then select CC file */
1414         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1415         {
1416             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1417         }
1418         else
1419         {
1420             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1421         }
1422         break;
1423 
1424     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1425 
1426         /* CC file has been selected then read mandatory part of CC file */
1427         if (!rw_t4t_read_file (0x00, T4T_CC_FILE_MIN_LEN, FALSE))
1428         {
1429             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1430         }
1431         else
1432         {
1433             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
1434         }
1435         break;
1436 
1437     case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1438 
1439         /* CC file has been read then validate and select mandatory NDEF file */
1440         if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE)
1441         {
1442             p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1443 
1444             BE_STREAM_TO_UINT16 (p_t4t->cc_file.cclen, p);
1445             BE_STREAM_TO_UINT8 (p_t4t->cc_file.version, p);
1446             BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_le, p);
1447             BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_lc, p);
1448 
1449             BE_STREAM_TO_UINT8 (type, p);
1450             BE_STREAM_TO_UINT8 (length, p);
1451 
1452             if (  (type == T4T_NDEF_FILE_CONTROL_TYPE)
1453                 &&(length == T4T_FILE_CONTROL_LENGTH)  )
1454             {
1455                 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.file_id, p);
1456                 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.max_file_size, p);
1457                 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.read_access, p);
1458                 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.write_access, p);
1459 
1460 #if (BT_TRACE_VERBOSE == TRUE)
1461                 RW_TRACE_DEBUG0 ("Capability Container (CC) file");
1462                 RW_TRACE_DEBUG1 ("  CCLEN:  0x%04X",    p_t4t->cc_file.cclen);
1463                 RW_TRACE_DEBUG1 ("  Version:0x%02X",    p_t4t->cc_file.version);
1464                 RW_TRACE_DEBUG1 ("  MaxLe:  0x%04X",    p_t4t->cc_file.max_le);
1465                 RW_TRACE_DEBUG1 ("  MaxLc:  0x%04X",    p_t4t->cc_file.max_lc);
1466                 RW_TRACE_DEBUG0 ("  NDEF File Control TLV");
1467                 RW_TRACE_DEBUG1 ("    FileID:      0x%04X", p_t4t->cc_file.ndef_fc.file_id);
1468                 RW_TRACE_DEBUG1 ("    MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
1469                 RW_TRACE_DEBUG1 ("    ReadAccess:  0x%02X", p_t4t->cc_file.ndef_fc.read_access);
1470                 RW_TRACE_DEBUG1 ("    WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
1471 #endif
1472 
1473                 if (rw_t4t_validate_cc_file ())
1474                 {
1475                     if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
1476                     {
1477                         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1478                     }
1479                     else
1480                     {
1481                         p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1482                     }
1483                     break;
1484                 }
1485             }
1486         }
1487 
1488         /* invalid response or CC file */
1489         p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1490         rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
1491         break;
1492 
1493     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1494 
1495         /* NDEF file has been selected then read the first 2 bytes (NLEN) */
1496         if (!rw_t4t_read_file (0, T4T_FILE_LENGTH_SIZE, FALSE))
1497         {
1498             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1499         }
1500         else
1501         {
1502             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
1503         }
1504         break;
1505 
1506     case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1507 
1508         /* NLEN has been read then report upper layer */
1509         if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE)
1510         {
1511             /* get length of NDEF */
1512             p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1513             BE_STREAM_TO_UINT16 (nlen, p);
1514 
1515             if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE)
1516             {
1517                 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
1518 
1519                 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
1520                 {
1521                     p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1522                 }
1523 
1524                 /* Get max bytes to read per command */
1525                 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ)
1526                 {
1527                     p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
1528                 }
1529                 else
1530                 {
1531                     p_t4t->max_read_size = p_t4t->cc_file.max_le;
1532                 }
1533 
1534                 /* Le: valid range is 0x01 to 0xFF */
1535                 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE)
1536                 {
1537                     p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1538                 }
1539 
1540                 /* Get max bytes to update per command */
1541                 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE)
1542                 {
1543                     p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
1544                 }
1545                 else
1546                 {
1547                     p_t4t->max_update_size = p_t4t->cc_file.max_lc;
1548                 }
1549 
1550                 /* Lc: valid range is 0x01 to 0xFF */
1551                 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC)
1552                 {
1553                     p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1554                 }
1555 
1556                 p_t4t->ndef_length = nlen;
1557                 p_t4t->state       = RW_T4T_STATE_IDLE;
1558 
1559                 if (rw_cb.p_cback)
1560                 {
1561                     rw_data.ndef.status   = NFC_STATUS_OK;
1562                     rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1563                     rw_data.ndef.max_size = (UINT32) (p_t4t->cc_file.ndef_fc.max_file_size - (UINT16) T4T_FILE_LENGTH_SIZE);
1564                     rw_data.ndef.cur_size = nlen;
1565                     rw_data.ndef.flags    = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
1566                     if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
1567                     {
1568                         rw_data.ndef.flags    |= RW_NDEF_FL_READ_ONLY;
1569                     }
1570 
1571                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_DETECT_EVT, &rw_data);
1572 
1573                     RW_TRACE_DEBUG0 ("rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT");
1574                 }
1575             }
1576             else
1577             {
1578                 /* NLEN should be less than max file size */
1579                 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file size (%d)",
1580                                  nlen, p_t4t->cc_file.ndef_fc.max_file_size);
1581 
1582                 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1583                 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
1584             }
1585         }
1586         else
1587         {
1588             /* response payload size should be T4T_FILE_LENGTH_SIZE */
1589             RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d",
1590                              p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);
1591 
1592             p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1593             rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
1594         }
1595         break;
1596 
1597     default:
1598         RW_TRACE_ERROR1 ("rw_t4t_sm_detect_ndef (): unknown sub_state=%d", p_t4t->sub_state);
1599         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1600         break;
1601     }
1602 }
1603 
1604 /*******************************************************************************
1605 **
1606 ** Function         rw_t4t_sm_read_ndef
1607 **
1608 ** Description      State machine for NDEF read procedure
1609 **
1610 ** Returns          none
1611 **
1612 *******************************************************************************/
rw_t4t_sm_read_ndef(BT_HDR * p_r_apdu)1613 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu)
1614 {
1615     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1616     UINT8       *p;
1617     UINT16      status_words;
1618     tRW_DATA    rw_data;
1619 
1620 #if (BT_TRACE_VERBOSE == TRUE)
1621     RW_TRACE_DEBUG2 ("rw_t4t_sm_read_ndef (): sub_state:%s (%d)",
1622                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1623 #else
1624     RW_TRACE_DEBUG1 ("rw_t4t_sm_read_ndef (): sub_state=%d", p_t4t->sub_state);
1625 #endif
1626 
1627     /* get status words */
1628     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1629     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1630     BE_STREAM_TO_UINT16 (status_words, p);
1631 
1632     if (status_words != T4T_RSP_CMD_CMPLTED)
1633     {
1634         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1635         GKI_freebuf (p_r_apdu);
1636         return;
1637     }
1638 
1639     switch (p_t4t->sub_state)
1640     {
1641     case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1642 
1643         /* Read partial or complete data */
1644         p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
1645 
1646         if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length))
1647         {
1648             p_t4t->rw_length -= p_r_apdu->len;
1649             p_t4t->rw_offset += p_r_apdu->len;
1650 
1651             if (rw_cb.p_cback)
1652             {
1653                 rw_data.data.status = NFC_STATUS_OK;
1654                 rw_data.data.p_data = p_r_apdu;
1655 
1656                 /* if need to read more data */
1657                 if (p_t4t->rw_length > 0)
1658                 {
1659                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_EVT, &rw_data);
1660 
1661                     if (!rw_t4t_read_file (p_t4t->rw_offset, p_t4t->rw_length, TRUE))
1662                     {
1663                         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1664                     }
1665                 }
1666                 else
1667                 {
1668                     p_t4t->state = RW_T4T_STATE_IDLE;
1669 
1670                     (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
1671 
1672                     RW_TRACE_DEBUG0 ("rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT");
1673 
1674                 }
1675 
1676                 p_r_apdu = NULL;
1677             }
1678             else
1679             {
1680                 p_t4t->rw_length = 0;
1681                 p_t4t->state = RW_T4T_STATE_IDLE;
1682             }
1683         }
1684         else
1685         {
1686             RW_TRACE_ERROR2 ("rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length (%d)",
1687                              p_r_apdu->len, p_t4t->rw_length);
1688             rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
1689         }
1690         break;
1691 
1692     default:
1693         RW_TRACE_ERROR1 ("rw_t4t_sm_read_ndef (): unknown sub_state = %d", p_t4t->sub_state);
1694         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1695         break;
1696     }
1697 
1698     if (p_r_apdu)
1699         GKI_freebuf (p_r_apdu);
1700 }
1701 
1702 /*******************************************************************************
1703 **
1704 ** Function         rw_t4t_sm_update_ndef
1705 **
1706 ** Description      State machine for NDEF update procedure
1707 **
1708 ** Returns          none
1709 **
1710 *******************************************************************************/
rw_t4t_sm_update_ndef(BT_HDR * p_r_apdu)1711 static void rw_t4t_sm_update_ndef (BT_HDR  *p_r_apdu)
1712 {
1713     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1714     UINT8       *p;
1715     UINT16      status_words;
1716     tRW_DATA    rw_data;
1717 
1718 #if (BT_TRACE_VERBOSE == TRUE)
1719     RW_TRACE_DEBUG2 ("rw_t4t_sm_update_ndef (): sub_state:%s (%d)",
1720                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1721 #else
1722     RW_TRACE_DEBUG1 ("rw_t4t_sm_update_ndef (): sub_state=%d", p_t4t->sub_state);
1723 #endif
1724 
1725     /* Get status words */
1726     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1727     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1728     BE_STREAM_TO_UINT16 (status_words, p);
1729 
1730     if (status_words != T4T_RSP_CMD_CMPLTED)
1731     {
1732         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1733         return;
1734     }
1735 
1736     switch (p_t4t->sub_state)
1737     {
1738     case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1739 
1740         /* NLEN has been updated */
1741         /* if need to update data */
1742         if (p_t4t->p_update_data)
1743         {
1744             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;
1745 
1746             if (!rw_t4t_update_file ())
1747             {
1748                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1749                 p_t4t->p_update_data = NULL;
1750             }
1751         }
1752         else
1753         {
1754             p_t4t->state = RW_T4T_STATE_IDLE;
1755 
1756             /* just finished last step of updating (updating NLEN) */
1757             if (rw_cb.p_cback)
1758             {
1759                 rw_data.status = NFC_STATUS_OK;
1760 
1761                 (*(rw_cb.p_cback)) (RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
1762                 RW_TRACE_DEBUG0 ("rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
1763             }
1764         }
1765         break;
1766 
1767     case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1768 
1769         /* if updating is not completed */
1770         if (p_t4t->rw_length > 0)
1771         {
1772             if (!rw_t4t_update_file ())
1773             {
1774                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1775                 p_t4t->p_update_data = NULL;
1776             }
1777         }
1778         else
1779         {
1780             p_t4t->p_update_data = NULL;
1781 
1782             /* update NLEN as last step of updating file */
1783             if (!rw_t4t_update_nlen (p_t4t->ndef_length))
1784             {
1785                 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1786             }
1787             else
1788             {
1789                 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1790             }
1791         }
1792         break;
1793 
1794     default:
1795         RW_TRACE_ERROR1 ("rw_t4t_sm_update_ndef (): unknown sub_state = %d", p_t4t->sub_state);
1796         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1797         break;
1798     }
1799 }
1800 
1801 /*******************************************************************************
1802 **
1803 ** Function         rw_t4t_sm_set_readonly
1804 **
1805 ** Description      State machine for CC update procedure
1806 **
1807 ** Returns          none
1808 **
1809 *******************************************************************************/
rw_t4t_sm_set_readonly(BT_HDR * p_r_apdu)1810 static void rw_t4t_sm_set_readonly (BT_HDR  *p_r_apdu)
1811 {
1812     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1813     UINT8       *p;
1814     UINT16      status_words;
1815     tRW_DATA    rw_data;
1816 
1817 #if (BT_TRACE_VERBOSE == TRUE)
1818     RW_TRACE_DEBUG2 ("rw_t4t_sm_set_readonly (): sub_state:%s (%d)",
1819                       rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1820 #else
1821     RW_TRACE_DEBUG1 ("rw_t4t_sm_set_readonly (): sub_state=%d", p_t4t->sub_state);
1822 #endif
1823 
1824     /* Get status words */
1825     p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1826     p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1827     BE_STREAM_TO_UINT16 (status_words, p);
1828 
1829     if (status_words != T4T_RSP_CMD_CMPLTED)
1830     {
1831         rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1832         return;
1833     }
1834 
1835     switch (p_t4t->sub_state)
1836     {
1837     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1838 
1839         /* CC file has been selected then update write access to read-only in CC file */
1840         if (!rw_t4t_update_cc_to_readonly ())
1841         {
1842             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1843         }
1844         else
1845         {
1846             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC;
1847         }
1848         break;
1849 
1850     case RW_T4T_SUBSTATE_WAIT_UPDATE_CC:
1851         /* CC Updated, Select NDEF File to allow NDEF operation */
1852         p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS;
1853         p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1854 
1855         if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
1856         {
1857             rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1858         }
1859         else
1860         {
1861             p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1862         }
1863         break;
1864 
1865     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1866         p_t4t->state = RW_T4T_STATE_IDLE;
1867         /* just finished last step of configuring tag read only (Selecting NDEF file CC) */
1868         if (rw_cb.p_cback)
1869         {
1870             rw_data.status = NFC_STATUS_OK;
1871 
1872             RW_TRACE_DEBUG0 ("rw_t4t_sm_set_readonly (): Sent RW_T4T_SET_TO_RO_EVT");
1873             (*(rw_cb.p_cback)) (RW_T4T_SET_TO_RO_EVT, &rw_data);
1874         }
1875         break;
1876 
1877     default:
1878         RW_TRACE_ERROR1 ("rw_t4t_sm_set_readonly (): unknown sub_state = %d", p_t4t->sub_state);
1879         rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1880         break;
1881     }
1882 }
1883 
1884 /*******************************************************************************
1885 **
1886 ** Function         rw_t4t_process_timeout
1887 **
1888 ** Description      process timeout event
1889 **
1890 ** Returns          none
1891 **
1892 *******************************************************************************/
rw_t4t_process_timeout(TIMER_LIST_ENT * p_tle)1893 void rw_t4t_process_timeout (TIMER_LIST_ENT *p_tle)
1894 {
1895     RW_TRACE_DEBUG1 ("rw_t4t_process_timeout () event=%d", p_tle->event);
1896 
1897     if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE)
1898     {
1899         rw_t4t_handle_error (NFC_STATUS_TIMEOUT, 0, 0);
1900     }
1901     else
1902     {
1903         RW_TRACE_ERROR1 ("rw_t4t_process_timeout () unknown event=%d", p_tle->event);
1904     }
1905 }
1906 
1907 /*******************************************************************************
1908 **
1909 ** Function         rw_t4t_data_cback
1910 **
1911 ** Description      This callback function receives the data from NFCC.
1912 **
1913 ** Returns          none
1914 **
1915 *******************************************************************************/
rw_t4t_data_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)1916 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
1917 {
1918     tRW_T4T_CB *p_t4t    = &rw_cb.tcb.t4t;
1919     BT_HDR     *p_r_apdu;
1920     tRW_DATA    rw_data;
1921 
1922 #if (BT_TRACE_VERBOSE == TRUE)
1923     UINT8  begin_state   = p_t4t->state;
1924 #endif
1925 
1926     RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event);
1927     nfc_stop_quick_timer (&p_t4t->timer);
1928 
1929     switch (event)
1930     {
1931     case NFC_DEACTIVATE_CEVT:
1932         NFC_SetStaticRfCback (NULL);
1933         p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
1934         return;
1935 
1936     case NFC_ERROR_CEVT:
1937         if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK)
1938         {
1939             p_t4t->state   = RW_T4T_STATE_IDLE;
1940             rw_data.status = NFC_STATUS_FAILED;
1941             (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1942         }
1943         else if (p_t4t->state == RW_T4T_STATE_NDEF_FORMAT)
1944         {
1945             p_t4t->state   = RW_T4T_STATE_IDLE;
1946             rw_data.status = NFC_STATUS_FAILED;
1947             (*(rw_cb.p_cback)) (RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
1948         }
1949         else if (p_t4t->state != RW_T4T_STATE_IDLE)
1950         {
1951             rw_t4t_handle_error (rw_data.status, 0, 0);
1952         }
1953         else
1954         {
1955             p_t4t->state   = RW_T4T_STATE_IDLE;
1956             rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
1957             (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data);
1958         }
1959         return;
1960 
1961     case NFC_DATA_CEVT:
1962         p_r_apdu = (BT_HDR *) p_data->data.p_data;
1963         break;
1964 
1965     default:
1966         return;
1967     }
1968 
1969 #if (BT_TRACE_PROTOCOL == TRUE)
1970     if (p_t4t->state != RW_T4T_STATE_IDLE)
1971         DispRWT4Tags (p_r_apdu, TRUE);
1972 #endif
1973 
1974 #if (BT_TRACE_VERBOSE == TRUE)
1975     RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>",
1976                         rw_t4t_get_state_name (p_t4t->state), p_t4t->state);
1977 #else
1978     RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state);
1979 #endif
1980 
1981     switch (p_t4t->state)
1982     {
1983     case RW_T4T_STATE_IDLE:
1984         /* Unexpected R-APDU, it should be raw frame response */
1985         /* forward to upper layer without parsing */
1986 #if (BT_TRACE_VERBOSE == TRUE)
1987         RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len, NFC_GetStatusName (p_data->data.status));
1988 #else
1989         RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [0x%X]", p_r_apdu->len, p_data->data.status);
1990 #endif
1991         if (rw_cb.p_cback)
1992         {
1993             rw_data.raw_frame.status = p_data->data.status;
1994             rw_data.raw_frame.p_data = p_r_apdu;
1995             (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data);
1996             p_r_apdu = NULL;
1997         }
1998         else
1999         {
2000             GKI_freebuf (p_r_apdu);
2001         }
2002         break;
2003     case RW_T4T_STATE_DETECT_NDEF:
2004         rw_t4t_sm_detect_ndef (p_r_apdu);
2005         GKI_freebuf (p_r_apdu);
2006         break;
2007     case RW_T4T_STATE_READ_NDEF:
2008         rw_t4t_sm_read_ndef (p_r_apdu);
2009         /* p_r_apdu may send upper lyaer */
2010         break;
2011     case RW_T4T_STATE_UPDATE_NDEF:
2012         rw_t4t_sm_update_ndef (p_r_apdu);
2013         GKI_freebuf (p_r_apdu);
2014         break;
2015     case RW_T4T_STATE_PRESENCE_CHECK:
2016         /* if any response, send presence check with ok */
2017         rw_data.status = NFC_STATUS_OK;
2018         p_t4t->state = RW_T4T_STATE_IDLE;
2019         (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
2020         GKI_freebuf (p_r_apdu);
2021         break;
2022     case RW_T4T_STATE_SET_READ_ONLY:
2023         rw_t4t_sm_set_readonly (p_r_apdu);
2024         GKI_freebuf (p_r_apdu);
2025         break;
2026     case RW_T4T_STATE_NDEF_FORMAT:
2027         rw_t4t_sm_ndef_format (p_r_apdu);
2028         GKI_freebuf (p_r_apdu);
2029         break;
2030     default:
2031         RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
2032         GKI_freebuf (p_r_apdu);
2033         break;
2034     }
2035 
2036 #if (BT_TRACE_VERBOSE == TRUE)
2037     if (begin_state != p_t4t->state)
2038     {
2039         RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>",
2040                           rw_t4t_get_state_name (begin_state),
2041                           rw_t4t_get_state_name (p_t4t->state));
2042     }
2043 #endif
2044 }
2045 
2046 /*******************************************************************************
2047 **
2048 ** Function         RW_T4tFormatNDef
2049 **
2050 ** Description      format T4T tag
2051 **
2052 ** Returns          NFC_STATUS_OK if success
2053 **
2054 *******************************************************************************/
RW_T4tFormatNDef(void)2055 tNFC_STATUS RW_T4tFormatNDef (void)
2056 {
2057     RW_TRACE_API0 ("RW_T4tFormatNDef ()");
2058 
2059     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2060     {
2061         RW_TRACE_ERROR1 ("RW_T4tFormatNDef ():Unable to start command at state (0x%X)",
2062                           rw_cb.tcb.t4t.state);
2063         return NFC_STATUS_FAILED;
2064     }
2065 
2066     rw_cb.tcb.t4t.card_type = 0x00;
2067 
2068     if (!rw_t4t_get_hw_version ())
2069     {
2070         return NFC_STATUS_FAILED;
2071     }
2072 
2073     rw_cb.tcb.t4t.state = RW_T4T_STATE_NDEF_FORMAT;
2074     rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION;
2075 
2076     return NFC_STATUS_OK;
2077 }
2078 
2079 /*******************************************************************************
2080 **
2081 ** Function         rw_t4t_select
2082 **
2083 ** Description      Initialise T4T
2084 **
2085 ** Returns          NFC_STATUS_OK if success
2086 **
2087 *******************************************************************************/
rw_t4t_select(void)2088 tNFC_STATUS rw_t4t_select (void)
2089 {
2090     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
2091 
2092     RW_TRACE_DEBUG0 ("rw_t4t_select ()");
2093 
2094     NFC_SetStaticRfCback (rw_t4t_data_cback);
2095 
2096     p_t4t->state   = RW_T4T_STATE_IDLE;
2097     p_t4t->version = T4T_MY_VERSION;
2098 
2099     /* set it min of max R-APDU data size before reading CC file */
2100     p_t4t->cc_file.max_le = T4T_MIN_MLE;
2101 
2102     /* These will be udated during NDEF detection */
2103     p_t4t->max_read_size   = T4T_MAX_LENGTH_LE;
2104     p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
2105 
2106     return NFC_STATUS_OK;
2107 }
2108 
2109 /*******************************************************************************
2110 **
2111 ** Function         RW_T4tDetectNDef
2112 **
2113 ** Description      This function performs NDEF detection procedure
2114 **
2115 **                  RW_T4T_NDEF_DETECT_EVT will be returned
2116 **
2117 ** Returns          NFC_STATUS_OK if success
2118 **                  NFC_STATUS_FAILED if T4T is busy or other error
2119 **
2120 *******************************************************************************/
RW_T4tDetectNDef(void)2121 tNFC_STATUS RW_T4tDetectNDef (void)
2122 {
2123     RW_TRACE_API0 ("RW_T4tDetectNDef ()");
2124 
2125     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2126     {
2127         RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)",
2128                           rw_cb.tcb.t4t.state);
2129         return NFC_STATUS_FAILED;
2130     }
2131 
2132     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
2133     {
2134         /* NDEF Tag application has been selected then select CC file */
2135         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
2136         {
2137             return NFC_STATUS_FAILED;
2138         }
2139         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
2140     }
2141     else
2142     {
2143         /* Select NDEF Tag Application */
2144         if (!rw_t4t_select_application (rw_cb.tcb.t4t.version))
2145         {
2146             return NFC_STATUS_FAILED;
2147         }
2148         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
2149     }
2150 
2151     rw_cb.tcb.t4t.state     = RW_T4T_STATE_DETECT_NDEF;
2152 
2153     return NFC_STATUS_OK;
2154 }
2155 
2156 /*******************************************************************************
2157 **
2158 ** Function         RW_T4tReadNDef
2159 **
2160 ** Description      This function performs NDEF read procedure
2161 **                  Note: RW_T4tDetectNDef () must be called before using this
2162 **
2163 **                  The following event will be returned
2164 **                      RW_T4T_NDEF_READ_EVT for each segmented NDEF message
2165 **                      RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF
2166 **                      RW_T4T_NDEF_READ_FAIL_EVT for failure
2167 **
2168 ** Returns          NFC_STATUS_OK if success
2169 **                  NFC_STATUS_FAILED if T4T is busy or other error
2170 **
2171 *******************************************************************************/
RW_T4tReadNDef(void)2172 tNFC_STATUS RW_T4tReadNDef (void)
2173 {
2174     RW_TRACE_API0 ("RW_T4tReadNDef ()");
2175 
2176     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2177     {
2178         RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)",
2179                           rw_cb.tcb.t4t.state);
2180         return NFC_STATUS_FAILED;
2181     }
2182 
2183     /* if NDEF has been detected */
2184     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
2185     {
2186         /* start reading NDEF */
2187         if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE))
2188         {
2189             return NFC_STATUS_FAILED;
2190         }
2191 
2192         rw_cb.tcb.t4t.state     = RW_T4T_STATE_READ_NDEF;
2193         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
2194 
2195         return NFC_STATUS_OK;
2196     }
2197     else
2198     {
2199         RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected");
2200         return NFC_STATUS_FAILED;
2201     }
2202 }
2203 
2204 /*******************************************************************************
2205 **
2206 ** Function         RW_T4tUpdateNDef
2207 **
2208 ** Description      This function performs NDEF update procedure
2209 **                  Note: RW_T4tDetectNDef () must be called before using this
2210 **                        Updating data must not be removed until returning event
2211 **
2212 **                  The following event will be returned
2213 **                      RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
2214 **                      RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
2215 **
2216 ** Returns          NFC_STATUS_OK if success
2217 **                  NFC_STATUS_FAILED if T4T is busy or other error
2218 **
2219 *******************************************************************************/
RW_T4tUpdateNDef(UINT16 length,UINT8 * p_data)2220 tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data)
2221 {
2222     RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length);
2223 
2224     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2225     {
2226         RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)",
2227                           rw_cb.tcb.t4t.state);
2228         return NFC_STATUS_FAILED;
2229     }
2230 
2231     /* if NDEF has been detected */
2232     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
2233     {
2234         /* if read-only */
2235         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
2236         {
2237             RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only");
2238             return NFC_STATUS_FAILED;
2239         }
2240 
2241         if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE)
2242         {
2243             RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)",
2244                               length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
2245             return NFC_STATUS_FAILED;
2246         }
2247 
2248         /* store NDEF length and data */
2249         rw_cb.tcb.t4t.ndef_length   = length;
2250         rw_cb.tcb.t4t.p_update_data = p_data;
2251 
2252         rw_cb.tcb.t4t.rw_offset     = T4T_FILE_LENGTH_SIZE;
2253         rw_cb.tcb.t4t.rw_length     = length;
2254 
2255         /* set NLEN to 0x0000 for the first step */
2256         if (!rw_t4t_update_nlen (0x0000))
2257         {
2258             return NFC_STATUS_FAILED;
2259         }
2260 
2261         rw_cb.tcb.t4t.state     = RW_T4T_STATE_UPDATE_NDEF;
2262         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
2263 
2264         return NFC_STATUS_OK;
2265     }
2266     else
2267     {
2268         RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected");
2269         return NFC_STATUS_FAILED;
2270     }
2271 }
2272 
2273 /*****************************************************************************
2274 **
2275 ** Function         RW_T4tPresenceCheck
2276 **
2277 ** Description
2278 **      Check if the tag is still in the field.
2279 **
2280 **      The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
2281 **      or non-presence.
2282 **      option is RW_T4T_CHK_EMPTY_I_BLOCK, use empty I block for presence check.
2283 **
2284 ** Returns
2285 **      NFC_STATUS_OK, if raw data frame sent
2286 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2287 **      NFC_STATUS_FAILED: other error
2288 **
2289 *****************************************************************************/
RW_T4tPresenceCheck(UINT8 option)2290 tNFC_STATUS RW_T4tPresenceCheck (UINT8 option)
2291 {
2292     tNFC_STATUS retval = NFC_STATUS_OK;
2293     tRW_DATA    evt_data;
2294     BOOLEAN     status;
2295     BT_HDR      *p_data;
2296 
2297     RW_TRACE_API1 ("RW_T4tPresenceCheck () %d", option);
2298 
2299     /* If RW_SelectTagType was not called (no conn_callback) return failure */
2300     if (!rw_cb.p_cback)
2301     {
2302         retval = NFC_STATUS_FAILED;
2303     }
2304     /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */
2305     else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED)
2306     {
2307         evt_data.status = NFC_STATUS_FAILED;
2308         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2309     }
2310     /* If command is pending, assume tag is still present */
2311     else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2312     {
2313         evt_data.status = NFC_STATUS_OK;
2314         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2315     }
2316     else
2317     {
2318         status = FALSE;
2319         if (option == RW_T4T_CHK_EMPTY_I_BLOCK)
2320         {
2321             /* use empty I block for presence check */
2322             if ((p_data = (BT_HDR *) GKI_getbuf (NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE)) != NULL)
2323             {
2324                 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
2325                 p_data->len    = 0;
2326                 if (NFC_SendData (NFC_RF_CONN_ID, (BT_HDR*) p_data) == NFC_STATUS_OK)
2327                     status = TRUE;
2328             }
2329         }
2330         else
2331         {
2332             /* use read binary on the given channel */
2333             rw_cb.tcb.t4t.channel = 0;
2334             if (option <= RW_T4T_CHK_READ_BINARY_CH3)
2335                 rw_cb.tcb.t4t.channel = option;
2336             status = rw_t4t_read_file (0, 1, FALSE);
2337             rw_cb.tcb.t4t.channel = 0;
2338         }
2339 
2340         if (status == TRUE)
2341         {
2342             rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
2343         }
2344         else
2345         {
2346             retval = NFC_STATUS_NO_BUFFERS;
2347         }
2348     }
2349 
2350     return (retval);
2351 }
2352 
2353 /*****************************************************************************
2354 **
2355 ** Function         RW_T4tSetNDefReadOnly
2356 **
2357 ** Description      This function performs NDEF read-only procedure
2358 **                  Note: RW_T4tDetectNDef() must be called before using this
2359 **
2360 **                  The RW_T4T_SET_TO_RO_EVT event will be returned.
2361 **
2362 ** Returns          NFC_STATUS_OK if success
2363 **                  NFC_STATUS_FAILED if T4T is busy or other error
2364 **
2365 *****************************************************************************/
RW_T4tSetNDefReadOnly(void)2366 tNFC_STATUS RW_T4tSetNDefReadOnly (void)
2367 {
2368     tNFC_STATUS retval = NFC_STATUS_OK;
2369     tRW_DATA    evt_data;
2370 
2371     RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()");
2372 
2373     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
2374     {
2375         RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)",
2376                           rw_cb.tcb.t4t.state);
2377         return NFC_STATUS_FAILED;
2378     }
2379 
2380     /* if NDEF has been detected */
2381     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
2382     {
2383         /* if read-only */
2384         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
2385         {
2386             RW_TRACE_API0 ("RW_T4tSetNDefReadOnly (): NDEF is already read-only");
2387 
2388             evt_data.status = NFC_STATUS_OK;
2389             (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data);
2390             return (retval);
2391         }
2392 
2393         /* NDEF Tag application has been selected then select CC file */
2394         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
2395         {
2396             return NFC_STATUS_FAILED;
2397         }
2398 
2399         rw_cb.tcb.t4t.state     = RW_T4T_STATE_SET_READ_ONLY;
2400         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
2401 
2402         return NFC_STATUS_OK;
2403     }
2404     else
2405     {
2406         RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected");
2407         return NFC_STATUS_FAILED;
2408     }
2409     return (retval);
2410 }
2411 
2412 #if (BT_TRACE_VERBOSE == TRUE)
2413 /*******************************************************************************
2414 **
2415 ** Function         rw_t4t_get_state_name
2416 **
2417 ** Description      This function returns the state name.
2418 **
2419 ** NOTE             conditionally compiled to save memory.
2420 **
2421 ** Returns          pointer to the name
2422 **
2423 *******************************************************************************/
rw_t4t_get_state_name(UINT8 state)2424 static char *rw_t4t_get_state_name (UINT8 state)
2425 {
2426     switch (state)
2427     {
2428     case RW_T4T_STATE_NOT_ACTIVATED:
2429         return ("NOT_ACTIVATED");
2430     case RW_T4T_STATE_IDLE:
2431         return ("IDLE");
2432     case RW_T4T_STATE_DETECT_NDEF:
2433         return ("NDEF_DETECTION");
2434     case RW_T4T_STATE_READ_NDEF:
2435         return ("READ_NDEF");
2436     case RW_T4T_STATE_UPDATE_NDEF:
2437         return ("UPDATE_NDEF");
2438     case RW_T4T_STATE_PRESENCE_CHECK:
2439         return ("PRESENCE_CHECK");
2440     case RW_T4T_STATE_SET_READ_ONLY:
2441         return ("SET_READ_ONLY");
2442 
2443     default:
2444         return ("???? UNKNOWN STATE");
2445     }
2446 }
2447 
2448 /*******************************************************************************
2449 **
2450 ** Function         rw_t4t_get_sub_state_name
2451 **
2452 ** Description      This function returns the sub_state name.
2453 **
2454 ** NOTE             conditionally compiled to save memory.
2455 **
2456 ** Returns          pointer to the name
2457 **
2458 *******************************************************************************/
rw_t4t_get_sub_state_name(UINT8 sub_state)2459 static char *rw_t4t_get_sub_state_name (UINT8 sub_state)
2460 {
2461     switch (sub_state)
2462     {
2463     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
2464         return ("WAIT_SELECT_APP");
2465     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
2466         return ("WAIT_SELECT_CC");
2467     case RW_T4T_SUBSTATE_WAIT_CC_FILE:
2468         return ("WAIT_CC_FILE");
2469     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
2470         return ("WAIT_SELECT_NDEF_FILE");
2471     case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
2472         return ("WAIT_READ_NLEN");
2473 
2474     case RW_T4T_SUBSTATE_WAIT_READ_RESP:
2475         return ("WAIT_READ_RESP");
2476     case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
2477         return ("WAIT_UPDATE_RESP");
2478     case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
2479         return ("WAIT_UPDATE_NLEN");
2480     case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
2481         return ("WAIT_GET_HW_VERSION");
2482     case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION :
2483         return ("WAIT_GET_SW_VERSION");
2484     case RW_T4T_SUBSTATE_WAIT_GET_UID:
2485         return ("WAIT_GET_UID");
2486     case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
2487         return ("WAIT_CREATE_APP");
2488     case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
2489         return ("WAIT_CREATE_CC");
2490     case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
2491         return ("WAIT_CREATE_NDEF");
2492     case RW_T4T_SUBSTATE_WAIT_WRITE_CC :
2493         return ("WAIT_WRITE_CC");
2494     case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
2495         return ("WAIT_WRITE_NDEF");
2496     default:
2497         return ("???? UNKNOWN SUBSTATE");
2498     }
2499 }
2500 #endif
2501 
2502 #endif /* (NFC_INCLUDED == TRUE) */
2503