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