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 #include "bt_types.h"
27 #include "nfc_target.h"
28 #include "trace_api.h"
29
30 #include "gki.h"
31 #include "nfc_api.h"
32 #include "nfc_int.h"
33 #include "rw_api.h"
34 #include "rw_int.h"
35 #include "tags_int.h"
36
37 /* main state */
38 /* T4T is not activated */
39 #define RW_T4T_STATE_NOT_ACTIVATED 0x00
40 /* waiting for upper layer API */
41 #define RW_T4T_STATE_IDLE 0x01
42 /* performing NDEF detection precedure */
43 #define RW_T4T_STATE_DETECT_NDEF 0x02
44 /* performing read NDEF procedure */
45 #define RW_T4T_STATE_READ_NDEF 0x03
46 /* performing update NDEF procedure */
47 #define RW_T4T_STATE_UPDATE_NDEF 0x04
48 /* checking presence of tag */
49 #define RW_T4T_STATE_PRESENCE_CHECK 0x05
50 /* convert tag to read only */
51 #define RW_T4T_STATE_SET_READ_ONLY 0x06
52
53 /* performing NDEF format */
54 #define RW_T4T_STATE_NDEF_FORMAT 0x07
55
56 /* sub state */
57 /* waiting for response of selecting AID */
58 #define RW_T4T_SUBSTATE_WAIT_SELECT_APP 0x00
59 /* waiting for response of selecting CC */
60 #define RW_T4T_SUBSTATE_WAIT_SELECT_CC 0x01
61 /* waiting for response of reading CC */
62 #define RW_T4T_SUBSTATE_WAIT_CC_FILE 0x02
63 /* waiting for response of selecting NDEF */
64 #define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE 0x03
65 /* waiting for response of reading NLEN */
66 #define RW_T4T_SUBSTATE_WAIT_READ_NLEN 0x04
67 /* waiting for response of reading file */
68 #define RW_T4T_SUBSTATE_WAIT_READ_RESP 0x05
69 /* waiting for response of updating file */
70 #define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP 0x06
71 /* waiting for response of updating NLEN */
72 #define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07
73 /* waiting for response of updating CC */
74 #define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08
75
76 #define RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION 0x09
77 #define RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION 0x0A
78 #define RW_T4T_SUBSTATE_WAIT_GET_UID 0x0B
79 #define RW_T4T_SUBSTATE_WAIT_CREATE_APP 0x0C
80 #define RW_T4T_SUBSTATE_WAIT_CREATE_CC 0x0D
81 #define RW_T4T_SUBSTATE_WAIT_CREATE_NDEF 0x0E
82 #define RW_T4T_SUBSTATE_WAIT_WRITE_CC 0x0F
83 #define RW_T4T_SUBSTATE_WAIT_WRITE_NDEF 0x10
84
85 #if (BT_TRACE_VERBOSE == TRUE)
86 static char* rw_t4t_get_state_name(uint8_t state);
87 static char* rw_t4t_get_sub_state_name(uint8_t sub_state);
88 #endif
89
90 static bool rw_t4t_send_to_lower(NFC_HDR* p_c_apdu);
91 static bool rw_t4t_select_file(uint16_t file_id);
92 static bool rw_t4t_read_file(uint16_t offset, uint16_t length,
93 bool is_continue);
94 static bool rw_t4t_update_nlen(uint16_t ndef_len);
95 static bool rw_t4t_update_file(void);
96 static bool rw_t4t_update_cc_to_readonly(void);
97 static bool rw_t4t_select_application(uint8_t version);
98 static bool rw_t4t_validate_cc_file(void);
99
100 static bool rw_t4t_get_hw_version(void);
101 static bool rw_t4t_get_sw_version(void);
102 static bool rw_t4t_create_app(void);
103 static bool rw_t4t_select_app(void);
104 static bool rw_t4t_create_ccfile(void);
105 static bool rw_t4t_create_ndef(void);
106 static bool rw_t4t_write_cc(void);
107 static bool rw_t4t_write_ndef(void);
108 static void rw_t4t_handle_error(tNFC_STATUS status, uint8_t sw1, uint8_t sw2);
109 static void rw_t4t_sm_detect_ndef(NFC_HDR* p_r_apdu);
110 static void rw_t4t_sm_read_ndef(NFC_HDR* p_r_apdu);
111 static void rw_t4t_sm_update_ndef(NFC_HDR* p_r_apdu);
112 static void rw_t4t_sm_set_readonly(NFC_HDR* p_r_apdu);
113 static void rw_t4t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
114 tNFC_CONN* p_data);
115 static void rw_t4t_sm_ndef_format(NFC_HDR* p_r_apdu);
116
117 /*******************************************************************************
118 **
119 ** Function rw_t4t_send_to_lower
120 **
121 ** Description Send C-APDU to lower layer
122 **
123 ** Returns TRUE if success
124 **
125 *******************************************************************************/
rw_t4t_send_to_lower(NFC_HDR * p_c_apdu)126 static bool rw_t4t_send_to_lower(NFC_HDR* p_c_apdu) {
127 #if (BT_TRACE_PROTOCOL == TRUE)
128 DispRWT4Tags(p_c_apdu, false);
129 #endif
130
131 if (NFC_SendData(NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK) {
132 RW_TRACE_ERROR0("rw_t4t_send_to_lower (): NFC_SendData () 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 RW_TRACE_ERROR0("rw_t4t_get_hw_version (): 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 RW_TRACE_ERROR0("rw_t4t_get_sw_version (): 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 RW_TRACE_ERROR0("rw_t4t_get_uid_details (): 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 RW_TRACE_ERROR0("rw_t4t_create_app (): 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 RW_TRACE_ERROR0("rw_t4t_select_app (): 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 RW_TRACE_ERROR0("rw_t4t_create_ccfile (): 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 RW_TRACE_ERROR0("rw_t4t_create_ndef (): 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 RW_TRACE_ERROR0("rw_t4t_write_cc (): 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 RW_TRACE_ERROR0("rw_t4t_write_ndef (): 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 RW_TRACE_DEBUG1("rw_t4t_select_file (): 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 RW_TRACE_ERROR0("rw_t4t_select_file (): 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 RW_TRACE_DEBUG3("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ",
659 offset, length, is_continue);
660
661 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
662
663 if (!p_c_apdu) {
664 RW_TRACE_ERROR0("rw_t4t_read_file (): 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 RW_TRACE_DEBUG1("rw_t4t_update_nlen () NLEN:%d", ndef_len);
713
714 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
715
716 if (!p_c_apdu) {
717 RW_TRACE_ERROR0("rw_t4t_update_nlen (): 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 RW_TRACE_DEBUG2("rw_t4t_update_file () rw_offset:%d, rw_length:%d",
755 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 RW_TRACE_ERROR0("rw_t4t_write_file (): 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 RW_TRACE_DEBUG0(
811 "rw_t4t_update_cc_to_readonly (): 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 RW_TRACE_ERROR0("rw_t4t_update_cc_to_readonly (): 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 RW_TRACE_DEBUG1("rw_t4t_select_application () version:0x%X", version);
865
866 p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
867
868 if (!p_c_apdu) {
869 RW_TRACE_ERROR0("rw_t4t_select_application (): 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 RW_TRACE_DEBUG0("rw_t4t_validate_cc_file ()");
922
923 if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN) {
924 RW_TRACE_ERROR1("rw_t4t_validate_cc_file (): CCLEN (%d) is too short",
925 p_t4t->cc_file.cclen);
926 return false;
927 }
928
929 if (T4T_GET_MAJOR_VERSION(p_t4t->cc_file.version) !=
930 T4T_GET_MAJOR_VERSION(p_t4t->version)) {
931 RW_TRACE_ERROR2(
932 "rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours "
933 "(0x%02X)",
934 p_t4t->cc_file.version, p_t4t->version);
935 return false;
936 }
937
938 if (p_t4t->cc_file.max_le < 0x000F) {
939 RW_TRACE_ERROR1("rw_t4t_validate_cc_file (): MaxLe (%d) is too small",
940 p_t4t->cc_file.max_le);
941 return false;
942 }
943
944 if (p_t4t->cc_file.max_lc < 0x0001) {
945 RW_TRACE_ERROR1("rw_t4t_validate_cc_file (): MaxLc (%d) is too small",
946 p_t4t->cc_file.max_lc);
947 return false;
948 }
949
950 if ((p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID) ||
951 (p_t4t->cc_file.ndef_fc.file_id == 0xE102) ||
952 (p_t4t->cc_file.ndef_fc.file_id == 0xE103) ||
953 ((p_t4t->cc_file.ndef_fc.file_id == 0x0000) &&
954 (p_t4t->cc_file.version == 0x20)) ||
955 (p_t4t->cc_file.ndef_fc.file_id == 0x3F00) ||
956 (p_t4t->cc_file.ndef_fc.file_id == 0x3FFF) ||
957 (p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)) {
958 RW_TRACE_ERROR1("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid",
959 p_t4t->cc_file.ndef_fc.file_id);
960 return false;
961 }
962
963 if ((p_t4t->cc_file.ndef_fc.max_file_size < 0x0005) ||
964 (p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)) {
965 RW_TRACE_ERROR1(
966 "rw_t4t_validate_cc_file (): max_file_size (%d) is reserved",
967 p_t4t->cc_file.ndef_fc.max_file_size);
968 return false;
969 }
970
971 if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS) {
972 RW_TRACE_ERROR1(
973 "rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid",
974 p_t4t->cc_file.ndef_fc.read_access);
975 return false;
976 }
977
978 if ((p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) &&
979 (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS)) {
980 RW_TRACE_ERROR1(
981 "rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid",
982 p_t4t->cc_file.ndef_fc.write_access);
983 return false;
984 }
985
986 return true;
987 }
988
989 /*******************************************************************************
990 **
991 ** Function rw_t4t_handle_error
992 **
993 ** Description notify error to application and clean up
994 **
995 ** Returns none
996 **
997 *******************************************************************************/
rw_t4t_handle_error(tNFC_STATUS status,uint8_t sw1,uint8_t sw2)998 static void rw_t4t_handle_error(tNFC_STATUS status, uint8_t sw1, uint8_t sw2) {
999 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1000 tRW_DATA rw_data;
1001 tRW_EVENT event;
1002
1003 RW_TRACE_DEBUG4(
1004 "rw_t4t_handle_error (): status:0x%02X, sw1:0x%02X, sw2:0x%02X, "
1005 "state:0x%X",
1006 status, sw1, sw2, p_t4t->state);
1007
1008 nfc_stop_quick_timer(&p_t4t->timer);
1009
1010 if (rw_cb.p_cback) {
1011 rw_data.status = status;
1012
1013 rw_data.t4t_sw.sw1 = sw1;
1014 rw_data.t4t_sw.sw2 = sw2;
1015
1016 switch (p_t4t->state) {
1017 case RW_T4T_STATE_DETECT_NDEF:
1018 rw_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
1019 event = RW_T4T_NDEF_DETECT_EVT;
1020 break;
1021
1022 case RW_T4T_STATE_READ_NDEF:
1023 event = RW_T4T_NDEF_READ_FAIL_EVT;
1024 break;
1025
1026 case RW_T4T_STATE_UPDATE_NDEF:
1027 event = RW_T4T_NDEF_UPDATE_FAIL_EVT;
1028 break;
1029
1030 case RW_T4T_STATE_PRESENCE_CHECK:
1031 event = RW_T4T_PRESENCE_CHECK_EVT;
1032 rw_data.status = NFC_STATUS_FAILED;
1033 break;
1034
1035 case RW_T4T_STATE_SET_READ_ONLY:
1036 event = RW_T4T_SET_TO_RO_EVT;
1037 break;
1038
1039 case RW_T4T_STATE_NDEF_FORMAT:
1040 event = RW_T4T_NDEF_FORMAT_CPLT_EVT;
1041 rw_data.status = NFC_STATUS_FAILED;
1042 break;
1043
1044 default:
1045 event = RW_T4T_MAX_EVT;
1046 break;
1047 }
1048
1049 p_t4t->state = RW_T4T_STATE_IDLE;
1050
1051 if (event != RW_T4T_MAX_EVT) {
1052 (*(rw_cb.p_cback))(event, &rw_data);
1053 }
1054 } else {
1055 p_t4t->state = RW_T4T_STATE_IDLE;
1056 }
1057 }
1058
1059 /*******************************************************************************
1060 **
1061 ** Function rw_t4t_sm_ndef_format
1062 **
1063 ** Description State machine for NDEF format procedure
1064 **
1065 ** Returns none
1066 **
1067 *******************************************************************************/
rw_t4t_sm_ndef_format(NFC_HDR * p_r_apdu)1068 static void rw_t4t_sm_ndef_format(NFC_HDR* p_r_apdu) {
1069 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1070 uint8_t *p, type, length;
1071 uint16_t status_words, nlen;
1072 tRW_DATA rw_data;
1073
1074 #if (BT_TRACE_VERBOSE == TRUE)
1075 RW_TRACE_DEBUG2("rw_t4t_sm_ndef_format (): sub_state:%s (%d)",
1076 rw_t4t_get_sub_state_name(p_t4t->sub_state),
1077 p_t4t->sub_state);
1078 #else
1079 RW_TRACE_DEBUG1("rw_t4t_sm_ndef_format (): sub_state=%d", p_t4t->sub_state);
1080 #endif
1081
1082 /* get status words */
1083 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1084
1085 switch (p_t4t->sub_state) {
1086 case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
1087 p += (p_r_apdu->len - 1);
1088 if (*(p) == T4T_ADDI_FRAME_RESP) {
1089 if (!rw_t4t_get_sw_version()) {
1090 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1091 } else {
1092 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION;
1093 }
1094 } else {
1095 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1096 }
1097 break;
1098
1099 case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
1100 p += (p_r_apdu->len - 1);
1101 if (*(p) == T4T_ADDI_FRAME_RESP) {
1102 if (!rw_t4t_update_version_details(p_r_apdu)) {
1103 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1104 }
1105
1106 if (!rw_t4t_get_uid_details()) {
1107 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1108 }
1109
1110 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_GET_UID;
1111 } else {
1112 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1113 }
1114 break;
1115
1116 case RW_T4T_SUBSTATE_WAIT_GET_UID:
1117 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1118 BE_STREAM_TO_UINT16(status_words, p);
1119 if (status_words != 0x9100) {
1120 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1121 } else {
1122 if (!rw_t4t_create_app()) {
1123 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1124 } else {
1125 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_APP;
1126 }
1127 }
1128 break;
1129
1130 case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
1131 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1132 BE_STREAM_TO_UINT16(status_words, p);
1133 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1134 {
1135 status_words = 0x9100;
1136 }
1137
1138 if (status_words != 0x9100) {
1139 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1140 } else {
1141 if (!rw_t4t_select_app()) {
1142 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1143 } else {
1144 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1145 }
1146 }
1147 break;
1148
1149 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1150 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1151 BE_STREAM_TO_UINT16(status_words, p);
1152 if (status_words != 0x9100) {
1153 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1154 } else {
1155 if (!rw_t4t_create_ccfile()) {
1156 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1157 } else {
1158 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_CC;
1159 }
1160 }
1161 break;
1162
1163 case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
1164 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1165 BE_STREAM_TO_UINT16(status_words, p);
1166 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1167 {
1168 status_words = 0x9100;
1169 }
1170
1171 if (status_words != 0x9100) {
1172 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1173 } else {
1174 if (!rw_t4t_create_ndef()) {
1175 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1176 } else {
1177 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CREATE_NDEF;
1178 }
1179 }
1180 break;
1181
1182 case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
1183 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1184 BE_STREAM_TO_UINT16(status_words, p);
1185 if (status_words == 0x91DE) /* DUPLICATE_ERROR, file already exist*/
1186 {
1187 status_words = 0x9100;
1188 }
1189
1190 if (status_words != 0x9100) {
1191 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1192 } else {
1193 if (!rw_t4t_write_cc()) {
1194 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1195 } else {
1196 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_CC;
1197 }
1198 }
1199 break;
1200
1201 case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
1202 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1203 BE_STREAM_TO_UINT16(status_words, p);
1204 if (status_words != 0x9100) {
1205 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1206 } else {
1207 if (!rw_t4t_write_ndef()) {
1208 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1209 } else {
1210 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_WRITE_NDEF;
1211 }
1212 }
1213 break;
1214
1215 case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
1216 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1217 BE_STREAM_TO_UINT16(status_words, p);
1218 if (status_words != 0x9100) {
1219 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1220 } else {
1221 p_t4t->state = RW_T4T_STATE_IDLE;
1222 if (rw_cb.p_cback) {
1223 rw_data.ndef.status = NFC_STATUS_OK;
1224 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1225 rw_data.ndef.max_size = p_t4t->card_size;
1226 rw_data.ndef.cur_size = 0x00;
1227
1228 (*(rw_cb.p_cback))(RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
1229
1230 RW_TRACE_DEBUG0(
1231 "rw_t4t_ndef_format (): Sent RW_T4T_NDEF_FORMAT_CPLT_EVT");
1232 }
1233 }
1234 break;
1235
1236 default:
1237 RW_TRACE_ERROR1("rw_t4t_sm_ndef_format (): unknown sub_state=%d",
1238 p_t4t->sub_state);
1239 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1240 break;
1241 }
1242 }
1243
1244 /*******************************************************************************
1245 **
1246 ** Function rw_t4t_sm_detect_ndef
1247 **
1248 ** Description State machine for NDEF detection procedure
1249 **
1250 ** Returns none
1251 **
1252 *******************************************************************************/
rw_t4t_sm_detect_ndef(NFC_HDR * p_r_apdu)1253 static void rw_t4t_sm_detect_ndef(NFC_HDR* p_r_apdu) {
1254 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1255 uint8_t *p, type, length;
1256 uint16_t status_words, nlen;
1257 tRW_DATA rw_data;
1258
1259 #if (BT_TRACE_VERBOSE == TRUE)
1260 RW_TRACE_DEBUG2("rw_t4t_sm_detect_ndef (): sub_state:%s (%d)",
1261 rw_t4t_get_sub_state_name(p_t4t->sub_state),
1262 p_t4t->sub_state);
1263 #else
1264 RW_TRACE_DEBUG1("rw_t4t_sm_detect_ndef (): sub_state=%d", p_t4t->sub_state);
1265 #endif
1266
1267 /* get status words */
1268 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1269 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1270 BE_STREAM_TO_UINT16(status_words, p);
1271
1272 if (status_words != T4T_RSP_CMD_CMPLTED) {
1273 /* try V1.0 after failing of V2.0 */
1274 if ((p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP) &&
1275 (p_t4t->version == T4T_VERSION_2_0)) {
1276 p_t4t->version = T4T_VERSION_1_0;
1277
1278 RW_TRACE_DEBUG1("rw_t4t_sm_detect_ndef (): retry with version=0x%02X",
1279 p_t4t->version);
1280
1281 if (!rw_t4t_select_application(T4T_VERSION_1_0)) {
1282 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1283 }
1284 return;
1285 }
1286
1287 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1288 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1289 return;
1290 }
1291
1292 switch (p_t4t->sub_state) {
1293 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1294
1295 /* NDEF Tag application has been selected then select CC file */
1296 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
1297 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1298 } else {
1299 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1300 }
1301 break;
1302
1303 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1304
1305 /* CC file has been selected then read mandatory part of CC file */
1306 if (!rw_t4t_read_file(0x00, T4T_CC_FILE_MIN_LEN, false)) {
1307 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1308 } else {
1309 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
1310 }
1311 break;
1312
1313 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1314
1315 /* CC file has been read then validate and select mandatory NDEF file */
1316 if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE) {
1317 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1318
1319 BE_STREAM_TO_UINT16(p_t4t->cc_file.cclen, p);
1320 BE_STREAM_TO_UINT8(p_t4t->cc_file.version, p);
1321 BE_STREAM_TO_UINT16(p_t4t->cc_file.max_le, p);
1322 BE_STREAM_TO_UINT16(p_t4t->cc_file.max_lc, p);
1323
1324 BE_STREAM_TO_UINT8(type, p);
1325 BE_STREAM_TO_UINT8(length, p);
1326
1327 if ((type == T4T_NDEF_FILE_CONTROL_TYPE) &&
1328 (length == T4T_FILE_CONTROL_LENGTH)) {
1329 BE_STREAM_TO_UINT16(p_t4t->cc_file.ndef_fc.file_id, p);
1330 BE_STREAM_TO_UINT16(p_t4t->cc_file.ndef_fc.max_file_size, p);
1331 BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.read_access, p);
1332 BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.write_access, p);
1333
1334 #if (BT_TRACE_VERBOSE == TRUE)
1335 RW_TRACE_DEBUG0("Capability Container (CC) file");
1336 RW_TRACE_DEBUG1(" CCLEN: 0x%04X", p_t4t->cc_file.cclen);
1337 RW_TRACE_DEBUG1(" Version:0x%02X", p_t4t->cc_file.version);
1338 RW_TRACE_DEBUG1(" MaxLe: 0x%04X", p_t4t->cc_file.max_le);
1339 RW_TRACE_DEBUG1(" MaxLc: 0x%04X", p_t4t->cc_file.max_lc);
1340 RW_TRACE_DEBUG0(" NDEF File Control TLV");
1341 RW_TRACE_DEBUG1(" FileID: 0x%04X",
1342 p_t4t->cc_file.ndef_fc.file_id);
1343 RW_TRACE_DEBUG1(" MaxFileSize: 0x%04X",
1344 p_t4t->cc_file.ndef_fc.max_file_size);
1345 RW_TRACE_DEBUG1(" ReadAccess: 0x%02X",
1346 p_t4t->cc_file.ndef_fc.read_access);
1347 RW_TRACE_DEBUG1(" WriteAccess: 0x%02X",
1348 p_t4t->cc_file.ndef_fc.write_access);
1349 #endif
1350
1351 if (rw_t4t_validate_cc_file()) {
1352 if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
1353 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1354 } else {
1355 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1356 }
1357 break;
1358 }
1359 }
1360 }
1361
1362 /* invalid response or CC file */
1363 p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
1364 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
1365 break;
1366
1367 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1368
1369 /* NDEF file has been selected then read the first 2 bytes (NLEN) */
1370 if (!rw_t4t_read_file(0, T4T_FILE_LENGTH_SIZE, false)) {
1371 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1372 } else {
1373 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
1374 }
1375 break;
1376
1377 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1378
1379 /* NLEN has been read then report upper layer */
1380 if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE) {
1381 /* get length of NDEF */
1382 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1383 BE_STREAM_TO_UINT16(nlen, p);
1384
1385 if (nlen <=
1386 p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE) {
1387 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
1388
1389 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
1390 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1391 }
1392
1393 /* Get max bytes to read per command */
1394 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ) {
1395 p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
1396 } else {
1397 p_t4t->max_read_size = p_t4t->cc_file.max_le;
1398 }
1399
1400 /* Le: valid range is 0x01 to 0xFF */
1401 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE) {
1402 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1403 }
1404
1405 /* Get max bytes to update per command */
1406 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE) {
1407 p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
1408 } else {
1409 p_t4t->max_update_size = p_t4t->cc_file.max_lc;
1410 }
1411
1412 /* Lc: valid range is 0x01 to 0xFF */
1413 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC) {
1414 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1415 }
1416
1417 p_t4t->ndef_length = nlen;
1418 p_t4t->state = RW_T4T_STATE_IDLE;
1419
1420 if (rw_cb.p_cback) {
1421 rw_data.ndef.status = NFC_STATUS_OK;
1422 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
1423 rw_data.ndef.max_size =
1424 (uint32_t)(p_t4t->cc_file.ndef_fc.max_file_size -
1425 (uint16_t)T4T_FILE_LENGTH_SIZE);
1426 rw_data.ndef.cur_size = nlen;
1427 rw_data.ndef.flags = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
1428 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
1429 rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
1430 }
1431
1432 (*(rw_cb.p_cback))(RW_T4T_NDEF_DETECT_EVT, &rw_data);
1433
1434 RW_TRACE_DEBUG0(
1435 "rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT");
1436 }
1437 } else {
1438 /* NLEN should be less than max file size */
1439 RW_TRACE_ERROR2(
1440 "rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file "
1441 "size (%d)",
1442 nlen, p_t4t->cc_file.ndef_fc.max_file_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 } else {
1448 /* response payload size should be T4T_FILE_LENGTH_SIZE */
1449 RW_TRACE_ERROR2(
1450 "rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d",
1451 p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_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 break;
1457
1458 default:
1459 RW_TRACE_ERROR1("rw_t4t_sm_detect_ndef (): unknown sub_state=%d",
1460 p_t4t->sub_state);
1461 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1462 break;
1463 }
1464 }
1465
1466 /*******************************************************************************
1467 **
1468 ** Function rw_t4t_sm_read_ndef
1469 **
1470 ** Description State machine for NDEF read procedure
1471 **
1472 ** Returns none
1473 **
1474 *******************************************************************************/
rw_t4t_sm_read_ndef(NFC_HDR * p_r_apdu)1475 static void rw_t4t_sm_read_ndef(NFC_HDR* p_r_apdu) {
1476 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1477 uint8_t* p;
1478 uint16_t status_words;
1479 tRW_DATA rw_data;
1480
1481 #if (BT_TRACE_VERBOSE == TRUE)
1482 RW_TRACE_DEBUG2("rw_t4t_sm_read_ndef (): sub_state:%s (%d)",
1483 rw_t4t_get_sub_state_name(p_t4t->sub_state),
1484 p_t4t->sub_state);
1485 #else
1486 RW_TRACE_DEBUG1("rw_t4t_sm_read_ndef (): sub_state=%d", p_t4t->sub_state);
1487 #endif
1488
1489 /* get status words */
1490 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1491 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1492 BE_STREAM_TO_UINT16(status_words, p);
1493
1494 if (status_words != T4T_RSP_CMD_CMPLTED) {
1495 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1496 GKI_freebuf(p_r_apdu);
1497 return;
1498 }
1499
1500 switch (p_t4t->sub_state) {
1501 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1502
1503 /* Read partial or complete data */
1504 p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
1505
1506 if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) {
1507 p_t4t->rw_length -= p_r_apdu->len;
1508 p_t4t->rw_offset += p_r_apdu->len;
1509
1510 if (rw_cb.p_cback) {
1511 rw_data.data.status = NFC_STATUS_OK;
1512 rw_data.data.p_data = p_r_apdu;
1513
1514 /* if need to read more data */
1515 if (p_t4t->rw_length > 0) {
1516 (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_EVT, &rw_data);
1517
1518 if (!rw_t4t_read_file(p_t4t->rw_offset, p_t4t->rw_length, true)) {
1519 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1520 }
1521 } else {
1522 p_t4t->state = RW_T4T_STATE_IDLE;
1523
1524 (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
1525
1526 RW_TRACE_DEBUG0(
1527 "rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT");
1528 }
1529
1530 p_r_apdu = NULL;
1531 } else {
1532 p_t4t->rw_length = 0;
1533 p_t4t->state = RW_T4T_STATE_IDLE;
1534 }
1535 } else {
1536 RW_TRACE_ERROR2(
1537 "rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length "
1538 "(%d)",
1539 p_r_apdu->len, p_t4t->rw_length);
1540 rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
1541 }
1542 break;
1543
1544 default:
1545 RW_TRACE_ERROR1("rw_t4t_sm_read_ndef (): unknown sub_state = %d",
1546 p_t4t->sub_state);
1547 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1548 break;
1549 }
1550
1551 if (p_r_apdu) GKI_freebuf(p_r_apdu);
1552 }
1553
1554 /*******************************************************************************
1555 **
1556 ** Function rw_t4t_sm_update_ndef
1557 **
1558 ** Description State machine for NDEF update procedure
1559 **
1560 ** Returns none
1561 **
1562 *******************************************************************************/
rw_t4t_sm_update_ndef(NFC_HDR * p_r_apdu)1563 static void rw_t4t_sm_update_ndef(NFC_HDR* p_r_apdu) {
1564 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1565 uint8_t* p;
1566 uint16_t status_words;
1567 tRW_DATA rw_data;
1568
1569 #if (BT_TRACE_VERBOSE == TRUE)
1570 RW_TRACE_DEBUG2("rw_t4t_sm_update_ndef (): sub_state:%s (%d)",
1571 rw_t4t_get_sub_state_name(p_t4t->sub_state),
1572 p_t4t->sub_state);
1573 #else
1574 RW_TRACE_DEBUG1("rw_t4t_sm_update_ndef (): sub_state=%d", p_t4t->sub_state);
1575 #endif
1576
1577 /* Get status words */
1578 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1579 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1580 BE_STREAM_TO_UINT16(status_words, p);
1581
1582 if (status_words != T4T_RSP_CMD_CMPLTED) {
1583 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1584 return;
1585 }
1586
1587 switch (p_t4t->sub_state) {
1588 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1589
1590 /* NLEN has been updated */
1591 /* if need to update data */
1592 if (p_t4t->p_update_data) {
1593 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;
1594
1595 if (!rw_t4t_update_file()) {
1596 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1597 p_t4t->p_update_data = NULL;
1598 }
1599 } else {
1600 p_t4t->state = RW_T4T_STATE_IDLE;
1601
1602 /* just finished last step of updating (updating NLEN) */
1603 if (rw_cb.p_cback) {
1604 rw_data.status = NFC_STATUS_OK;
1605
1606 (*(rw_cb.p_cback))(RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
1607 RW_TRACE_DEBUG0(
1608 "rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
1609 }
1610 }
1611 break;
1612
1613 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1614
1615 /* if updating is not completed */
1616 if (p_t4t->rw_length > 0) {
1617 if (!rw_t4t_update_file()) {
1618 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1619 p_t4t->p_update_data = NULL;
1620 }
1621 } else {
1622 p_t4t->p_update_data = NULL;
1623
1624 /* update NLEN as last step of updating file */
1625 if (!rw_t4t_update_nlen(p_t4t->ndef_length)) {
1626 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1627 } else {
1628 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1629 }
1630 }
1631 break;
1632
1633 default:
1634 RW_TRACE_ERROR1("rw_t4t_sm_update_ndef (): unknown sub_state = %d",
1635 p_t4t->sub_state);
1636 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1637 break;
1638 }
1639 }
1640
1641 /*******************************************************************************
1642 **
1643 ** Function rw_t4t_sm_set_readonly
1644 **
1645 ** Description State machine for CC update procedure
1646 **
1647 ** Returns none
1648 **
1649 *******************************************************************************/
rw_t4t_sm_set_readonly(NFC_HDR * p_r_apdu)1650 static void rw_t4t_sm_set_readonly(NFC_HDR* p_r_apdu) {
1651 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1652 uint8_t* p;
1653 uint16_t status_words;
1654 tRW_DATA rw_data;
1655
1656 #if (BT_TRACE_VERBOSE == TRUE)
1657 RW_TRACE_DEBUG2("rw_t4t_sm_set_readonly (): sub_state:%s (%d)",
1658 rw_t4t_get_sub_state_name(p_t4t->sub_state),
1659 p_t4t->sub_state);
1660 #else
1661 RW_TRACE_DEBUG1("rw_t4t_sm_set_readonly (): sub_state=%d", p_t4t->sub_state);
1662 #endif
1663
1664 /* Get status words */
1665 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
1666 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1667 BE_STREAM_TO_UINT16(status_words, p);
1668
1669 if (status_words != T4T_RSP_CMD_CMPLTED) {
1670 rw_t4t_handle_error(NFC_STATUS_CMD_NOT_CMPLTD, *(p - 2), *(p - 1));
1671 return;
1672 }
1673
1674 switch (p_t4t->sub_state) {
1675 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1676
1677 /* CC file has been selected then update write access to read-only in CC
1678 * file */
1679 if (!rw_t4t_update_cc_to_readonly()) {
1680 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1681 } else {
1682 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC;
1683 }
1684 break;
1685
1686 case RW_T4T_SUBSTATE_WAIT_UPDATE_CC:
1687 /* CC Updated, Select NDEF File to allow NDEF operation */
1688 p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS;
1689 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1690
1691 if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
1692 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1693 } else {
1694 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1695 }
1696 break;
1697
1698 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1699 p_t4t->state = RW_T4T_STATE_IDLE;
1700 /* just finished last step of configuring tag read only (Selecting NDEF
1701 * file CC) */
1702 if (rw_cb.p_cback) {
1703 rw_data.status = NFC_STATUS_OK;
1704
1705 RW_TRACE_DEBUG0("rw_t4t_sm_set_readonly (): Sent RW_T4T_SET_TO_RO_EVT");
1706 (*(rw_cb.p_cback))(RW_T4T_SET_TO_RO_EVT, &rw_data);
1707 }
1708 break;
1709
1710 default:
1711 RW_TRACE_ERROR1("rw_t4t_sm_set_readonly (): unknown sub_state = %d",
1712 p_t4t->sub_state);
1713 rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
1714 break;
1715 }
1716 }
1717
1718 /*******************************************************************************
1719 **
1720 ** Function rw_t4t_process_timeout
1721 **
1722 ** Description process timeout event
1723 **
1724 ** Returns none
1725 **
1726 *******************************************************************************/
rw_t4t_process_timeout(TIMER_LIST_ENT * p_tle)1727 void rw_t4t_process_timeout(TIMER_LIST_ENT* p_tle) {
1728 RW_TRACE_DEBUG1("rw_t4t_process_timeout () event=%d", p_tle->event);
1729
1730 if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE) {
1731 rw_t4t_handle_error(NFC_STATUS_TIMEOUT, 0, 0);
1732 } else {
1733 RW_TRACE_ERROR1("rw_t4t_process_timeout () unknown event=%d", p_tle->event);
1734 }
1735 }
1736
1737 /*******************************************************************************
1738 **
1739 ** Function rw_t4t_data_cback
1740 **
1741 ** Description This callback function receives the data from NFCC.
1742 **
1743 ** Returns none
1744 **
1745 *******************************************************************************/
rw_t4t_data_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)1746 static void rw_t4t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
1747 tNFC_CONN* p_data) {
1748 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1749 NFC_HDR* p_r_apdu;
1750 tRW_DATA rw_data;
1751
1752 #if (BT_TRACE_VERBOSE == TRUE)
1753 uint8_t begin_state = p_t4t->state;
1754 #endif
1755
1756 RW_TRACE_DEBUG1("rw_t4t_data_cback () event = 0x%X", event);
1757 nfc_stop_quick_timer(&p_t4t->timer);
1758
1759 switch (event) {
1760 case NFC_DEACTIVATE_CEVT:
1761 NFC_SetStaticRfCback(NULL);
1762 p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
1763 return;
1764
1765 case NFC_ERROR_CEVT:
1766 if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK) {
1767 p_t4t->state = RW_T4T_STATE_IDLE;
1768 rw_data.status = NFC_STATUS_FAILED;
1769 (*(rw_cb.p_cback))(RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1770 } else if (p_t4t->state == RW_T4T_STATE_NDEF_FORMAT) {
1771 p_t4t->state = RW_T4T_STATE_IDLE;
1772 rw_data.status = NFC_STATUS_FAILED;
1773 (*(rw_cb.p_cback))(RW_T4T_NDEF_FORMAT_CPLT_EVT, &rw_data);
1774 } else if (p_t4t->state != RW_T4T_STATE_IDLE) {
1775 rw_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
1776 rw_t4t_handle_error(rw_data.status, 0, 0);
1777 } else {
1778 p_t4t->state = RW_T4T_STATE_IDLE;
1779 rw_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
1780 (*(rw_cb.p_cback))(RW_T4T_INTF_ERROR_EVT, &rw_data);
1781 }
1782 return;
1783
1784 case NFC_DATA_CEVT:
1785 p_r_apdu = (NFC_HDR*)p_data->data.p_data;
1786 break;
1787
1788 default:
1789 return;
1790 }
1791
1792 #if (BT_TRACE_PROTOCOL == TRUE)
1793 if (p_t4t->state != RW_T4T_STATE_IDLE) DispRWT4Tags(p_r_apdu, true);
1794 #endif
1795
1796 #if (BT_TRACE_VERBOSE == TRUE)
1797 RW_TRACE_DEBUG2("RW T4T state: <%s (%d)>",
1798 rw_t4t_get_state_name(p_t4t->state), p_t4t->state);
1799 #else
1800 RW_TRACE_DEBUG1("RW T4T state: %d", p_t4t->state);
1801 #endif
1802
1803 switch (p_t4t->state) {
1804 case RW_T4T_STATE_IDLE:
1805 /* Unexpected R-APDU, it should be raw frame response */
1806 /* forward to upper layer without parsing */
1807 #if (BT_TRACE_VERBOSE == TRUE)
1808 RW_TRACE_DEBUG2("RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len,
1809 NFC_GetStatusName(p_data->data.status));
1810 #else
1811 RW_TRACE_DEBUG2("RW T4T Raw Frame: Len [0x%X] Status [0x%X]",
1812 p_r_apdu->len, p_data->data.status);
1813 #endif
1814 if (rw_cb.p_cback) {
1815 rw_data.raw_frame.status = p_data->data.status;
1816 rw_data.raw_frame.p_data = p_r_apdu;
1817 (*(rw_cb.p_cback))(RW_T4T_RAW_FRAME_EVT, &rw_data);
1818 p_r_apdu = NULL;
1819 } else {
1820 GKI_freebuf(p_r_apdu);
1821 }
1822 break;
1823 case RW_T4T_STATE_DETECT_NDEF:
1824 rw_t4t_sm_detect_ndef(p_r_apdu);
1825 GKI_freebuf(p_r_apdu);
1826 break;
1827 case RW_T4T_STATE_READ_NDEF:
1828 rw_t4t_sm_read_ndef(p_r_apdu);
1829 /* p_r_apdu may send upper lyaer */
1830 break;
1831 case RW_T4T_STATE_UPDATE_NDEF:
1832 rw_t4t_sm_update_ndef(p_r_apdu);
1833 GKI_freebuf(p_r_apdu);
1834 break;
1835 case RW_T4T_STATE_PRESENCE_CHECK:
1836 /* if any response, send presence check with ok */
1837 rw_data.status = NFC_STATUS_OK;
1838 p_t4t->state = RW_T4T_STATE_IDLE;
1839 (*(rw_cb.p_cback))(RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1840 GKI_freebuf(p_r_apdu);
1841 break;
1842 case RW_T4T_STATE_SET_READ_ONLY:
1843 rw_t4t_sm_set_readonly(p_r_apdu);
1844 GKI_freebuf(p_r_apdu);
1845 break;
1846 case RW_T4T_STATE_NDEF_FORMAT:
1847 rw_t4t_sm_ndef_format(p_r_apdu);
1848 GKI_freebuf(p_r_apdu);
1849 break;
1850 default:
1851 RW_TRACE_ERROR1("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
1852 GKI_freebuf(p_r_apdu);
1853 break;
1854 }
1855
1856 #if (BT_TRACE_VERBOSE == TRUE)
1857 if (begin_state != p_t4t->state) {
1858 RW_TRACE_DEBUG2("RW T4T state changed:<%s> -> <%s>",
1859 rw_t4t_get_state_name(begin_state),
1860 rw_t4t_get_state_name(p_t4t->state));
1861 }
1862 #endif
1863 }
1864
1865 /*******************************************************************************
1866 **
1867 ** Function RW_T4tFormatNDef
1868 **
1869 ** Description format T4T tag
1870 **
1871 ** Returns NFC_STATUS_OK if success
1872 **
1873 *******************************************************************************/
RW_T4tFormatNDef(void)1874 tNFC_STATUS RW_T4tFormatNDef(void) {
1875 RW_TRACE_API0("RW_T4tFormatNDef ()");
1876
1877 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
1878 RW_TRACE_ERROR1(
1879 "RW_T4tFormatNDef ():Unable to start command at state (0x%X)",
1880 rw_cb.tcb.t4t.state);
1881 return NFC_STATUS_FAILED;
1882 }
1883
1884 rw_cb.tcb.t4t.card_type = 0x00;
1885
1886 if (!rw_t4t_get_hw_version()) {
1887 return NFC_STATUS_FAILED;
1888 }
1889
1890 rw_cb.tcb.t4t.state = RW_T4T_STATE_NDEF_FORMAT;
1891 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION;
1892
1893 return NFC_STATUS_OK;
1894 }
1895
1896 /*******************************************************************************
1897 **
1898 ** Function rw_t4t_select
1899 **
1900 ** Description Initialise T4T
1901 **
1902 ** Returns NFC_STATUS_OK if success
1903 **
1904 *******************************************************************************/
rw_t4t_select(void)1905 tNFC_STATUS rw_t4t_select(void) {
1906 tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
1907
1908 RW_TRACE_DEBUG0("rw_t4t_select ()");
1909
1910 NFC_SetStaticRfCback(rw_t4t_data_cback);
1911
1912 p_t4t->state = RW_T4T_STATE_IDLE;
1913 p_t4t->version = T4T_MY_VERSION;
1914
1915 /* set it min of max R-APDU data size before reading CC file */
1916 p_t4t->cc_file.max_le = T4T_MIN_MLE;
1917
1918 /* These will be udated during NDEF detection */
1919 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1920 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1921
1922 return NFC_STATUS_OK;
1923 }
1924
1925 /*******************************************************************************
1926 **
1927 ** Function RW_T4tDetectNDef
1928 **
1929 ** Description This function performs NDEF detection procedure
1930 **
1931 ** RW_T4T_NDEF_DETECT_EVT will be returned
1932 **
1933 ** Returns NFC_STATUS_OK if success
1934 ** NFC_STATUS_FAILED if T4T is busy or other error
1935 **
1936 *******************************************************************************/
RW_T4tDetectNDef(void)1937 tNFC_STATUS RW_T4tDetectNDef(void) {
1938 RW_TRACE_API0("RW_T4tDetectNDef ()");
1939
1940 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
1941 RW_TRACE_ERROR1(
1942 "RW_T4tDetectNDef ():Unable to start command at state (0x%X)",
1943 rw_cb.tcb.t4t.state);
1944 return NFC_STATUS_FAILED;
1945 }
1946
1947 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
1948 /* NDEF Tag application has been selected then select CC file */
1949 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
1950 return NFC_STATUS_FAILED;
1951 }
1952 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1953 } else {
1954 /* Select NDEF Tag Application */
1955 if (!rw_t4t_select_application(rw_cb.tcb.t4t.version)) {
1956 return NFC_STATUS_FAILED;
1957 }
1958 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1959 }
1960
1961 rw_cb.tcb.t4t.state = RW_T4T_STATE_DETECT_NDEF;
1962
1963 return NFC_STATUS_OK;
1964 }
1965
1966 /*******************************************************************************
1967 **
1968 ** Function RW_T4tReadNDef
1969 **
1970 ** Description This function performs NDEF read procedure
1971 ** Note: RW_T4tDetectNDef () must be called before using this
1972 **
1973 ** The following event will be returned
1974 ** RW_T4T_NDEF_READ_EVT for each segmented NDEF message
1975 ** RW_T4T_NDEF_READ_CPLT_EVT for the last segment or
1976 ** complete NDEF
1977 ** RW_T4T_NDEF_READ_FAIL_EVT for failure
1978 **
1979 ** Returns NFC_STATUS_OK if success
1980 ** NFC_STATUS_FAILED if T4T is busy or other error
1981 **
1982 *******************************************************************************/
RW_T4tReadNDef(void)1983 tNFC_STATUS RW_T4tReadNDef(void) {
1984 RW_TRACE_API0("RW_T4tReadNDef ()");
1985
1986 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
1987 RW_TRACE_ERROR1("RW_T4tReadNDef ():Unable to start command at state (0x%X)",
1988 rw_cb.tcb.t4t.state);
1989 return NFC_STATUS_FAILED;
1990 }
1991
1992 /* if NDEF has been detected */
1993 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
1994 /* start reading NDEF */
1995 if (!rw_t4t_read_file(T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length,
1996 false)) {
1997 return NFC_STATUS_FAILED;
1998 }
1999
2000 rw_cb.tcb.t4t.state = RW_T4T_STATE_READ_NDEF;
2001 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
2002
2003 return NFC_STATUS_OK;
2004 } else {
2005 RW_TRACE_ERROR0("RW_T4tReadNDef ():No NDEF detected");
2006 return NFC_STATUS_FAILED;
2007 }
2008 }
2009
2010 /*******************************************************************************
2011 **
2012 ** Function RW_T4tUpdateNDef
2013 **
2014 ** Description This function performs NDEF update procedure
2015 ** Note: RW_T4tDetectNDef () must be called before using this
2016 ** Updating data must not be removed until returning
2017 ** event
2018 **
2019 ** The following event will be returned
2020 ** RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
2021 ** RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
2022 **
2023 ** Returns NFC_STATUS_OK if success
2024 ** NFC_STATUS_FAILED if T4T is busy or other error
2025 **
2026 *******************************************************************************/
RW_T4tUpdateNDef(uint16_t length,uint8_t * p_data)2027 tNFC_STATUS RW_T4tUpdateNDef(uint16_t length, uint8_t* p_data) {
2028 RW_TRACE_API1("RW_T4tUpdateNDef () length:%d", length);
2029
2030 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
2031 RW_TRACE_ERROR1(
2032 "RW_T4tUpdateNDef ():Unable to start command at state (0x%X)",
2033 rw_cb.tcb.t4t.state);
2034 return NFC_STATUS_FAILED;
2035 }
2036
2037 /* if NDEF has been detected */
2038 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
2039 /* if read-only */
2040 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
2041 RW_TRACE_ERROR0("RW_T4tUpdateNDef ():NDEF is read-only");
2042 return NFC_STATUS_FAILED;
2043 }
2044
2045 if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size <
2046 length + T4T_FILE_LENGTH_SIZE) {
2047 RW_TRACE_ERROR2(
2048 "RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file "
2049 "size (%d)",
2050 length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
2051 return NFC_STATUS_FAILED;
2052 }
2053
2054 /* store NDEF length and data */
2055 rw_cb.tcb.t4t.ndef_length = length;
2056 rw_cb.tcb.t4t.p_update_data = p_data;
2057
2058 rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE;
2059 rw_cb.tcb.t4t.rw_length = length;
2060
2061 /* set NLEN to 0x0000 for the first step */
2062 if (!rw_t4t_update_nlen(0x0000)) {
2063 return NFC_STATUS_FAILED;
2064 }
2065
2066 rw_cb.tcb.t4t.state = RW_T4T_STATE_UPDATE_NDEF;
2067 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
2068
2069 return NFC_STATUS_OK;
2070 } else {
2071 RW_TRACE_ERROR0("RW_T4tUpdateNDef ():No NDEF detected");
2072 return NFC_STATUS_FAILED;
2073 }
2074 }
2075
2076 /*****************************************************************************
2077 **
2078 ** Function RW_T4tPresenceCheck
2079 **
2080 ** Description
2081 ** Check if the tag is still in the field.
2082 **
2083 ** The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
2084 ** or non-presence.
2085 **
2086 ** option is RW_T4T_CHK_EMPTY_I_BLOCK, use empty I block for presence check
2087 **
2088 ** Returns
2089 ** NFC_STATUS_OK, if raw data frame sent
2090 ** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
2091 ** NFC_STATUS_FAILED: other error
2092 **
2093 *****************************************************************************/
RW_T4tPresenceCheck(uint8_t option)2094 tNFC_STATUS RW_T4tPresenceCheck(uint8_t option) {
2095 tNFC_STATUS retval = NFC_STATUS_OK;
2096 tRW_DATA evt_data;
2097 bool status;
2098 NFC_HDR* p_data;
2099
2100 RW_TRACE_API1("RW_T4tPresenceCheck () %d", option);
2101
2102 /* If RW_SelectTagType was not called (no conn_callback) return failure */
2103 if (!rw_cb.p_cback) {
2104 retval = NFC_STATUS_FAILED;
2105 }
2106 /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with
2107 NFC_STATUS_FAILED */
2108 else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED) {
2109 evt_data.status = NFC_STATUS_FAILED;
2110 (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2111 }
2112 /* If command is pending, assume tag is still present */
2113 else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
2114 evt_data.status = NFC_STATUS_OK;
2115 (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
2116 } else {
2117 status = false;
2118 if (option == RW_T4T_CHK_EMPTY_I_BLOCK) {
2119 /* use empty I block for presence check */
2120 p_data = (NFC_HDR*)GKI_getbuf(NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE);
2121 if (p_data != NULL) {
2122 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
2123 p_data->len = 0;
2124 if (NFC_SendData(NFC_RF_CONN_ID, (NFC_HDR*)p_data) == NFC_STATUS_OK)
2125 status = true;
2126 }
2127 } else {
2128 /* use read binary on the given channel */
2129 rw_cb.tcb.t4t.channel = 0;
2130 if (option <= RW_T4T_CHK_READ_BINARY_CH3) rw_cb.tcb.t4t.channel = option;
2131 status = rw_t4t_read_file(0, 1, false);
2132 rw_cb.tcb.t4t.channel = 0;
2133 }
2134
2135 if (status == true) {
2136 rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
2137 } else {
2138 retval = NFC_STATUS_NO_BUFFERS;
2139 }
2140 }
2141
2142 return (retval);
2143 }
2144
2145 /*****************************************************************************
2146 **
2147 ** Function RW_T4tSetNDefReadOnly
2148 **
2149 ** Description This function performs NDEF read-only procedure
2150 ** Note: RW_T4tDetectNDef() must be called before using this
2151 **
2152 ** The RW_T4T_SET_TO_RO_EVT event will be returned.
2153 **
2154 ** Returns NFC_STATUS_OK if success
2155 ** NFC_STATUS_FAILED if T4T is busy or other error
2156 **
2157 *****************************************************************************/
RW_T4tSetNDefReadOnly(void)2158 tNFC_STATUS RW_T4tSetNDefReadOnly(void) {
2159 tNFC_STATUS retval = NFC_STATUS_OK;
2160 tRW_DATA evt_data;
2161
2162 RW_TRACE_API0("RW_T4tSetNDefReadOnly ()");
2163
2164 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
2165 RW_TRACE_ERROR1(
2166 "RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)",
2167 rw_cb.tcb.t4t.state);
2168 return NFC_STATUS_FAILED;
2169 }
2170
2171 /* if NDEF has been detected */
2172 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
2173 /* if read-only */
2174 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
2175 RW_TRACE_API0("RW_T4tSetNDefReadOnly (): NDEF is already read-only");
2176
2177 evt_data.status = NFC_STATUS_OK;
2178 (*rw_cb.p_cback)(RW_T4T_SET_TO_RO_EVT, &evt_data);
2179 return (retval);
2180 }
2181
2182 /* NDEF Tag application has been selected then select CC file */
2183 if (!rw_t4t_select_file(T4T_CC_FILE_ID)) {
2184 return NFC_STATUS_FAILED;
2185 }
2186
2187 rw_cb.tcb.t4t.state = RW_T4T_STATE_SET_READ_ONLY;
2188 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
2189
2190 return NFC_STATUS_OK;
2191 } else {
2192 RW_TRACE_ERROR0("RW_T4tSetNDefReadOnly ():No NDEF detected");
2193 return NFC_STATUS_FAILED;
2194 }
2195 return (retval);
2196 }
2197
2198 #if (BT_TRACE_VERBOSE == TRUE)
2199 /*******************************************************************************
2200 **
2201 ** Function rw_t4t_get_state_name
2202 **
2203 ** Description This function returns the state name.
2204 **
2205 ** NOTE conditionally compiled to save memory.
2206 **
2207 ** Returns pointer to the name
2208 **
2209 *******************************************************************************/
rw_t4t_get_state_name(uint8_t state)2210 static char* rw_t4t_get_state_name(uint8_t state) {
2211 switch (state) {
2212 case RW_T4T_STATE_NOT_ACTIVATED:
2213 return ("NOT_ACTIVATED");
2214 case RW_T4T_STATE_IDLE:
2215 return ("IDLE");
2216 case RW_T4T_STATE_DETECT_NDEF:
2217 return ("NDEF_DETECTION");
2218 case RW_T4T_STATE_READ_NDEF:
2219 return ("READ_NDEF");
2220 case RW_T4T_STATE_UPDATE_NDEF:
2221 return ("UPDATE_NDEF");
2222 case RW_T4T_STATE_PRESENCE_CHECK:
2223 return ("PRESENCE_CHECK");
2224 case RW_T4T_STATE_SET_READ_ONLY:
2225 return ("SET_READ_ONLY");
2226
2227 default:
2228 return ("???? UNKNOWN STATE");
2229 }
2230 }
2231
2232 /*******************************************************************************
2233 **
2234 ** Function rw_t4t_get_sub_state_name
2235 **
2236 ** Description This function returns the sub_state name.
2237 **
2238 ** NOTE conditionally compiled to save memory.
2239 **
2240 ** Returns pointer to the name
2241 **
2242 *******************************************************************************/
rw_t4t_get_sub_state_name(uint8_t sub_state)2243 static char* rw_t4t_get_sub_state_name(uint8_t sub_state) {
2244 switch (sub_state) {
2245 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
2246 return ("WAIT_SELECT_APP");
2247 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
2248 return ("WAIT_SELECT_CC");
2249 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
2250 return ("WAIT_CC_FILE");
2251 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
2252 return ("WAIT_SELECT_NDEF_FILE");
2253 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
2254 return ("WAIT_READ_NLEN");
2255
2256 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
2257 return ("WAIT_READ_RESP");
2258 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
2259 return ("WAIT_UPDATE_RESP");
2260 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
2261 return ("WAIT_UPDATE_NLEN");
2262 case RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION:
2263 return ("WAIT_GET_HW_VERSION");
2264 case RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION:
2265 return ("WAIT_GET_SW_VERSION");
2266 case RW_T4T_SUBSTATE_WAIT_GET_UID:
2267 return ("WAIT_GET_UID");
2268 case RW_T4T_SUBSTATE_WAIT_CREATE_APP:
2269 return ("WAIT_CREATE_APP");
2270 case RW_T4T_SUBSTATE_WAIT_CREATE_CC:
2271 return ("WAIT_CREATE_CC");
2272 case RW_T4T_SUBSTATE_WAIT_CREATE_NDEF:
2273 return ("WAIT_CREATE_NDEF");
2274 case RW_T4T_SUBSTATE_WAIT_WRITE_CC:
2275 return ("WAIT_WRITE_CC");
2276 case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
2277 return ("WAIT_WRITE_NDEF");
2278 default:
2279 return ("???? UNKNOWN SUBSTATE");
2280 }
2281 }
2282 #endif
2283