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