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 /* sub state */
50 #define RW_T4T_SUBSTATE_WAIT_SELECT_APP 0x00 /* waiting for response of selecting AID */
51 #define RW_T4T_SUBSTATE_WAIT_SELECT_CC 0x01 /* waiting for response of selecting CC */
52 #define RW_T4T_SUBSTATE_WAIT_CC_FILE 0x02 /* waiting for response of reading CC */
53 #define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE 0x03 /* waiting for response of selecting NDEF */
54 #define RW_T4T_SUBSTATE_WAIT_READ_NLEN 0x04 /* waiting for response of reading NLEN */
55 #define RW_T4T_SUBSTATE_WAIT_READ_RESP 0x05 /* waiting for response of reading file */
56 #define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP 0x06 /* waiting for response of updating file */
57 #define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07 /* waiting for response of updating NLEN */
58 #define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08 /* waiting for response of updating CC */
59
60 #if (BT_TRACE_VERBOSE == TRUE)
61 static char *rw_t4t_get_state_name (UINT8 state);
62 static char *rw_t4t_get_sub_state_name (UINT8 sub_state);
63 #endif
64
65 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu);
66 static BOOLEAN rw_t4t_select_file (UINT16 file_id);
67 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue);
68 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len);
69 static BOOLEAN rw_t4t_update_file (void);
70 static BOOLEAN rw_t4t_update_cc_to_readonly (void);
71 static BOOLEAN rw_t4t_select_application (UINT8 version);
72 static BOOLEAN rw_t4t_validate_cc_file (void);
73 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2);
74 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu);
75 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu);
76 static void rw_t4t_sm_update_ndef (BT_HDR *p_r_apdu);
77 static void rw_t4t_sm_set_readonly (BT_HDR *p_r_apdu);
78 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
79
80 /*******************************************************************************
81 **
82 ** Function rw_t4t_send_to_lower
83 **
84 ** Description Send C-APDU to lower layer
85 **
86 ** Returns TRUE if success
87 **
88 *******************************************************************************/
rw_t4t_send_to_lower(BT_HDR * p_c_apdu)89 static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu)
90 {
91 #if (BT_TRACE_PROTOCOL == TRUE)
92 DispRWT4Tags (p_c_apdu, FALSE);
93 #endif
94
95 if (NFC_SendData (NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK)
96 {
97 RW_TRACE_ERROR0 ("rw_t4t_send_to_lower (): NFC_SendData () failed");
98 return FALSE;
99 }
100
101 nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE,
102 (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
103
104 return TRUE;
105 }
106
107 /*******************************************************************************
108 **
109 ** Function rw_t4t_select_file
110 **
111 ** Description Send Select Command (by File ID) to peer
112 **
113 ** Returns TRUE if success
114 **
115 *******************************************************************************/
rw_t4t_select_file(UINT16 file_id)116 static BOOLEAN rw_t4t_select_file (UINT16 file_id)
117 {
118 BT_HDR *p_c_apdu;
119 UINT8 *p;
120
121 RW_TRACE_DEBUG1 ("rw_t4t_select_file (): File ID:0x%04X", file_id);
122
123 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
124
125 if (!p_c_apdu)
126 {
127 RW_TRACE_ERROR0 ("rw_t4t_select_file (): Cannot allocate buffer");
128 return FALSE;
129 }
130
131 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
132 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
133
134 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
135 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
136 UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_FILE_ID);
137
138 /* if current version mapping is V2.0 */
139 if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0)
140 {
141 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_0CH);
142 }
143 else /* version 1.0 */
144 {
145 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
146 }
147
148 UINT8_TO_BE_STREAM (p, T4T_FILE_ID_SIZE);
149 UINT16_TO_BE_STREAM (p, file_id);
150
151 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE;
152
153 if (!rw_t4t_send_to_lower (p_c_apdu))
154 {
155 return FALSE;
156 }
157
158 return TRUE;
159 }
160
161 /*******************************************************************************
162 **
163 ** Function rw_t4t_read_file
164 **
165 ** Description Send ReadBinary Command to peer
166 **
167 ** Returns TRUE if success
168 **
169 *******************************************************************************/
rw_t4t_read_file(UINT16 offset,UINT16 length,BOOLEAN is_continue)170 static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue)
171 {
172 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
173 BT_HDR *p_c_apdu;
174 UINT8 *p;
175
176 RW_TRACE_DEBUG3 ("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ",
177 offset, length, is_continue);
178
179 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
180
181 if (!p_c_apdu)
182 {
183 RW_TRACE_ERROR0 ("rw_t4t_read_file (): Cannot allocate buffer");
184 return FALSE;
185 }
186
187 /* if this is the first reading */
188 if (is_continue == FALSE)
189 {
190 /* initialise starting offset and total length */
191 /* these will be updated when receiving response */
192 p_t4t->rw_offset = offset;
193 p_t4t->rw_length = length;
194 }
195
196 /* adjust reading length if payload is bigger than max size per single command */
197 if (length > p_t4t->max_read_size)
198 {
199 length = (UINT8) (p_t4t->max_read_size);
200 }
201
202 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
203 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
204
205 UINT8_TO_BE_STREAM (p, (T4T_CMD_CLASS | rw_cb.tcb.t4t.channel));
206 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_READ_BINARY);
207 UINT16_TO_BE_STREAM (p, offset);
208 UINT8_TO_BE_STREAM (p, length); /* Le */
209
210 p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
211
212 if (!rw_t4t_send_to_lower (p_c_apdu))
213 {
214 return FALSE;
215 }
216
217 return TRUE;
218 }
219
220 /*******************************************************************************
221 **
222 ** Function rw_t4t_update_nlen
223 **
224 ** Description Send UpdateBinary Command to update NLEN to peer
225 **
226 ** Returns TRUE if success
227 **
228 *******************************************************************************/
rw_t4t_update_nlen(UINT16 ndef_len)229 static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len)
230 {
231 BT_HDR *p_c_apdu;
232 UINT8 *p;
233
234 RW_TRACE_DEBUG1 ("rw_t4t_update_nlen () NLEN:%d", ndef_len);
235
236 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
237
238 if (!p_c_apdu)
239 {
240 RW_TRACE_ERROR0 ("rw_t4t_update_nlen (): Cannot allocate buffer");
241 return FALSE;
242 }
243
244 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
245 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
246
247 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
248 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
249 UINT16_TO_BE_STREAM (p, 0x0000); /* offset for NLEN */
250 UINT8_TO_BE_STREAM (p, T4T_FILE_LENGTH_SIZE);
251 UINT16_TO_BE_STREAM (p, ndef_len);
252
253 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE;
254
255 if (!rw_t4t_send_to_lower (p_c_apdu))
256 {
257 return FALSE;
258 }
259
260 return TRUE;
261 }
262
263 /*******************************************************************************
264 **
265 ** Function rw_t4t_update_file
266 **
267 ** Description Send UpdateBinary Command to peer
268 **
269 ** Returns TRUE if success
270 **
271 *******************************************************************************/
rw_t4t_update_file(void)272 static BOOLEAN rw_t4t_update_file (void)
273 {
274 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
275 BT_HDR *p_c_apdu;
276 UINT8 *p;
277 UINT16 length;
278
279 RW_TRACE_DEBUG2 ("rw_t4t_update_file () rw_offset:%d, rw_length:%d",
280 p_t4t->rw_offset, p_t4t->rw_length);
281
282 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
283
284 if (!p_c_apdu)
285 {
286 RW_TRACE_ERROR0 ("rw_t4t_write_file (): Cannot allocate buffer");
287 return FALSE;
288 }
289
290 /* try to send all of remaining data */
291 length = p_t4t->rw_length;
292
293 /* adjust updating length if payload is bigger than max size per single command */
294 if (length > p_t4t->max_update_size)
295 {
296 length = (UINT8) (p_t4t->max_update_size);
297 }
298
299 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
300 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
301
302 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
303 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
304 UINT16_TO_BE_STREAM (p, p_t4t->rw_offset);
305 UINT8_TO_BE_STREAM (p, length);
306
307 memcpy (p, p_t4t->p_update_data, length);
308
309 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
310
311 if (!rw_t4t_send_to_lower (p_c_apdu))
312 {
313 return FALSE;
314 }
315
316 /* adjust offset, length and pointer for remaining data */
317 p_t4t->rw_offset += length;
318 p_t4t->rw_length -= length;
319 p_t4t->p_update_data += length;
320
321 return TRUE;
322 }
323
324 /*******************************************************************************
325 **
326 ** Function rw_t4t_update_cc_to_readonly
327 **
328 ** Description Send UpdateBinary Command for changing Write access
329 **
330 ** Returns TRUE if success
331 **
332 *******************************************************************************/
rw_t4t_update_cc_to_readonly(void)333 static BOOLEAN rw_t4t_update_cc_to_readonly (void)
334 {
335 BT_HDR *p_c_apdu;
336 UINT8 *p;
337
338 RW_TRACE_DEBUG0 ("rw_t4t_update_cc_to_readonly (): Remove Write access from CC");
339
340 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
341
342 if (!p_c_apdu)
343 {
344 RW_TRACE_ERROR0 ("rw_t4t_update_cc_to_readonly (): Cannot allocate buffer");
345 return FALSE;
346 }
347
348 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
349 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
350
351 /* Add Command Header */
352 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
353 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY);
354 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 */
355 UINT8_TO_BE_STREAM (p, 1); /* Length of write access field in cc interms of bytes */
356
357 /* Remove Write access */
358 UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS);
359
360
361 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + 1;
362
363 if (!rw_t4t_send_to_lower (p_c_apdu))
364 {
365 return FALSE;
366 }
367
368 return TRUE;
369 }
370
371 /*******************************************************************************
372 **
373 ** Function rw_t4t_select_application
374 **
375 ** Description Select Application
376 **
377 ** NDEF Tag Application Select - C-APDU
378 **
379 ** CLA INS P1 P2 Lc Data(AID) Le
380 ** V1.0: 00 A4 04 00 07 D2760000850100 -
381 ** V2.0: 00 A4 04 00 07 D2760000850101 00
382 **
383 ** Returns TRUE if success
384 **
385 *******************************************************************************/
rw_t4t_select_application(UINT8 version)386 static BOOLEAN rw_t4t_select_application (UINT8 version)
387 {
388 BT_HDR *p_c_apdu;
389 UINT8 *p;
390
391 RW_TRACE_DEBUG1 ("rw_t4t_select_application () version:0x%X", version);
392
393 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID);
394
395 if (!p_c_apdu)
396 {
397 RW_TRACE_ERROR0 ("rw_t4t_select_application (): Cannot allocate buffer");
398 return FALSE;
399 }
400
401 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
402 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
403
404 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS);
405 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT);
406 UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_NAME);
407 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H);
408
409 if (version == T4T_VERSION_1_0) /* this is for V1.0 */
410 {
411 UINT8_TO_BE_STREAM (p, T4T_V10_NDEF_TAG_AID_LEN);
412
413 memcpy (p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN);
414
415 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN;
416 }
417 else if (version == T4T_VERSION_2_0) /* this is for V2.0 */
418 {
419 UINT8_TO_BE_STREAM (p, T4T_V20_NDEF_TAG_AID_LEN);
420
421 memcpy (p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN);
422 p += T4T_V20_NDEF_TAG_AID_LEN;
423
424 UINT8_TO_BE_STREAM (p, 0x00); /* Le set to 0x00 */
425
426 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1;
427 }
428 else
429 {
430 return FALSE;
431 }
432
433 if (!rw_t4t_send_to_lower (p_c_apdu))
434 {
435 return FALSE;
436 }
437
438 return TRUE;
439 }
440
441 /*******************************************************************************
442 **
443 ** Function rw_t4t_validate_cc_file
444 **
445 ** Description Validate CC file and mandatory NDEF TLV
446 **
447 ** Returns TRUE if success
448 **
449 *******************************************************************************/
rw_t4t_validate_cc_file(void)450 static BOOLEAN rw_t4t_validate_cc_file (void)
451 {
452 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
453
454 RW_TRACE_DEBUG0 ("rw_t4t_validate_cc_file ()");
455
456 if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN)
457 {
458 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): CCLEN (%d) is too short",
459 p_t4t->cc_file.cclen);
460 return FALSE;
461 }
462
463 if (T4T_GET_MAJOR_VERSION (p_t4t->cc_file.version) != T4T_GET_MAJOR_VERSION (p_t4t->version))
464 {
465 RW_TRACE_ERROR2 ("rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours (0x%02X)",
466 p_t4t->cc_file.version, p_t4t->version);
467 return FALSE;
468 }
469
470 if (p_t4t->cc_file.max_le < 0x000F)
471 {
472 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLe (%d) is too small",
473 p_t4t->cc_file.max_le);
474 return FALSE;
475 }
476
477 if (p_t4t->cc_file.max_lc < 0x0001)
478 {
479 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLc (%d) is too small",
480 p_t4t->cc_file.max_lc);
481 return FALSE;
482 }
483
484 if ( (p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID)
485 ||(p_t4t->cc_file.ndef_fc.file_id == 0xE102)
486 ||(p_t4t->cc_file.ndef_fc.file_id == 0xE103)
487 ||((p_t4t->cc_file.ndef_fc.file_id == 0x0000) && (p_t4t->cc_file.version == 0x20))
488 ||(p_t4t->cc_file.ndef_fc.file_id == 0x3F00)
489 ||(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF)
490 ||(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF) )
491 {
492 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid",
493 p_t4t->cc_file.ndef_fc.file_id);
494 return FALSE;
495 }
496
497 if ( (p_t4t->cc_file.ndef_fc.max_file_size < 0x0005)
498 ||(p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF) )
499 {
500 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): max_file_size (%d) is reserved",
501 p_t4t->cc_file.ndef_fc.max_file_size);
502 return FALSE;
503 }
504
505 if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS)
506 {
507 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid",
508 p_t4t->cc_file.ndef_fc.read_access);
509 return FALSE;
510 }
511
512 if ( (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
513 &&(p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS) )
514 {
515 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid",
516 p_t4t->cc_file.ndef_fc.write_access);
517 return FALSE;
518 }
519
520 return TRUE;
521 }
522
523 /*******************************************************************************
524 **
525 ** Function rw_t4t_handle_error
526 **
527 ** Description notify error to application and clean up
528 **
529 ** Returns none
530 **
531 *******************************************************************************/
rw_t4t_handle_error(tNFC_STATUS status,UINT8 sw1,UINT8 sw2)532 static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2)
533 {
534 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
535 tRW_DATA rw_data;
536 tRW_EVENT event;
537
538 RW_TRACE_DEBUG4 ("rw_t4t_handle_error (): status:0x%02X, sw1:0x%02X, sw2:0x%02X, state:0x%X",
539 status, sw1, sw2, p_t4t->state);
540
541 nfc_stop_quick_timer (&p_t4t->timer);
542
543 if (rw_cb.p_cback)
544 {
545 rw_data.status = status;
546
547 rw_data.t4t_sw.sw1 = sw1;
548 rw_data.t4t_sw.sw2 = sw2;
549
550 switch (p_t4t->state)
551 {
552 case RW_T4T_STATE_DETECT_NDEF:
553 rw_data.ndef.flags = RW_NDEF_FL_UNKNOWN;
554 event = RW_T4T_NDEF_DETECT_EVT;
555 break;
556
557 case RW_T4T_STATE_READ_NDEF:
558 event = RW_T4T_NDEF_READ_FAIL_EVT;
559 break;
560
561 case RW_T4T_STATE_UPDATE_NDEF:
562 event = RW_T4T_NDEF_UPDATE_FAIL_EVT;
563 break;
564
565 case RW_T4T_STATE_PRESENCE_CHECK:
566 event = RW_T4T_PRESENCE_CHECK_EVT;
567 rw_data.status = NFC_STATUS_FAILED;
568 break;
569
570 case RW_T4T_STATE_SET_READ_ONLY:
571 event = RW_T4T_SET_TO_RO_EVT;
572 break;
573
574 default:
575 event = RW_T4T_MAX_EVT;
576 break;
577 }
578
579 p_t4t->state = RW_T4T_STATE_IDLE;
580
581 if (event != RW_T4T_MAX_EVT)
582 {
583 (*(rw_cb.p_cback)) (event, &rw_data);
584 }
585 }
586 else
587 {
588 p_t4t->state = RW_T4T_STATE_IDLE;
589 }
590 }
591
592 /*******************************************************************************
593 **
594 ** Function rw_t4t_sm_detect_ndef
595 **
596 ** Description State machine for NDEF detection procedure
597 **
598 ** Returns none
599 **
600 *******************************************************************************/
rw_t4t_sm_detect_ndef(BT_HDR * p_r_apdu)601 static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu)
602 {
603 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
604 UINT8 *p, type, length;
605 UINT16 status_words, nlen;
606 tRW_DATA rw_data;
607
608 #if (BT_TRACE_VERBOSE == TRUE)
609 RW_TRACE_DEBUG2 ("rw_t4t_sm_detect_ndef (): sub_state:%s (%d)",
610 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
611 #else
612 RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): sub_state=%d", p_t4t->sub_state);
613 #endif
614
615 /* get status words */
616 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
617 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
618 BE_STREAM_TO_UINT16 (status_words, p);
619
620 if (status_words != T4T_RSP_CMD_CMPLTED)
621 {
622 /* try V1.0 after failing of V2.0 */
623 if ( (p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP)
624 &&(p_t4t->version == T4T_VERSION_2_0) )
625 {
626 p_t4t->version = T4T_VERSION_1_0;
627
628 RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): retry with version=0x%02X",
629 p_t4t->version);
630
631 if (!rw_t4t_select_application (T4T_VERSION_1_0))
632 {
633 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
634 }
635 return;
636 }
637
638 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
639 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
640 return;
641 }
642
643 switch (p_t4t->sub_state)
644 {
645 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
646
647 /* NDEF Tag application has been selected then select CC file */
648 if (!rw_t4t_select_file (T4T_CC_FILE_ID))
649 {
650 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
651 }
652 else
653 {
654 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
655 }
656 break;
657
658 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
659
660 /* CC file has been selected then read mandatory part of CC file */
661 if (!rw_t4t_read_file (0x00, T4T_CC_FILE_MIN_LEN, FALSE))
662 {
663 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
664 }
665 else
666 {
667 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
668 }
669 break;
670
671 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
672
673 /* CC file has been read then validate and select mandatory NDEF file */
674 if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE)
675 {
676 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
677
678 BE_STREAM_TO_UINT16 (p_t4t->cc_file.cclen, p);
679 BE_STREAM_TO_UINT8 (p_t4t->cc_file.version, p);
680 BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_le, p);
681 BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_lc, p);
682
683 BE_STREAM_TO_UINT8 (type, p);
684 BE_STREAM_TO_UINT8 (length, p);
685
686 if ( (type == T4T_NDEF_FILE_CONTROL_TYPE)
687 &&(length == T4T_FILE_CONTROL_LENGTH) )
688 {
689 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.file_id, p);
690 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.max_file_size, p);
691 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.read_access, p);
692 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.write_access, p);
693
694 #if (BT_TRACE_VERBOSE == TRUE)
695 RW_TRACE_DEBUG0 ("Capability Container (CC) file");
696 RW_TRACE_DEBUG1 (" CCLEN: 0x%04X", p_t4t->cc_file.cclen);
697 RW_TRACE_DEBUG1 (" Version:0x%02X", p_t4t->cc_file.version);
698 RW_TRACE_DEBUG1 (" MaxLe: 0x%04X", p_t4t->cc_file.max_le);
699 RW_TRACE_DEBUG1 (" MaxLc: 0x%04X", p_t4t->cc_file.max_lc);
700 RW_TRACE_DEBUG0 (" NDEF File Control TLV");
701 RW_TRACE_DEBUG1 (" FileID: 0x%04X", p_t4t->cc_file.ndef_fc.file_id);
702 RW_TRACE_DEBUG1 (" MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
703 RW_TRACE_DEBUG1 (" ReadAccess: 0x%02X", p_t4t->cc_file.ndef_fc.read_access);
704 RW_TRACE_DEBUG1 (" WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
705 #endif
706
707 if (rw_t4t_validate_cc_file ())
708 {
709 if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
710 {
711 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
712 }
713 else
714 {
715 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
716 }
717 break;
718 }
719 }
720 }
721
722 /* invalid response or CC file */
723 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
724 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
725 break;
726
727 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
728
729 /* NDEF file has been selected then read the first 2 bytes (NLEN) */
730 if (!rw_t4t_read_file (0, T4T_FILE_LENGTH_SIZE, FALSE))
731 {
732 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
733 }
734 else
735 {
736 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
737 }
738 break;
739
740 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
741
742 /* NLEN has been read then report upper layer */
743 if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE)
744 {
745 /* get length of NDEF */
746 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
747 BE_STREAM_TO_UINT16 (nlen, p);
748
749 if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE)
750 {
751 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
752
753 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
754 {
755 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
756 }
757
758 /* Get max bytes to read per command */
759 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ)
760 {
761 p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ;
762 }
763 else
764 {
765 p_t4t->max_read_size = p_t4t->cc_file.max_le;
766 }
767
768 /* Le: valid range is 0x01 to 0xFF */
769 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE)
770 {
771 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
772 }
773
774 /* Get max bytes to update per command */
775 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE)
776 {
777 p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE;
778 }
779 else
780 {
781 p_t4t->max_update_size = p_t4t->cc_file.max_lc;
782 }
783
784 /* Lc: valid range is 0x01 to 0xFF */
785 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC)
786 {
787 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
788 }
789
790 p_t4t->ndef_length = nlen;
791 p_t4t->state = RW_T4T_STATE_IDLE;
792
793 if (rw_cb.p_cback)
794 {
795 rw_data.ndef.status = NFC_STATUS_OK;
796 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
797 rw_data.ndef.max_size = (UINT32) (p_t4t->cc_file.ndef_fc.max_file_size - (UINT16) T4T_FILE_LENGTH_SIZE);
798 rw_data.ndef.cur_size = nlen;
799 rw_data.ndef.flags = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
800 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS)
801 {
802 rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
803 }
804
805 (*(rw_cb.p_cback)) (RW_T4T_NDEF_DETECT_EVT, &rw_data);
806
807 RW_TRACE_DEBUG0 ("rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT");
808 }
809 }
810 else
811 {
812 /* NLEN should be less than max file size */
813 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file size (%d)",
814 nlen, p_t4t->cc_file.ndef_fc.max_file_size);
815
816 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
817 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
818 }
819 }
820 else
821 {
822 /* response payload size should be T4T_FILE_LENGTH_SIZE */
823 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d",
824 p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);
825
826 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED);
827 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
828 }
829 break;
830
831 default:
832 RW_TRACE_ERROR1 ("rw_t4t_sm_detect_ndef (): unknown sub_state=%d", p_t4t->sub_state);
833 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
834 break;
835 }
836 }
837
838 /*******************************************************************************
839 **
840 ** Function rw_t4t_sm_read_ndef
841 **
842 ** Description State machine for NDEF read procedure
843 **
844 ** Returns none
845 **
846 *******************************************************************************/
rw_t4t_sm_read_ndef(BT_HDR * p_r_apdu)847 static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu)
848 {
849 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
850 UINT8 *p;
851 UINT16 status_words;
852 tRW_DATA rw_data;
853
854 #if (BT_TRACE_VERBOSE == TRUE)
855 RW_TRACE_DEBUG2 ("rw_t4t_sm_read_ndef (): sub_state:%s (%d)",
856 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
857 #else
858 RW_TRACE_DEBUG1 ("rw_t4t_sm_read_ndef (): sub_state=%d", p_t4t->sub_state);
859 #endif
860
861 /* get status words */
862 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
863 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
864 BE_STREAM_TO_UINT16 (status_words, p);
865
866 if (status_words != T4T_RSP_CMD_CMPLTED)
867 {
868 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
869 GKI_freebuf (p_r_apdu);
870 return;
871 }
872
873 switch (p_t4t->sub_state)
874 {
875 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
876
877 /* Read partial or complete data */
878 p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
879
880 if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length))
881 {
882 p_t4t->rw_length -= p_r_apdu->len;
883 p_t4t->rw_offset += p_r_apdu->len;
884
885 if (rw_cb.p_cback)
886 {
887 rw_data.data.status = NFC_STATUS_OK;
888 rw_data.data.p_data = p_r_apdu;
889
890 /* if need to read more data */
891 if (p_t4t->rw_length > 0)
892 {
893 (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_EVT, &rw_data);
894
895 if (!rw_t4t_read_file (p_t4t->rw_offset, p_t4t->rw_length, TRUE))
896 {
897 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
898 }
899 }
900 else
901 {
902 p_t4t->state = RW_T4T_STATE_IDLE;
903
904 (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
905
906 RW_TRACE_DEBUG0 ("rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT");
907
908 }
909
910 p_r_apdu = NULL;
911 }
912 else
913 {
914 p_t4t->rw_length = 0;
915 p_t4t->state = RW_T4T_STATE_IDLE;
916 }
917 }
918 else
919 {
920 RW_TRACE_ERROR2 ("rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length (%d)",
921 p_r_apdu->len, p_t4t->rw_length);
922 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0);
923 }
924 break;
925
926 default:
927 RW_TRACE_ERROR1 ("rw_t4t_sm_read_ndef (): unknown sub_state = %d", p_t4t->sub_state);
928 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
929 break;
930 }
931
932 if (p_r_apdu)
933 GKI_freebuf (p_r_apdu);
934 }
935
936 /*******************************************************************************
937 **
938 ** Function rw_t4t_sm_update_ndef
939 **
940 ** Description State machine for NDEF update procedure
941 **
942 ** Returns none
943 **
944 *******************************************************************************/
rw_t4t_sm_update_ndef(BT_HDR * p_r_apdu)945 static void rw_t4t_sm_update_ndef (BT_HDR *p_r_apdu)
946 {
947 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
948 UINT8 *p;
949 UINT16 status_words;
950 tRW_DATA rw_data;
951
952 #if (BT_TRACE_VERBOSE == TRUE)
953 RW_TRACE_DEBUG2 ("rw_t4t_sm_update_ndef (): sub_state:%s (%d)",
954 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
955 #else
956 RW_TRACE_DEBUG1 ("rw_t4t_sm_update_ndef (): sub_state=%d", p_t4t->sub_state);
957 #endif
958
959 /* Get status words */
960 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
961 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
962 BE_STREAM_TO_UINT16 (status_words, p);
963
964 if (status_words != T4T_RSP_CMD_CMPLTED)
965 {
966 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
967 return;
968 }
969
970 switch (p_t4t->sub_state)
971 {
972 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
973
974 /* NLEN has been updated */
975 /* if need to update data */
976 if (p_t4t->p_update_data)
977 {
978 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP;
979
980 if (!rw_t4t_update_file ())
981 {
982 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
983 p_t4t->p_update_data = NULL;
984 }
985 }
986 else
987 {
988 p_t4t->state = RW_T4T_STATE_IDLE;
989
990 /* just finished last step of updating (updating NLEN) */
991 if (rw_cb.p_cback)
992 {
993 rw_data.status = NFC_STATUS_OK;
994
995 (*(rw_cb.p_cback)) (RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
996 RW_TRACE_DEBUG0 ("rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
997 }
998 }
999 break;
1000
1001 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1002
1003 /* if updating is not completed */
1004 if (p_t4t->rw_length > 0)
1005 {
1006 if (!rw_t4t_update_file ())
1007 {
1008 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1009 p_t4t->p_update_data = NULL;
1010 }
1011 }
1012 else
1013 {
1014 p_t4t->p_update_data = NULL;
1015
1016 /* update NLEN as last step of updating file */
1017 if (!rw_t4t_update_nlen (p_t4t->ndef_length))
1018 {
1019 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1020 }
1021 else
1022 {
1023 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1024 }
1025 }
1026 break;
1027
1028 default:
1029 RW_TRACE_ERROR1 ("rw_t4t_sm_update_ndef (): unknown sub_state = %d", p_t4t->sub_state);
1030 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1031 break;
1032 }
1033 }
1034
1035 /*******************************************************************************
1036 **
1037 ** Function rw_t4t_sm_set_readonly
1038 **
1039 ** Description State machine for CC update procedure
1040 **
1041 ** Returns none
1042 **
1043 *******************************************************************************/
rw_t4t_sm_set_readonly(BT_HDR * p_r_apdu)1044 static void rw_t4t_sm_set_readonly (BT_HDR *p_r_apdu)
1045 {
1046 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
1047 UINT8 *p;
1048 UINT16 status_words;
1049 tRW_DATA rw_data;
1050
1051 #if (BT_TRACE_VERBOSE == TRUE)
1052 RW_TRACE_DEBUG2 ("rw_t4t_sm_set_readonly (): sub_state:%s (%d)",
1053 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state);
1054 #else
1055 RW_TRACE_DEBUG1 ("rw_t4t_sm_set_readonly (): sub_state=%d", p_t4t->sub_state);
1056 #endif
1057
1058 /* Get status words */
1059 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
1060 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE);
1061 BE_STREAM_TO_UINT16 (status_words, p);
1062
1063 if (status_words != T4T_RSP_CMD_CMPLTED)
1064 {
1065 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1));
1066 return;
1067 }
1068
1069 switch (p_t4t->sub_state)
1070 {
1071 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1072
1073 /* CC file has been selected then update write access to read-only in CC file */
1074 if (!rw_t4t_update_cc_to_readonly ())
1075 {
1076 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1077 }
1078 else
1079 {
1080 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC;
1081 }
1082 break;
1083
1084 case RW_T4T_SUBSTATE_WAIT_UPDATE_CC:
1085 /* CC Updated, Select NDEF File to allow NDEF operation */
1086 p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS;
1087 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
1088
1089 if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id))
1090 {
1091 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1092 }
1093 else
1094 {
1095 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
1096 }
1097 break;
1098
1099 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1100 p_t4t->state = RW_T4T_STATE_IDLE;
1101 /* just finished last step of configuring tag read only (Selecting NDEF file CC) */
1102 if (rw_cb.p_cback)
1103 {
1104 rw_data.status = NFC_STATUS_OK;
1105
1106 RW_TRACE_DEBUG0 ("rw_t4t_sm_set_readonly (): Sent RW_T4T_SET_TO_RO_EVT");
1107 (*(rw_cb.p_cback)) (RW_T4T_SET_TO_RO_EVT, &rw_data);
1108 }
1109 break;
1110
1111 default:
1112 RW_TRACE_ERROR1 ("rw_t4t_sm_set_readonly (): unknown sub_state = %d", p_t4t->sub_state);
1113 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0);
1114 break;
1115 }
1116 }
1117
1118 /*******************************************************************************
1119 **
1120 ** Function rw_t4t_process_timeout
1121 **
1122 ** Description process timeout event
1123 **
1124 ** Returns none
1125 **
1126 *******************************************************************************/
rw_t4t_process_timeout(TIMER_LIST_ENT * p_tle)1127 void rw_t4t_process_timeout (TIMER_LIST_ENT *p_tle)
1128 {
1129 RW_TRACE_DEBUG1 ("rw_t4t_process_timeout () event=%d", p_tle->event);
1130
1131 if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE)
1132 {
1133 rw_t4t_handle_error (NFC_STATUS_TIMEOUT, 0, 0);
1134 }
1135 else
1136 {
1137 RW_TRACE_ERROR1 ("rw_t4t_process_timeout () unknown event=%d", p_tle->event);
1138 }
1139 }
1140
1141 /*******************************************************************************
1142 **
1143 ** Function rw_t4t_data_cback
1144 **
1145 ** Description This callback function receives the data from NFCC.
1146 **
1147 ** Returns none
1148 **
1149 *******************************************************************************/
rw_t4t_data_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)1150 static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
1151 {
1152 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
1153 BT_HDR *p_r_apdu;
1154 tRW_DATA rw_data;
1155
1156 #if (BT_TRACE_VERBOSE == TRUE)
1157 UINT8 begin_state = p_t4t->state;
1158 #endif
1159
1160 RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event);
1161 nfc_stop_quick_timer (&p_t4t->timer);
1162
1163 switch (event)
1164 {
1165 case NFC_DEACTIVATE_CEVT:
1166 NFC_SetStaticRfCback (NULL);
1167 p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED;
1168 return;
1169
1170 case NFC_ERROR_CEVT:
1171 rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data);
1172
1173 if (p_t4t->state != RW_T4T_STATE_IDLE)
1174 {
1175 rw_t4t_handle_error (rw_data.status, 0, 0);
1176 }
1177 else
1178 {
1179 (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data);
1180 }
1181 return;
1182
1183 case NFC_DATA_CEVT:
1184 p_r_apdu = (BT_HDR *) p_data->data.p_data;
1185 break;
1186
1187 default:
1188 return;
1189 }
1190
1191 #if (BT_TRACE_PROTOCOL == TRUE)
1192 if (p_t4t->state != RW_T4T_STATE_IDLE)
1193 DispRWT4Tags (p_r_apdu, TRUE);
1194 #endif
1195
1196 #if (BT_TRACE_VERBOSE == TRUE)
1197 RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>",
1198 rw_t4t_get_state_name (p_t4t->state), p_t4t->state);
1199 #else
1200 RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state);
1201 #endif
1202
1203 switch (p_t4t->state)
1204 {
1205 case RW_T4T_STATE_IDLE:
1206 /* Unexpected R-APDU, it should be raw frame response */
1207 /* forward to upper layer without parsing */
1208 #if (BT_TRACE_VERBOSE == TRUE)
1209 RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len, NFC_GetStatusName (p_data->data.status));
1210 #else
1211 RW_TRACE_DEBUG2 ("RW T4T Raw Frame: Len [0x%X] Status [0x%X]", p_r_apdu->len, p_data->data.status);
1212 #endif
1213 if (rw_cb.p_cback)
1214 {
1215 rw_data.raw_frame.status = p_data->data.status;
1216 rw_data.raw_frame.p_data = p_r_apdu;
1217 (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data);
1218 p_r_apdu = NULL;
1219 }
1220 else
1221 {
1222 GKI_freebuf (p_r_apdu);
1223 }
1224 break;
1225 case RW_T4T_STATE_DETECT_NDEF:
1226 rw_t4t_sm_detect_ndef (p_r_apdu);
1227 GKI_freebuf (p_r_apdu);
1228 break;
1229 case RW_T4T_STATE_READ_NDEF:
1230 rw_t4t_sm_read_ndef (p_r_apdu);
1231 /* p_r_apdu may send upper lyaer */
1232 break;
1233 case RW_T4T_STATE_UPDATE_NDEF:
1234 rw_t4t_sm_update_ndef (p_r_apdu);
1235 GKI_freebuf (p_r_apdu);
1236 break;
1237 case RW_T4T_STATE_PRESENCE_CHECK:
1238 /* if any response, send presence check with ok */
1239 rw_data.status = NFC_STATUS_OK;
1240 p_t4t->state = RW_T4T_STATE_IDLE;
1241 (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1242 GKI_freebuf (p_r_apdu);
1243 break;
1244 case RW_T4T_STATE_SET_READ_ONLY:
1245 rw_t4t_sm_set_readonly (p_r_apdu);
1246 GKI_freebuf (p_r_apdu);
1247 break;
1248 default:
1249 RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
1250 GKI_freebuf (p_r_apdu);
1251 break;
1252 }
1253
1254 #if (BT_TRACE_VERBOSE == TRUE)
1255 if (begin_state != p_t4t->state)
1256 {
1257 RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>",
1258 rw_t4t_get_state_name (begin_state),
1259 rw_t4t_get_state_name (p_t4t->state));
1260 }
1261 #endif
1262 }
1263
1264
1265 /*******************************************************************************
1266 **
1267 ** Function rw_t4t_select
1268 **
1269 ** Description Initialise T4T
1270 **
1271 ** Returns NFC_STATUS_OK if success
1272 **
1273 *******************************************************************************/
rw_t4t_select(void)1274 tNFC_STATUS rw_t4t_select (void)
1275 {
1276 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t;
1277
1278 RW_TRACE_DEBUG0 ("rw_t4t_select ()");
1279
1280 NFC_SetStaticRfCback (rw_t4t_data_cback);
1281
1282 p_t4t->state = RW_T4T_STATE_IDLE;
1283 p_t4t->version = T4T_MY_VERSION;
1284
1285 /* set it min of max R-APDU data size before reading CC file */
1286 p_t4t->cc_file.max_le = T4T_MIN_MLE;
1287
1288 /* These will be udated during NDEF detection */
1289 p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
1290 p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1291
1292 return NFC_STATUS_OK;
1293 }
1294
1295 /*******************************************************************************
1296 **
1297 ** Function RW_T4tDetectNDef
1298 **
1299 ** Description This function performs NDEF detection procedure
1300 **
1301 ** RW_T4T_NDEF_DETECT_EVT will be returned
1302 **
1303 ** Returns NFC_STATUS_OK if success
1304 ** NFC_STATUS_FAILED if T4T is busy or other error
1305 **
1306 *******************************************************************************/
RW_T4tDetectNDef(void)1307 tNFC_STATUS RW_T4tDetectNDef (void)
1308 {
1309 RW_TRACE_API0 ("RW_T4tDetectNDef ()");
1310
1311 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1312 {
1313 RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)",
1314 rw_cb.tcb.t4t.state);
1315 return NFC_STATUS_FAILED;
1316 }
1317
1318 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1319 {
1320 /* NDEF Tag application has been selected then select CC file */
1321 if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1322 {
1323 return NFC_STATUS_FAILED;
1324 }
1325 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1326 }
1327 else
1328 {
1329 /* Select NDEF Tag Application */
1330 if (!rw_t4t_select_application (rw_cb.tcb.t4t.version))
1331 {
1332 return NFC_STATUS_FAILED;
1333 }
1334 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1335 }
1336
1337 rw_cb.tcb.t4t.state = RW_T4T_STATE_DETECT_NDEF;
1338
1339 return NFC_STATUS_OK;
1340 }
1341
1342 /*******************************************************************************
1343 **
1344 ** Function RW_T4tReadNDef
1345 **
1346 ** Description This function performs NDEF read procedure
1347 ** Note: RW_T4tDetectNDef () must be called before using this
1348 **
1349 ** The following event will be returned
1350 ** RW_T4T_NDEF_READ_EVT for each segmented NDEF message
1351 ** RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF
1352 ** RW_T4T_NDEF_READ_FAIL_EVT for failure
1353 **
1354 ** Returns NFC_STATUS_OK if success
1355 ** NFC_STATUS_FAILED if T4T is busy or other error
1356 **
1357 *******************************************************************************/
RW_T4tReadNDef(void)1358 tNFC_STATUS RW_T4tReadNDef (void)
1359 {
1360 RW_TRACE_API0 ("RW_T4tReadNDef ()");
1361
1362 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1363 {
1364 RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)",
1365 rw_cb.tcb.t4t.state);
1366 return NFC_STATUS_FAILED;
1367 }
1368
1369 /* if NDEF has been detected */
1370 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1371 {
1372 /* start reading NDEF */
1373 if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE))
1374 {
1375 return NFC_STATUS_FAILED;
1376 }
1377
1378 rw_cb.tcb.t4t.state = RW_T4T_STATE_READ_NDEF;
1379 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
1380
1381 return NFC_STATUS_OK;
1382 }
1383 else
1384 {
1385 RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected");
1386 return NFC_STATUS_FAILED;
1387 }
1388 }
1389
1390 /*******************************************************************************
1391 **
1392 ** Function RW_T4tUpdateNDef
1393 **
1394 ** Description This function performs NDEF update procedure
1395 ** Note: RW_T4tDetectNDef () must be called before using this
1396 ** Updating data must not be removed until returning event
1397 **
1398 ** The following event will be returned
1399 ** RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
1400 ** RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
1401 **
1402 ** Returns NFC_STATUS_OK if success
1403 ** NFC_STATUS_FAILED if T4T is busy or other error
1404 **
1405 *******************************************************************************/
RW_T4tUpdateNDef(UINT16 length,UINT8 * p_data)1406 tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data)
1407 {
1408 RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length);
1409
1410 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1411 {
1412 RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)",
1413 rw_cb.tcb.t4t.state);
1414 return NFC_STATUS_FAILED;
1415 }
1416
1417 /* if NDEF has been detected */
1418 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1419 {
1420 /* if read-only */
1421 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1422 {
1423 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only");
1424 return NFC_STATUS_FAILED;
1425 }
1426
1427 if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE)
1428 {
1429 RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)",
1430 length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
1431 return NFC_STATUS_FAILED;
1432 }
1433
1434 /* store NDEF length and data */
1435 rw_cb.tcb.t4t.ndef_length = length;
1436 rw_cb.tcb.t4t.p_update_data = p_data;
1437
1438 rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE;
1439 rw_cb.tcb.t4t.rw_length = length;
1440
1441 /* set NLEN to 0x0000 for the first step */
1442 if (!rw_t4t_update_nlen (0x0000))
1443 {
1444 return NFC_STATUS_FAILED;
1445 }
1446
1447 rw_cb.tcb.t4t.state = RW_T4T_STATE_UPDATE_NDEF;
1448 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1449
1450 return NFC_STATUS_OK;
1451 }
1452 else
1453 {
1454 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected");
1455 return NFC_STATUS_FAILED;
1456 }
1457 }
1458
1459 /*****************************************************************************
1460 **
1461 ** Function RW_T4tPresenceCheck
1462 **
1463 ** Description
1464 ** Check if the tag is still in the field.
1465 **
1466 ** The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
1467 ** or non-presence.
1468 ** option is RW_T4T_CHK_EMPTY_I_BLOCK, use empty I block for presence check.
1469 **
1470 ** Returns
1471 ** NFC_STATUS_OK, if raw data frame sent
1472 ** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
1473 ** NFC_STATUS_FAILED: other error
1474 **
1475 *****************************************************************************/
RW_T4tPresenceCheck(UINT8 option)1476 tNFC_STATUS RW_T4tPresenceCheck (UINT8 option)
1477 {
1478 tNFC_STATUS retval = NFC_STATUS_OK;
1479 tRW_DATA evt_data;
1480 BOOLEAN status;
1481 BT_HDR *p_data;
1482
1483 RW_TRACE_API1 ("RW_T4tPresenceCheck () %d", option);
1484
1485 /* If RW_SelectTagType was not called (no conn_callback) return failure */
1486 if (!rw_cb.p_cback)
1487 {
1488 retval = NFC_STATUS_FAILED;
1489 }
1490 /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */
1491 else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED)
1492 {
1493 evt_data.status = NFC_STATUS_FAILED;
1494 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1495 }
1496 /* If command is pending, assume tag is still present */
1497 else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1498 {
1499 evt_data.status = NFC_STATUS_OK;
1500 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1501 }
1502 else
1503 {
1504 status = FALSE;
1505 if (option == RW_T4T_CHK_EMPTY_I_BLOCK)
1506 {
1507 /* use empty I block for presence check */
1508 if ((p_data = (BT_HDR *) GKI_getbuf (NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE)) != NULL)
1509 {
1510 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1511 p_data->len = 0;
1512 if (NFC_SendData (NFC_RF_CONN_ID, (BT_HDR*) p_data) == NFC_STATUS_OK)
1513 status = TRUE;
1514 }
1515 }
1516 else
1517 {
1518 /* use read binary on the given channel */
1519 rw_cb.tcb.t4t.channel = 0;
1520 if (option <= RW_T4T_CHK_READ_BINARY_CH3)
1521 rw_cb.tcb.t4t.channel = option;
1522 status = rw_t4t_read_file (0, 1, FALSE);
1523 rw_cb.tcb.t4t.channel = 0;
1524 }
1525
1526 if (status == TRUE)
1527 {
1528 rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
1529 }
1530 else
1531 {
1532 retval = NFC_STATUS_NO_BUFFERS;
1533 }
1534 }
1535
1536 return (retval);
1537 }
1538
1539 /*****************************************************************************
1540 **
1541 ** Function RW_T4tSetNDefReadOnly
1542 **
1543 ** Description This function performs NDEF read-only procedure
1544 ** Note: RW_T4tDetectNDef() must be called before using this
1545 **
1546 ** The RW_T4T_SET_TO_RO_EVT event will be returned.
1547 **
1548 ** Returns NFC_STATUS_OK if success
1549 ** NFC_STATUS_FAILED if T4T is busy or other error
1550 **
1551 *****************************************************************************/
RW_T4tSetNDefReadOnly(void)1552 tNFC_STATUS RW_T4tSetNDefReadOnly (void)
1553 {
1554 tNFC_STATUS retval = NFC_STATUS_OK;
1555 tRW_DATA evt_data;
1556
1557 RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()");
1558
1559 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1560 {
1561 RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)",
1562 rw_cb.tcb.t4t.state);
1563 return NFC_STATUS_FAILED;
1564 }
1565
1566 /* if NDEF has been detected */
1567 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1568 {
1569 /* if read-only */
1570 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1571 {
1572 RW_TRACE_API0 ("RW_T4tSetNDefReadOnly (): NDEF is already read-only");
1573
1574 evt_data.status = NFC_STATUS_OK;
1575 (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data);
1576 return (retval);
1577 }
1578
1579 /* NDEF Tag application has been selected then select CC file */
1580 if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1581 {
1582 return NFC_STATUS_FAILED;
1583 }
1584
1585 rw_cb.tcb.t4t.state = RW_T4T_STATE_SET_READ_ONLY;
1586 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1587
1588 return NFC_STATUS_OK;
1589 }
1590 else
1591 {
1592 RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected");
1593 return NFC_STATUS_FAILED;
1594 }
1595 return (retval);
1596 }
1597
1598 #if (BT_TRACE_VERBOSE == TRUE)
1599 /*******************************************************************************
1600 **
1601 ** Function rw_t4t_get_state_name
1602 **
1603 ** Description This function returns the state name.
1604 **
1605 ** NOTE conditionally compiled to save memory.
1606 **
1607 ** Returns pointer to the name
1608 **
1609 *******************************************************************************/
rw_t4t_get_state_name(UINT8 state)1610 static char *rw_t4t_get_state_name (UINT8 state)
1611 {
1612 switch (state)
1613 {
1614 case RW_T4T_STATE_NOT_ACTIVATED:
1615 return ("NOT_ACTIVATED");
1616 case RW_T4T_STATE_IDLE:
1617 return ("IDLE");
1618 case RW_T4T_STATE_DETECT_NDEF:
1619 return ("NDEF_DETECTION");
1620 case RW_T4T_STATE_READ_NDEF:
1621 return ("READ_NDEF");
1622 case RW_T4T_STATE_UPDATE_NDEF:
1623 return ("UPDATE_NDEF");
1624 case RW_T4T_STATE_PRESENCE_CHECK:
1625 return ("PRESENCE_CHECK");
1626 case RW_T4T_STATE_SET_READ_ONLY:
1627 return ("SET_READ_ONLY");
1628
1629 default:
1630 return ("???? UNKNOWN STATE");
1631 }
1632 }
1633
1634 /*******************************************************************************
1635 **
1636 ** Function rw_t4t_get_sub_state_name
1637 **
1638 ** Description This function returns the sub_state name.
1639 **
1640 ** NOTE conditionally compiled to save memory.
1641 **
1642 ** Returns pointer to the name
1643 **
1644 *******************************************************************************/
rw_t4t_get_sub_state_name(UINT8 sub_state)1645 static char *rw_t4t_get_sub_state_name (UINT8 sub_state)
1646 {
1647 switch (sub_state)
1648 {
1649 case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1650 return ("WAIT_SELECT_APP");
1651 case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1652 return ("WAIT_SELECT_CC");
1653 case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1654 return ("WAIT_CC_FILE");
1655 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1656 return ("WAIT_SELECT_NDEF_FILE");
1657 case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1658 return ("WAIT_READ_NLEN");
1659
1660 case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1661 return ("WAIT_READ_RESP");
1662 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1663 return ("WAIT_UPDATE_RESP");
1664 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1665 return ("WAIT_UPDATE_NLEN");
1666 default:
1667 return ("???? UNKNOWN SUBSTATE");
1668 }
1669 }
1670 #endif
1671
1672 #endif /* (NFC_INCLUDED == TRUE) */
1673