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