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