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