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