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