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