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