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