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