• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2013 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);
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     DispRWT4Tags (p_r_apdu, TRUE);
1193 #endif
1194 
1195 #if (BT_TRACE_VERBOSE == TRUE)
1196     RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>",
1197                         rw_t4t_get_state_name (p_t4t->state), p_t4t->state);
1198 #else
1199     RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state);
1200 #endif
1201 
1202     switch (p_t4t->state)
1203     {
1204     case RW_T4T_STATE_IDLE:
1205         /* Unexpected R-APDU, it should be raw frame response */
1206         /* forward to upper layer without parsing */
1207         if (rw_cb.p_cback)
1208         {
1209             rw_data.raw_frame.status = NFC_STATUS_OK;
1210             rw_data.raw_frame.p_data = p_r_apdu;
1211             (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data);
1212             p_r_apdu = NULL;
1213         }
1214         else
1215         {
1216             GKI_freebuf (p_r_apdu);
1217         }
1218         break;
1219     case RW_T4T_STATE_DETECT_NDEF:
1220         rw_t4t_sm_detect_ndef (p_r_apdu);
1221         GKI_freebuf (p_r_apdu);
1222         break;
1223     case RW_T4T_STATE_READ_NDEF:
1224         rw_t4t_sm_read_ndef (p_r_apdu);
1225         /* p_r_apdu may send upper lyaer */
1226         break;
1227     case RW_T4T_STATE_UPDATE_NDEF:
1228         rw_t4t_sm_update_ndef (p_r_apdu);
1229         GKI_freebuf (p_r_apdu);
1230         break;
1231     case RW_T4T_STATE_PRESENCE_CHECK:
1232         /* if any response, send presence check with ok */
1233         rw_data.status = NFC_STATUS_OK;
1234         p_t4t->state = RW_T4T_STATE_IDLE;
1235         (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data);
1236         GKI_freebuf (p_r_apdu);
1237         break;
1238     case RW_T4T_STATE_SET_READ_ONLY:
1239         rw_t4t_sm_set_readonly (p_r_apdu);
1240         GKI_freebuf (p_r_apdu);
1241         break;
1242     default:
1243         RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state);
1244         GKI_freebuf (p_r_apdu);
1245         break;
1246     }
1247 
1248 #if (BT_TRACE_VERBOSE == TRUE)
1249     if (begin_state != p_t4t->state)
1250     {
1251         RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>",
1252                           rw_t4t_get_state_name (begin_state),
1253                           rw_t4t_get_state_name (p_t4t->state));
1254     }
1255 #endif
1256 }
1257 
1258 
1259 /*******************************************************************************
1260 **
1261 ** Function         rw_t4t_select
1262 **
1263 ** Description      Initialise T4T
1264 **
1265 ** Returns          NFC_STATUS_OK if success
1266 **
1267 *******************************************************************************/
rw_t4t_select(void)1268 tNFC_STATUS rw_t4t_select (void)
1269 {
1270     tRW_T4T_CB  *p_t4t = &rw_cb.tcb.t4t;
1271 
1272     RW_TRACE_DEBUG0 ("rw_t4t_select ()");
1273 
1274     NFC_SetStaticRfCback (rw_t4t_data_cback);
1275 
1276     p_t4t->state   = RW_T4T_STATE_IDLE;
1277     p_t4t->version = T4T_MY_VERSION;
1278 
1279     /* set it min of max R-APDU data size before reading CC file */
1280     p_t4t->cc_file.max_le = T4T_MIN_MLE;
1281 
1282     /* These will be udated during NDEF detection */
1283     p_t4t->max_read_size   = T4T_MAX_LENGTH_LE;
1284     p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
1285 
1286     return NFC_STATUS_OK;
1287 }
1288 
1289 /*******************************************************************************
1290 **
1291 ** Function         RW_T4tDetectNDef
1292 **
1293 ** Description      This function performs NDEF detection procedure
1294 **
1295 **                  RW_T4T_NDEF_DETECT_EVT will be returned
1296 **
1297 ** Returns          NFC_STATUS_OK if success
1298 **                  NFC_STATUS_FAILED if T4T is busy or other error
1299 **
1300 *******************************************************************************/
RW_T4tDetectNDef(void)1301 tNFC_STATUS RW_T4tDetectNDef (void)
1302 {
1303     RW_TRACE_API0 ("RW_T4tDetectNDef ()");
1304 
1305     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1306     {
1307         RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)",
1308                           rw_cb.tcb.t4t.state);
1309         return NFC_STATUS_FAILED;
1310     }
1311 
1312     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1313     {
1314         /* NDEF Tag application has been selected then select CC file */
1315         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1316         {
1317             return NFC_STATUS_FAILED;
1318         }
1319         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1320     }
1321     else
1322     {
1323         /* Select NDEF Tag Application */
1324         if (!rw_t4t_select_application (rw_cb.tcb.t4t.version))
1325         {
1326             return NFC_STATUS_FAILED;
1327         }
1328         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP;
1329     }
1330 
1331     rw_cb.tcb.t4t.state     = RW_T4T_STATE_DETECT_NDEF;
1332 
1333     return NFC_STATUS_OK;
1334 }
1335 
1336 /*******************************************************************************
1337 **
1338 ** Function         RW_T4tReadNDef
1339 **
1340 ** Description      This function performs NDEF read procedure
1341 **                  Note: RW_T4tDetectNDef () must be called before using this
1342 **
1343 **                  The following event will be returned
1344 **                      RW_T4T_NDEF_READ_EVT for each segmented NDEF message
1345 **                      RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF
1346 **                      RW_T4T_NDEF_READ_FAIL_EVT for failure
1347 **
1348 ** Returns          NFC_STATUS_OK if success
1349 **                  NFC_STATUS_FAILED if T4T is busy or other error
1350 **
1351 *******************************************************************************/
RW_T4tReadNDef(void)1352 tNFC_STATUS RW_T4tReadNDef (void)
1353 {
1354     RW_TRACE_API0 ("RW_T4tReadNDef ()");
1355 
1356     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1357     {
1358         RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)",
1359                           rw_cb.tcb.t4t.state);
1360         return NFC_STATUS_FAILED;
1361     }
1362 
1363     /* if NDEF has been detected */
1364     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1365     {
1366         /* start reading NDEF */
1367         if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE))
1368         {
1369             return NFC_STATUS_FAILED;
1370         }
1371 
1372         rw_cb.tcb.t4t.state     = RW_T4T_STATE_READ_NDEF;
1373         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP;
1374 
1375         return NFC_STATUS_OK;
1376     }
1377     else
1378     {
1379         RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected");
1380         return NFC_STATUS_FAILED;
1381     }
1382 }
1383 
1384 /*******************************************************************************
1385 **
1386 ** Function         RW_T4tUpdateNDef
1387 **
1388 ** Description      This function performs NDEF update procedure
1389 **                  Note: RW_T4tDetectNDef () must be called before using this
1390 **                        Updating data must not be removed until returning event
1391 **
1392 **                  The following event will be returned
1393 **                      RW_T4T_NDEF_UPDATE_CPLT_EVT for complete
1394 **                      RW_T4T_NDEF_UPDATE_FAIL_EVT for failure
1395 **
1396 ** Returns          NFC_STATUS_OK if success
1397 **                  NFC_STATUS_FAILED if T4T is busy or other error
1398 **
1399 *******************************************************************************/
RW_T4tUpdateNDef(UINT16 length,UINT8 * p_data)1400 tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data)
1401 {
1402     RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length);
1403 
1404     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1405     {
1406         RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)",
1407                           rw_cb.tcb.t4t.state);
1408         return NFC_STATUS_FAILED;
1409     }
1410 
1411     /* if NDEF has been detected */
1412     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1413     {
1414         /* if read-only */
1415         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1416         {
1417             RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only");
1418             return NFC_STATUS_FAILED;
1419         }
1420 
1421         if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE)
1422         {
1423             RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)",
1424                               length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
1425             return NFC_STATUS_FAILED;
1426         }
1427 
1428         /* store NDEF length and data */
1429         rw_cb.tcb.t4t.ndef_length   = length;
1430         rw_cb.tcb.t4t.p_update_data = p_data;
1431 
1432         rw_cb.tcb.t4t.rw_offset     = T4T_FILE_LENGTH_SIZE;
1433         rw_cb.tcb.t4t.rw_length     = length;
1434 
1435         /* set NLEN to 0x0000 for the first step */
1436         if (!rw_t4t_update_nlen (0x0000))
1437         {
1438             return NFC_STATUS_FAILED;
1439         }
1440 
1441         rw_cb.tcb.t4t.state     = RW_T4T_STATE_UPDATE_NDEF;
1442         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN;
1443 
1444         return NFC_STATUS_OK;
1445     }
1446     else
1447     {
1448         RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected");
1449         return NFC_STATUS_FAILED;
1450     }
1451 }
1452 
1453 /*****************************************************************************
1454 **
1455 ** Function         RW_T4tPresenceCheck
1456 **
1457 ** Description
1458 **      Check if the tag is still in the field.
1459 **
1460 **      The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence
1461 **      or non-presence.
1462 **
1463 ** Returns
1464 **      NFC_STATUS_OK, if raw data frame sent
1465 **      NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation
1466 **      NFC_STATUS_FAILED: other error
1467 **
1468 *****************************************************************************/
RW_T4tPresenceCheck(void)1469 tNFC_STATUS RW_T4tPresenceCheck (void)
1470 {
1471     tNFC_STATUS retval = NFC_STATUS_OK;
1472     tRW_DATA    evt_data;
1473 
1474     RW_TRACE_API0 ("RW_T4tPresenceCheck ()");
1475 
1476     /* If RW_SelectTagType was not called (no conn_callback) return failure */
1477     if (!rw_cb.p_cback)
1478     {
1479         retval = NFC_STATUS_FAILED;
1480     }
1481     /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */
1482     else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED)
1483     {
1484         evt_data.status = NFC_STATUS_FAILED;
1485         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1486     }
1487     /* If command is pending, assume tag is still present */
1488     else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1489     {
1490         evt_data.status = NFC_STATUS_OK;
1491         (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
1492     }
1493     else
1494     {
1495         if (rw_t4t_read_file (0, 1, FALSE))
1496         {
1497             rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK;
1498         }
1499         else
1500         {
1501             retval = NFC_STATUS_NO_BUFFERS;
1502         }
1503     }
1504 
1505     return (retval);
1506 }
1507 
1508 /*****************************************************************************
1509 **
1510 ** Function         RW_T4tSetNDefReadOnly
1511 **
1512 ** Description      This function performs NDEF read-only procedure
1513 **                  Note: RW_T4tDetectNDef() must be called before using this
1514 **
1515 **                  The RW_T4T_SET_TO_RO_EVT event will be returned.
1516 **
1517 ** Returns          NFC_STATUS_OK if success
1518 **                  NFC_STATUS_FAILED if T4T is busy or other error
1519 **
1520 *****************************************************************************/
RW_T4tSetNDefReadOnly(void)1521 tNFC_STATUS RW_T4tSetNDefReadOnly (void)
1522 {
1523     tNFC_STATUS retval = NFC_STATUS_OK;
1524     tRW_DATA    evt_data;
1525 
1526     RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()");
1527 
1528     if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE)
1529     {
1530         RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)",
1531                           rw_cb.tcb.t4t.state);
1532         return NFC_STATUS_FAILED;
1533     }
1534 
1535     /* if NDEF has been detected */
1536     if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED)
1537     {
1538         /* if read-only */
1539         if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY)
1540         {
1541             RW_TRACE_API0 ("RW_T4tSetNDefReadOnly (): NDEF is already read-only");
1542 
1543             evt_data.status = NFC_STATUS_OK;
1544             (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data);
1545             return (retval);
1546         }
1547 
1548         /* NDEF Tag application has been selected then select CC file */
1549         if (!rw_t4t_select_file (T4T_CC_FILE_ID))
1550         {
1551             return NFC_STATUS_FAILED;
1552         }
1553 
1554         rw_cb.tcb.t4t.state     = RW_T4T_STATE_SET_READ_ONLY;
1555         rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC;
1556 
1557         return NFC_STATUS_OK;
1558     }
1559     else
1560     {
1561         RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected");
1562         return NFC_STATUS_FAILED;
1563     }
1564     return (retval);
1565 }
1566 
1567 #if (BT_TRACE_VERBOSE == TRUE)
1568 /*******************************************************************************
1569 **
1570 ** Function         rw_t4t_get_state_name
1571 **
1572 ** Description      This function returns the state name.
1573 **
1574 ** NOTE             conditionally compiled to save memory.
1575 **
1576 ** Returns          pointer to the name
1577 **
1578 *******************************************************************************/
rw_t4t_get_state_name(UINT8 state)1579 static char *rw_t4t_get_state_name (UINT8 state)
1580 {
1581     switch (state)
1582     {
1583     case RW_T4T_STATE_NOT_ACTIVATED:
1584         return ("NOT_ACTIVATED");
1585     case RW_T4T_STATE_IDLE:
1586         return ("IDLE");
1587     case RW_T4T_STATE_DETECT_NDEF:
1588         return ("NDEF_DETECTION");
1589     case RW_T4T_STATE_READ_NDEF:
1590         return ("READ_NDEF");
1591     case RW_T4T_STATE_UPDATE_NDEF:
1592         return ("UPDATE_NDEF");
1593     case RW_T4T_STATE_PRESENCE_CHECK:
1594         return ("PRESENCE_CHECK");
1595     case RW_T4T_STATE_SET_READ_ONLY:
1596         return ("SET_READ_ONLY");
1597 
1598     default:
1599         return ("???? UNKNOWN STATE");
1600     }
1601 }
1602 
1603 /*******************************************************************************
1604 **
1605 ** Function         rw_t4t_get_sub_state_name
1606 **
1607 ** Description      This function returns the sub_state name.
1608 **
1609 ** NOTE             conditionally compiled to save memory.
1610 **
1611 ** Returns          pointer to the name
1612 **
1613 *******************************************************************************/
rw_t4t_get_sub_state_name(UINT8 sub_state)1614 static char *rw_t4t_get_sub_state_name (UINT8 sub_state)
1615 {
1616     switch (sub_state)
1617     {
1618     case RW_T4T_SUBSTATE_WAIT_SELECT_APP:
1619         return ("WAIT_SELECT_APP");
1620     case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
1621         return ("WAIT_SELECT_CC");
1622     case RW_T4T_SUBSTATE_WAIT_CC_FILE:
1623         return ("WAIT_CC_FILE");
1624     case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
1625         return ("WAIT_SELECT_NDEF_FILE");
1626     case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
1627         return ("WAIT_READ_NLEN");
1628 
1629     case RW_T4T_SUBSTATE_WAIT_READ_RESP:
1630         return ("WAIT_READ_RESP");
1631     case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP:
1632         return ("WAIT_UPDATE_RESP");
1633     case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN:
1634         return ("WAIT_UPDATE_NLEN");
1635     default:
1636         return ("???? UNKNOWN SUBSTATE");
1637     }
1638 }
1639 #endif
1640 
1641 #endif /* (NFC_INCLUDED == TRUE) */
1642