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