ce_t4t.c revision e9629bad30a9f478b336ab46b8e6e02f7f87af46
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 Card Emulation
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#include "nfc_api.h"
33#include "nfc_int.h"
34#include "ce_api.h"
35#include "ce_int.h"
36#include "tags_int.h"
37#include "gki.h"
38
39#if (CE_TEST_INCLUDED == TRUE) /* test only */
40BOOLEAN mapping_aid_test_enabled = FALSE;
41UINT8   ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
42#endif
43
44/*******************************************************************************
45**
46** Function         ce_t4t_send_to_lower
47**
48** Description      Send packet to lower layer
49**
50** Returns          TRUE if success
51**
52*******************************************************************************/
53static BOOLEAN ce_t4t_send_to_lower (BT_HDR *p_r_apdu)
54{
55#if (BT_TRACE_PROTOCOL == TRUE)
56    DispCET4Tags (p_r_apdu, FALSE);
57#endif
58
59    if (NFC_SendData (NFC_RF_CONN_ID, p_r_apdu) != NFC_STATUS_OK)
60    {
61        CE_TRACE_ERROR0 ("ce_t4t_send_to_lower (): NFC_SendData () failed");
62        return FALSE;
63    }
64    return TRUE;
65}
66
67/*******************************************************************************
68**
69** Function         ce_t4t_send_status
70**
71** Description      Send status on R-APDU to peer
72**
73** Returns          TRUE if success
74**
75*******************************************************************************/
76static BOOLEAN ce_t4t_send_status (UINT16 status)
77{
78    BT_HDR      *p_r_apdu;
79    UINT8       *p;
80
81    CE_TRACE_DEBUG1 ("ce_t4t_send_status (): Status:0x%04X", status);
82
83    p_r_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID);
84
85    if (!p_r_apdu)
86    {
87        CE_TRACE_ERROR0 ("ce_t4t_send_status (): Cannot allocate buffer");
88        return FALSE;
89    }
90
91    p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
92    p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
93
94    UINT16_TO_BE_STREAM (p, status);
95
96    p_r_apdu->len = T4T_RSP_STATUS_WORDS_SIZE;
97
98    if (!ce_t4t_send_to_lower (p_r_apdu))
99    {
100        return FALSE;
101    }
102    return TRUE;
103}
104
105/*******************************************************************************
106**
107** Function         ce_t4t_select_file
108**
109** Description      Select a file
110**
111** Returns          TRUE if success
112**
113*******************************************************************************/
114static BOOLEAN ce_t4t_select_file (UINT16 file_id)
115{
116    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
117
118    CE_TRACE_DEBUG1 ("ce_t4t_select_file (): FileID:0x%04X", file_id);
119
120    if (file_id == T4T_CC_FILE_ID)
121    {
122        CE_TRACE_DEBUG0 ("ce_t4t_select_file (): Select CC file");
123
124        p_t4t->status |= CE_T4T_STATUS_CC_FILE_SELECTED;
125        p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_SELECTED);
126
127        return TRUE;
128    }
129
130    if (file_id == CE_T4T_MANDATORY_NDEF_FILE_ID)
131    {
132        CE_TRACE_DEBUG3 ("ce_t4t_select_file (): NLEN:0x%04X, MaxFileSize:0x%04X, WriteAccess:%s",
133                          p_t4t->nlen,
134                          p_t4t->max_file_size,
135                          (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY ? "RW" : "RO"));
136
137        p_t4t->status |= CE_T4T_STATUS_NDEF_SELECTED;
138        p_t4t->status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED);
139
140        return TRUE;
141    }
142    else
143    {
144        CE_TRACE_ERROR1 ("ce_t4t_select_file (): Cannot find file ID (0x%04X)", file_id);
145
146        p_t4t->status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED);
147        p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_SELECTED);
148
149        return FALSE;
150    }
151}
152
153/*******************************************************************************
154**
155** Function         ce_t4t_read_binary
156**
157** Description      Read data from selected file and send R-APDU to peer
158**
159** Returns          TRUE if success
160**
161*******************************************************************************/
162static BOOLEAN ce_t4t_read_binary (UINT16 offset, UINT8 length)
163{
164    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
165    UINT8       *p_src = NULL, *p_dst;
166    BT_HDR      *p_r_apdu;
167
168    CE_TRACE_DEBUG3 ("ce_t4t_read_binary (): Offset:0x%04X, Length:0x%04X, selected status = 0x%02X",
169                      offset, length, p_t4t->status);
170
171    if (p_t4t->status & CE_T4T_STATUS_CC_FILE_SELECTED)
172    {
173        p_src = p_t4t->cc_file;
174    }
175    else if (p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED)
176    {
177        if (p_t4t->p_scratch_buf)
178            p_src = p_t4t->p_scratch_buf;
179        else
180            p_src = p_t4t->p_ndef_msg;
181    }
182
183    if (p_src)
184    {
185        p_r_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID);
186
187        if (!p_r_apdu)
188        {
189            CE_TRACE_ERROR0 ("ce_t4t_read_binary (): Cannot allocate buffer");
190            return FALSE;
191        }
192
193        p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
194        p_dst = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset;
195
196        p_r_apdu->len = length;
197
198        /* add NLEN before NDEF message and adjust offset             */
199        /* if NDEF file is selected and offset < T4T_FILE_LENGTH_SIZE */
200        if ((p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED) && (length > 0))
201        {
202            if (offset == 0)
203            {
204                UINT16_TO_BE_STREAM (p_dst, p_t4t->nlen);
205
206                if (length == 1)
207                {
208                    length = 0;
209                    p_dst--;
210                }
211                else /* length >= 2 */
212                    length -= T4T_FILE_LENGTH_SIZE;
213            }
214            else if (offset == 1)
215            {
216                UINT8_TO_BE_STREAM (p_dst, (UINT8) (p_t4t->nlen));
217
218                offset = 0;
219                length--;
220            }
221            else
222            {
223                offset -= T4T_FILE_LENGTH_SIZE;
224            }
225        }
226
227        if (length > 0)
228        {
229            memcpy (p_dst, p_src + offset, length);
230            p_dst += length;
231        }
232
233        UINT16_TO_BE_STREAM (p_dst, T4T_RSP_CMD_CMPLTED);
234        p_r_apdu->len += T4T_RSP_STATUS_WORDS_SIZE;
235
236        if (!ce_t4t_send_to_lower (p_r_apdu))
237        {
238            return FALSE;
239        }
240        return TRUE;
241    }
242    else
243    {
244        CE_TRACE_ERROR0 ("ce_t4t_read_binary (): No selected file");
245
246        if (!ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED))
247        {
248            return FALSE;
249        }
250        return TRUE;
251    }
252}
253
254/*******************************************************************************
255**
256** Function         ce_t4t_update_binary
257**
258** Description      Update file and send R-APDU to peer
259**
260** Returns          TRUE if success
261**
262*******************************************************************************/
263static BOOLEAN ce_t4t_update_binary (UINT16 offset, UINT8 length, UINT8 *p_data)
264{
265    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
266    UINT8       *p;
267    UINT8        file_length[2];
268    UINT16       starting_offset;
269    tCE_DATA     ce_data;
270
271    CE_TRACE_DEBUG3 ("ce_t4t_update_binary (): Offset:0x%04X, Length:0x%04X, selected status = 0x%02X",
272                      offset, length, p_t4t->status);
273
274    starting_offset = offset;
275
276    /* update file size (NLEN) */
277    if ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0))
278    {
279        p = file_length;
280        UINT16_TO_BE_STREAM (p, p_t4t->nlen);
281
282        while ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0))
283        {
284            *(file_length + offset++) = *(p_data++);
285            length--;
286        }
287
288        p = file_length;
289        BE_STREAM_TO_UINT16 (p_t4t->nlen, p);
290    }
291
292    if (length > 0)
293        memcpy (p_t4t->p_scratch_buf + offset - T4T_FILE_LENGTH_SIZE, p_data, length);
294
295    /* if this is the last step: writing non-zero length in NLEN */
296    if ((starting_offset == 0) && (p_t4t->nlen > 0))
297    {
298        nfc_stop_quick_timer (&p_t4t->timer);
299
300        if (ce_cb.p_cback)
301        {
302            ce_data.update_info.status = NFC_STATUS_OK;
303            ce_data.update_info.length = p_t4t->nlen;
304            ce_data.update_info.p_data = p_t4t->p_scratch_buf;
305
306            (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_CPLT_EVT, &ce_data);
307            CE_TRACE_DEBUG0 ("ce_t4t_update_binary (): Sent CE_T4T_NDEF_UPDATE_CPLT_EVT");
308        }
309
310        p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_UPDATING);
311    }
312    else if (!(p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING))
313    {
314        /* starting of updating */
315        p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_UPDATING;
316
317        nfc_start_quick_timer (&p_t4t->timer, NFC_TTYPE_CE_T4T_UPDATE,
318                               (CE_T4T_TOUT_UPDATE * QUICK_TIMER_TICKS_PER_SEC) / 1000);
319
320        if (ce_cb.p_cback)
321            (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_START_EVT, NULL);
322    }
323
324    if (!ce_t4t_send_status (T4T_RSP_CMD_CMPLTED))
325    {
326        return FALSE;
327    }
328    else
329    {
330        return TRUE;
331    }
332}
333
334/*******************************************************************************
335**
336** Function         ce_t4t_set_version_in_cc
337**
338** Description      update version in CC file
339**                  If reader selects NDEF Tag Application with V1.0 AID then
340**                  set V1.0 into CC file.
341**                  If reader selects NDEF Tag Application with V2.0 AID then
342**                  set V2.0 into CC file.
343**
344** Returns          None
345**
346*******************************************************************************/
347static void ce_t4t_set_version_in_cc (UINT8 version)
348{
349    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
350    UINT8       *p;
351
352    CE_TRACE_DEBUG1 ("ce_t4t_set_version_in_cc (): version = 0x%02X", version);
353
354    p = p_t4t->cc_file + T4T_VERSION_OFFSET_IN_CC;
355
356    UINT8_TO_BE_STREAM (p, version);
357}
358
359/*******************************************************************************
360**
361** Function         ce_t4t_process_select_file_cmd
362**
363** Description      This function processes Select Command by file ID.
364**
365** Returns          TRUE if success
366**
367*******************************************************************************/
368static BOOLEAN ce_t4t_process_select_file_cmd (UINT8 *p_cmd)
369{
370    UINT8  data_len;
371    UINT16 file_id, status_words;
372
373    CE_TRACE_DEBUG0 ("ce_t4t_process_select_file_cmd ()");
374
375    p_cmd++; /* skip P2 */
376
377    /* Lc Byte */
378    BE_STREAM_TO_UINT8 (data_len, p_cmd);
379
380    if (data_len == T4T_FILE_ID_SIZE)
381    {
382        /* File ID */
383        BE_STREAM_TO_UINT16 (file_id, p_cmd);
384
385        if (ce_t4t_select_file (file_id))
386        {
387            status_words = T4T_RSP_CMD_CMPLTED;
388        }
389        else
390        {
391            status_words = T4T_RSP_NOT_FOUND;
392        }
393    }
394    else
395    {
396        status_words = T4T_RSP_WRONG_LENGTH;
397    }
398
399    if (!ce_t4t_send_status (status_words))
400    {
401        return FALSE;
402    }
403
404    if (status_words == T4T_RSP_CMD_CMPLTED)
405    {
406        return TRUE;
407    }
408    return FALSE;
409}
410
411/*******************************************************************************
412**
413** Function         ce_t4t_process_select_app_cmd
414**
415** Description      This function processes Select Command by AID.
416**
417** Returns          none
418**
419*******************************************************************************/
420static void ce_t4t_process_select_app_cmd (UINT8 *p_cmd, BT_HDR *p_c_apdu)
421{
422    UINT8    data_len;
423    UINT16   status_words = 0x0000; /* invalid status words */
424    tCE_DATA ce_data;
425    UINT8    xx;
426
427    CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd ()");
428
429    p_cmd++; /* skip P2 */
430
431    /* Lc Byte */
432    BE_STREAM_TO_UINT8 (data_len, p_cmd);
433
434#if (CE_TEST_INCLUDED == TRUE)
435    if (mapping_aid_test_enabled)
436    {
437        if (  (data_len == T4T_V20_NDEF_TAG_AID_LEN)
438            &&(!memcmp(p_cmd, ce_test_tag_app_id, data_len))
439            &&(ce_cb.mem.t4t.p_ndef_msg)  )
440        {
441            GKI_freebuf (p_c_apdu);
442            ce_t4t_send_status ((UINT16) T4T_RSP_CMD_CMPLTED);
443            return;
444        }
445    }
446#endif
447
448    /*
449    ** Compare AIDs registered by applications
450    ** if found, use callback of the application
451    ** otherwise, return error and maintain the same status
452    */
453    ce_cb.mem.t4t.selected_aid_idx = CE_T4T_MAX_REG_AID;
454    for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++)
455    {
456        if (  (ce_cb.mem.t4t.reg_aid[xx].aid_len > 0)
457            &&(ce_cb.mem.t4t.reg_aid[xx].aid_len == data_len)
458            &&(!(memcmp(ce_cb.mem.t4t.reg_aid[xx].aid, p_cmd, data_len)))  )
459        {
460            ce_cb.mem.t4t.selected_aid_idx = xx;
461            break;
462        }
463    }
464
465    /* if found matched AID */
466    if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID)
467    {
468        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED);
469        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED);
470        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_T4T_APP_SELECTED);
471        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_WILDCARD_AID_SELECTED);
472        ce_cb.mem.t4t.status |= CE_T4T_STATUS_REG_AID_SELECTED;
473
474        CE_TRACE_DEBUG4 ("ce_t4t_process_select_app_cmd (): Registered AID[%02X%02X%02X%02X...] is selected",
475                         ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[0],
476                         ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[1],
477                         ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[2],
478                         ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[3]);
479
480        ce_data.raw_frame.status = NFC_STATUS_OK;
481        ce_data.raw_frame.p_data = p_c_apdu;
482        ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
483
484        p_c_apdu = NULL;
485
486        (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
487    }
488    else if (  (data_len == T4T_V20_NDEF_TAG_AID_LEN)
489             &&(!memcmp(p_cmd, t4t_v20_ndef_tag_aid, data_len - 1))
490             &&(ce_cb.mem.t4t.p_ndef_msg)  )
491    {
492        p_cmd += data_len - 1;
493
494        /* adjust version if possible */
495        if ((*p_cmd) == 0x00)
496        {
497            ce_t4t_set_version_in_cc (T4T_VERSION_1_0);
498            status_words = T4T_RSP_CMD_CMPLTED;
499        }
500        else if ((*p_cmd) == 0x01)
501        {
502            ce_t4t_set_version_in_cc (T4T_VERSION_2_0);
503            status_words = T4T_RSP_CMD_CMPLTED;
504        }
505        else
506        {
507            CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): Not found matched AID");
508            status_words = T4T_RSP_NOT_FOUND;
509        }
510    }
511    else if (ce_cb.mem.t4t.p_wildcard_aid_cback)
512    {
513        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED);
514        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED);
515        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_T4T_APP_SELECTED);
516        ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_REG_AID_SELECTED);
517        ce_cb.mem.t4t.status |= CE_T4T_STATUS_WILDCARD_AID_SELECTED;
518
519        ce_data.raw_frame.status = NFC_STATUS_OK;
520        ce_data.raw_frame.p_data = p_c_apdu;
521        ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
522        p_c_apdu = NULL;
523
524        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame (SELECT APP) to wildcard AID handler");
525        (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
526    }
527    else
528    {
529        CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): Not found matched AID or not listening T4T NDEF");
530        status_words = T4T_RSP_NOT_FOUND;
531    }
532
533    if (status_words)
534    {
535        /* if T4T CE can support */
536        if (status_words == T4T_RSP_CMD_CMPLTED)
537        {
538            ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED);
539            ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED);
540            ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_REG_AID_SELECTED);
541            ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_WILDCARD_AID_SELECTED);
542            ce_cb.mem.t4t.status |= CE_T4T_STATUS_T4T_APP_SELECTED;
543
544            CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): T4T CE App selected");
545        }
546
547        ce_t4t_send_status (status_words);
548        GKI_freebuf (p_c_apdu);
549    }
550    /* if status_words is not set then upper layer will send R-APDU */
551
552    return;
553}
554
555/*******************************************************************************
556**
557** Function         ce_t4t_process_timeout
558**
559** Description      process timeout event
560**
561** Returns          none
562**
563*******************************************************************************/
564void ce_t4t_process_timeout (TIMER_LIST_ENT *p_tle)
565{
566    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
567    tCE_DATA     ce_data;
568
569    CE_TRACE_DEBUG1 ("ce_t4t_process_timeout () event=%d", p_tle->event);
570
571    if (p_tle->event == NFC_TTYPE_CE_T4T_UPDATE)
572    {
573        if (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING)
574        {
575            ce_data.status = NFC_STATUS_TIMEOUT;
576
577            if (ce_cb.p_cback)
578                (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_ABORT_EVT, &ce_data);
579
580            p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_UPDATING);
581        }
582    }
583    else
584    {
585        CE_TRACE_ERROR1 ("ce_t4t_process_timeout () unknown event=%d", p_tle->event);
586    }
587}
588
589/*******************************************************************************
590**
591** Function         ce_t4t_data_cback
592**
593** Description      This callback function receives the data from NFCC.
594**
595** Returns          none
596**
597*******************************************************************************/
598static void ce_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
599{
600    BT_HDR  *p_c_apdu;
601    UINT8   *p_cmd;
602    UINT8    cla, instruct, select_type = 0, length;
603    UINT16   offset, max_file_size;
604    tCE_DATA ce_data;
605
606    if (event == NFC_DEACTIVATE_CEVT)
607    {
608        NFC_SetStaticRfCback (NULL);
609        return;
610    }
611    if (event != NFC_DATA_CEVT)
612    {
613        return;
614    }
615
616    p_c_apdu = (BT_HDR *) p_data->data.p_data;
617
618#if (BT_TRACE_PROTOCOL == TRUE)
619    DispCET4Tags (p_c_apdu, TRUE);
620#endif
621
622    CE_TRACE_DEBUG1 ("ce_t4t_data_cback (): conn_id = 0x%02X", conn_id);
623
624    p_cmd = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset;
625
626    /* Class Byte */
627    BE_STREAM_TO_UINT8 (cla, p_cmd);
628
629    /* Don't check class if registered AID has been selected */
630    if (  (cla != T4T_CMD_CLASS)
631        &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0)
632        &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) == 0)
633       )
634    {
635        CE_TRACE_ERROR1 ("CET4T: Unsupported Class byte (0x%02X)", cla);
636        GKI_freebuf (p_c_apdu);
637        ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED);
638        return;
639    }
640
641    /* Instruction Byte */
642    BE_STREAM_TO_UINT8 (instruct, p_cmd);
643
644    if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT))
645    {
646        /* P1 Byte */
647        BE_STREAM_TO_UINT8 (select_type, p_cmd);
648
649        if (select_type == T4T_CMD_P1_SELECT_BY_NAME)
650        {
651            ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu);
652            return;
653        }
654    }
655
656    /* if registered AID is selected */
657    if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED)
658    {
659        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID");
660
661        /* forward raw frame to upper layer */
662        if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID)
663        {
664            ce_data.raw_frame.status = NFC_STATUS_OK;
665            ce_data.raw_frame.p_data = p_c_apdu;
666            ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
667            p_c_apdu = NULL;
668
669            (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
670        }
671        else
672        {
673            GKI_freebuf (p_c_apdu);
674            ce_t4t_send_status (T4T_RSP_NOT_FOUND);
675        }
676    }
677    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED)
678    {
679        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler");
680
681        /* forward raw frame to upper layer */
682        ce_data.raw_frame.status = NFC_STATUS_OK;
683        ce_data.raw_frame.p_data = p_c_apdu;
684        ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
685        p_c_apdu = NULL;
686
687        (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
688    }
689    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED)
690    {
691        if (instruct == T4T_CMD_INS_SELECT)
692        {
693            /* P1 Byte is already parsed */
694            if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID)
695            {
696                ce_t4t_process_select_file_cmd (p_cmd);
697            }
698            else
699            {
700                CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type);
701                ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
702            }
703        }
704        else if (instruct == T4T_CMD_INS_READ_BINARY)
705        {
706            if (  (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
707                ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)  )
708            {
709                if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
710                {
711                    max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE;
712                }
713                else
714                {
715                    max_file_size = ce_cb.mem.t4t.max_file_size;
716                }
717
718                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
719                BE_STREAM_TO_UINT8 (length, p_cmd); /* Le     */
720
721                /* check if valid parameters */
722                if (length <= CE_T4T_MAX_LE)
723                {
724                    /* CE allows to read more than current file size but not max file size */
725                    if (length + offset > max_file_size)
726                    {
727                        if (offset < max_file_size)
728                        {
729                            length = (UINT8) (max_file_size - offset);
730
731                            CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)",
732                                              length, max_file_size);
733                        }
734                        else
735                        {
736                            CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)",
737                                              offset, max_file_size);
738                            length = 0;
739                        }
740                    }
741                }
742                else
743                {
744                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)",
745                                      length, CE_T4T_MAX_LE);
746                    length = 0;
747                }
748
749                if (length > 0)
750                    ce_t4t_read_binary (offset, length);
751                else
752                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
753            }
754            else
755            {
756                CE_TRACE_ERROR0 ("CET4T: File has not been selected");
757                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
758            }
759        }
760        else if (instruct == T4T_CMD_INS_UPDATE_BINARY)
761        {
762            if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY)
763            {
764                CE_TRACE_ERROR0 ("CET4T: No access right");
765                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
766            }
767            else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)
768            {
769                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
770                BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc     */
771
772                /* check if valid parameters */
773                if (length <= CE_T4T_MAX_LC)
774                {
775                    if (length + offset > ce_cb.mem.t4t.max_file_size)
776                    {
777                        CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)",
778                                          length, offset, ce_cb.mem.t4t.max_file_size);
779                        length = 0;
780                    }
781                }
782                else
783                {
784                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)",
785                                      length, CE_T4T_MAX_LC);
786                    length = 0;
787                }
788
789                if (length > 0)
790                    ce_t4t_update_binary (offset, length, p_cmd);
791                else
792                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
793            }
794            else
795            {
796                CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected");
797                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
798            }
799        }
800        else
801        {
802            CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct);
803            ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED);
804        }
805    }
806    else
807    {
808        CE_TRACE_ERROR0 ("CET4T: Application has not been selected");
809        ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
810    }
811
812    if (p_c_apdu)
813        GKI_freebuf (p_c_apdu);
814}
815
816/*******************************************************************************
817**
818** Function         ce_select_t4t
819**
820** Description      Select Type 4 Tag
821**
822** Returns          NFC_STATUS_OK if success
823**
824*******************************************************************************/
825tNFC_STATUS ce_select_t4t (void)
826{
827    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
828
829    CE_TRACE_DEBUG0 ("ce_select_t4t ()");
830
831    nfc_stop_quick_timer (&p_t4t->timer);
832
833    /* clear other than read-only flag */
834    p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
835
836    NFC_SetStaticRfCback (ce_t4t_data_cback);
837
838    return NFC_STATUS_OK;
839}
840
841/*******************************************************************************
842**
843** Function         CE_T4tSetLocalNDEFMsg
844**
845** Description      Initialise CE Type 4 Tag with mandatory NDEF message
846**
847**                  The following event may be returned
848**                      CE_T4T_UPDATE_START_EVT for starting update
849**                      CE_T4T_UPDATE_CPLT_EVT for complete update
850**                      CE_T4T_UPDATE_ABORT_EVT for failure of update
851**                      CE_T4T_RAW_FRAME_EVT for raw frame
852**
853**                  read_only:      TRUE if read only
854**                  ndef_msg_max:   Max NDEF message size
855**                  ndef_msg_len:   NDEF message size
856**                  p_ndef_msg:     NDEF message (excluding NLEN)
857**                  p_scratch_buf:  temp storage for update
858**
859** Returns          NFC_STATUS_OK if success
860**
861*******************************************************************************/
862tNFC_STATUS CE_T4tSetLocalNDEFMsg (BOOLEAN    read_only,
863                                   UINT16     ndef_msg_max,
864                                   UINT16     ndef_msg_len,
865                                   UINT8      *p_ndef_msg,
866                                   UINT8      *p_scratch_buf)
867{
868    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
869    UINT8       *p;
870
871    CE_TRACE_API3 ("CE_T4tSetLocalNDEFMsg () read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d",
872                   read_only, ndef_msg_max, ndef_msg_len);
873
874    if (!p_ndef_msg)
875    {
876        p_t4t->p_ndef_msg = NULL;
877
878        CE_TRACE_DEBUG0 ("CE_T4tSetLocalNDEFMsg (): T4T is disabled");
879        return NFC_STATUS_OK;
880    }
881
882    if ((!read_only) && (!p_scratch_buf))
883    {
884        CE_TRACE_ERROR0 ("CE_T4tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only");
885        return NFC_STATUS_FAILED;
886    }
887
888#if (CE_TEST_INCLUDED == TRUE)
889    mapping_aid_test_enabled = FALSE;
890#endif
891
892    /* Initialise CC file */
893    p = p_t4t->cc_file;
894
895    UINT16_TO_BE_STREAM (p, T4T_CC_FILE_MIN_LEN);
896    UINT8_TO_BE_STREAM (p, T4T_MY_VERSION);
897    UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LE);
898    UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LC);
899
900    /* Mandatory NDEF File Control TLV */
901    UINT8_TO_BE_STREAM (p, T4T_NDEF_FILE_CONTROL_TYPE);            /* type */
902    UINT8_TO_BE_STREAM (p, T4T_FILE_CONTROL_LENGTH);               /* length */
903    UINT16_TO_BE_STREAM (p, CE_T4T_MANDATORY_NDEF_FILE_ID);         /* file ID */
904    UINT16_TO_BE_STREAM (p, ndef_msg_max + T4T_FILE_LENGTH_SIZE);   /* max NDEF file size */
905    UINT8_TO_BE_STREAM (p, T4T_FC_READ_ACCESS);                    /* read access */
906
907    if (read_only)
908    {
909        UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS);    /* read only */
910        p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
911    }
912    else
913    {
914        UINT8_TO_BE_STREAM (p, T4T_FC_WRITE_ACCESS);       /* write access */
915        p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_READ_ONLY);
916    }
917
918    /* set mandatory NDEF file */
919    p_t4t->p_ndef_msg    = p_ndef_msg;
920    p_t4t->nlen          = ndef_msg_len;
921    p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE;
922
923    /* Initialize scratch buffer */
924    p_t4t->p_scratch_buf = p_scratch_buf;
925
926    if (p_scratch_buf)
927    {
928        memcpy (p_scratch_buf, p_ndef_msg, ndef_msg_len);
929    }
930
931    return NFC_STATUS_OK;
932}
933
934/*******************************************************************************
935**
936** Function         CE_T4tRegisterAID
937**
938** Description      Register AID in CE T4T
939**
940**                  aid_len: length of AID (up to NFC_MAX_AID_LEN)
941**                  p_aid:   AID
942**                  p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT
943**
944** Returns          tCE_T4T_AID_HANDLE if successful,
945**                  CE_T4T_AID_HANDLE_INVALID otherwisse
946**
947*******************************************************************************/
948tCE_T4T_AID_HANDLE CE_T4tRegisterAID (UINT8 aid_len, UINT8 *p_aid, tCE_CBACK *p_cback)
949{
950    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
951    UINT8       xx;
952
953    /* Handle registering callback for wildcard AID (all AIDs) */
954    if (aid_len == 0)
955    {
956        CE_TRACE_API0 ("CE_T4tRegisterAID (): registering callback for wildcard AID ");
957
958        /* Check if a wildcard callback is already registered (only one is allowed) */
959        if (p_t4t->p_wildcard_aid_cback != NULL)
960        {
961            CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): only one wildcard AID can be registered at time.");
962            return CE_T4T_AID_HANDLE_INVALID;
963        }
964
965        CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered (for wildcard AID)", CE_T4T_WILDCARD_AID_HANDLE);
966        p_t4t->p_wildcard_aid_cback = p_cback;
967        return CE_T4T_WILDCARD_AID_HANDLE;
968    }
969
970
971    CE_TRACE_API5 ("CE_T4tRegisterAID () AID [%02X%02X%02X%02X...], %d bytes",
972                   *p_aid, *(p_aid+1), *(p_aid+2), *(p_aid+3), aid_len);
973
974    if (aid_len > NFC_MAX_AID_LEN)
975    {
976        CE_TRACE_ERROR1 ("CE_T4tRegisterAID (): AID is up to %d bytes", NFC_MAX_AID_LEN);
977        return CE_T4T_AID_HANDLE_INVALID;
978    }
979
980    if (p_cback == NULL)
981    {
982        CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): callback must be provided");
983        return CE_T4T_AID_HANDLE_INVALID;
984    }
985
986    for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++)
987    {
988        if (  (p_t4t->reg_aid[xx].aid_len == aid_len)
989            &&(!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len)))  )
990        {
991            CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): already registered");
992            return CE_T4T_AID_HANDLE_INVALID;
993        }
994    }
995
996    for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++)
997    {
998        if (p_t4t->reg_aid[xx].aid_len == 0)
999        {
1000            p_t4t->reg_aid[xx].aid_len = aid_len;
1001            p_t4t->reg_aid[xx].p_cback = p_cback;
1002            memcpy (p_t4t->reg_aid[xx].aid, p_aid, aid_len);
1003            break;
1004        }
1005    }
1006
1007    if (xx >= CE_T4T_MAX_REG_AID)
1008    {
1009        CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): No resource");
1010        return CE_T4T_AID_HANDLE_INVALID;
1011    }
1012    else
1013    {
1014        CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered", xx);
1015    }
1016
1017    return (xx);
1018}
1019
1020/*******************************************************************************
1021**
1022** Function         CE_T4tDeregisterAID
1023**
1024** Description      Deregister AID in CE T4T
1025**
1026** Returns          NFC_STATUS_OK if success
1027**
1028*******************************************************************************/
1029NFC_API extern void CE_T4tDeregisterAID (tCE_T4T_AID_HANDLE aid_handle)
1030{
1031    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1032
1033    CE_TRACE_API1 ("CE_T4tDeregisterAID () handle 0x%02x", aid_handle);
1034
1035    /* Check if deregistering wildcard AID */
1036    if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE)
1037    {
1038        if (p_t4t->p_wildcard_aid_cback != NULL)
1039        {
1040            p_t4t->p_wildcard_aid_cback = NULL;
1041        }
1042        else
1043        {
1044            CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle");
1045        }
1046        return;
1047    }
1048
1049    /* Deregister AID */
1050    if ((aid_handle >= CE_T4T_MAX_REG_AID) || (p_t4t->reg_aid[aid_handle].aid_len==0))
1051    {
1052        CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle");
1053    }
1054    else
1055    {
1056        p_t4t->reg_aid[aid_handle].aid_len = 0;
1057        p_t4t->reg_aid[aid_handle].p_cback = NULL;
1058    }
1059}
1060
1061/*******************************************************************************
1062**
1063** Function         CE_T4TTestSetCC
1064**
1065** Description      Set fields in Capability Container File for testing
1066**
1067** Returns          NFC_STATUS_OK if success
1068**
1069*******************************************************************************/
1070tNFC_STATUS CE_T4TTestSetCC (UINT16 cc_len,
1071                             UINT8  version,
1072                             UINT16 max_le,
1073                             UINT16 max_lc)
1074{
1075#if (CE_TEST_INCLUDED == TRUE)
1076    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1077    UINT8       *p;
1078
1079    CE_TRACE_DEBUG4 ("CE_T4TTestSetCC (): CCLen:0x%04X, Ver:0x%02X, MaxLe:0x%04X, MaxLc:0x%04X",
1080                      cc_len, version, max_le, max_lc);
1081
1082    /* CC file */
1083    p = p_t4t->cc_file;
1084
1085    if (cc_len != 0xFFFF)
1086    {
1087        UINT16_TO_BE_STREAM (p, cc_len);
1088    }
1089    else
1090        p += 2;
1091
1092    if (version != 0xFF)
1093    {
1094        mapping_aid_test_enabled = TRUE;
1095        if (version == T4T_VERSION_1_0)
1096            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x00;
1097        else if (version == T4T_VERSION_2_0)
1098            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x01;
1099        else /* Undefined version */
1100            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0xFF;
1101
1102        UINT8_TO_BE_STREAM (p, version);
1103    }
1104    else
1105    {
1106        mapping_aid_test_enabled = FALSE;
1107        p += 1;
1108    }
1109
1110    if (max_le != 0xFFFF)
1111    {
1112        UINT16_TO_BE_STREAM (p, max_le);
1113    }
1114    else
1115        p += 2;
1116
1117    if (max_lc != 0xFFFF)
1118    {
1119        UINT16_TO_BE_STREAM (p, max_lc);
1120    }
1121    else
1122        p += 2;
1123
1124    return NFC_STATUS_OK;
1125#else
1126    return NFC_STATUS_FAILED;
1127#endif
1128}
1129
1130/*******************************************************************************
1131**
1132** Function         CE_T4TTestSetNDEFCtrlTLV
1133**
1134** Description      Set fields in NDEF File Control TLV for testing
1135**
1136** Returns          NFC_STATUS_OK if success
1137**
1138*******************************************************************************/
1139tNFC_STATUS CE_T4TTestSetNDEFCtrlTLV (UINT8  type,
1140                                      UINT8  length,
1141                                      UINT16 file_id,
1142                                      UINT16 max_file_size,
1143                                      UINT8  read_access,
1144                                      UINT8  write_access)
1145{
1146#if (CE_TEST_INCLUDED == TRUE)
1147    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1148    UINT8       *p;
1149
1150    CE_TRACE_DEBUG6 ("CE_T4TTestSetNDEFCtrlTLV (): type:0x%02X, len:0x%02X, FileID:0x%04X, MaxFile:0x%04X, RdAcc:0x%02X, WrAcc:0x%02X",
1151                      type, length, file_id, max_file_size, read_access, write_access);
1152
1153    /* NDEF File control TLV */
1154    p = p_t4t->cc_file + T4T_FC_TLV_OFFSET_IN_CC;
1155
1156    if (type != 0xFF)
1157    {
1158        UINT8_TO_BE_STREAM (p, type);
1159    }
1160    else
1161        p += 1;
1162
1163    if (length != 0xFF)
1164    {
1165        UINT8_TO_BE_STREAM (p, length);
1166    }
1167    else
1168        p += 1;
1169
1170    if (file_id != 0xFFFF)
1171    {
1172        UINT16_TO_BE_STREAM (p, file_id);
1173    }
1174    else
1175        p += 2;
1176
1177    if (max_file_size != 0xFFFF)
1178    {
1179        UINT16_TO_BE_STREAM (p, max_file_size);
1180    }
1181    else
1182        p += 2;
1183
1184    if (read_access != 0xFF)
1185    {
1186        UINT8_TO_BE_STREAM (p, read_access);
1187    }
1188    else
1189        p += 1;
1190
1191    if (write_access != 0xFF)
1192    {
1193        UINT8_TO_BE_STREAM (p, write_access);
1194    }
1195    else
1196        p += 1;
1197
1198    return NFC_STATUS_OK;
1199#else
1200    return NFC_STATUS_FAILED;
1201#endif
1202}
1203#endif /* NFC_INCLUDED == TRUE */
1204