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