ce_t4t.c revision a24be4f06674b2707b57904deaa0dff5a95823bd
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        GKI_freebuf (p_c_apdu);
635        ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED);
636        return;
637    }
638
639    /* Instruction Byte */
640    BE_STREAM_TO_UINT8 (instruct, p_cmd);
641
642    if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT))
643    {
644        /* P1 Byte */
645        BE_STREAM_TO_UINT8 (select_type, p_cmd);
646
647        if (select_type == T4T_CMD_P1_SELECT_BY_NAME)
648        {
649            ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu);
650            return;
651        }
652    }
653
654    /* if registered AID is selected */
655    if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED)
656    {
657        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID");
658
659        /* forward raw frame to upper layer */
660        if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID)
661        {
662            ce_data.raw_frame.status = p_data->data.status;
663            ce_data.raw_frame.p_data = p_c_apdu;
664            ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
665            p_c_apdu = NULL;
666
667            (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
668        }
669        else
670        {
671            GKI_freebuf (p_c_apdu);
672            ce_t4t_send_status (T4T_RSP_NOT_FOUND);
673        }
674    }
675    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED)
676    {
677        CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler");
678
679        /* forward raw frame to upper layer */
680        ce_data.raw_frame.status = p_data->data.status;
681        ce_data.raw_frame.p_data = p_c_apdu;
682        ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
683        p_c_apdu = NULL;
684
685        (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data);
686    }
687    else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED)
688    {
689        if (instruct == T4T_CMD_INS_SELECT)
690        {
691            /* P1 Byte is already parsed */
692            if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID)
693            {
694                ce_t4t_process_select_file_cmd (p_cmd);
695            }
696            else
697            {
698                CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type);
699                ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
700            }
701        }
702        else if (instruct == T4T_CMD_INS_READ_BINARY)
703        {
704            if (  (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
705                ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)  )
706            {
707                if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED)
708                {
709                    max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE;
710                }
711                else
712                {
713                    max_file_size = ce_cb.mem.t4t.max_file_size;
714                }
715
716                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
717                BE_STREAM_TO_UINT8 (length, p_cmd); /* Le     */
718
719                /* check if valid parameters */
720                if (length <= CE_T4T_MAX_LE)
721                {
722                    /* CE allows to read more than current file size but not max file size */
723                    if (length + offset > max_file_size)
724                    {
725                        if (offset < max_file_size)
726                        {
727                            length = (UINT8) (max_file_size - offset);
728
729                            CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)",
730                                              length, max_file_size);
731                        }
732                        else
733                        {
734                            CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)",
735                                              offset, max_file_size);
736                            length = 0;
737                        }
738                    }
739                }
740                else
741                {
742                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)",
743                                      length, CE_T4T_MAX_LE);
744                    length = 0;
745                }
746
747                if (length > 0)
748                    ce_t4t_read_binary (offset, length);
749                else
750                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
751            }
752            else
753            {
754                CE_TRACE_ERROR0 ("CET4T: File has not been selected");
755                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
756            }
757        }
758        else if (instruct == T4T_CMD_INS_UPDATE_BINARY)
759        {
760            if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY)
761            {
762                CE_TRACE_ERROR0 ("CET4T: No access right");
763                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
764            }
765            else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)
766            {
767                BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */
768                BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc     */
769
770                /* check if valid parameters */
771                if (length <= CE_T4T_MAX_LC)
772                {
773                    if (length + offset > ce_cb.mem.t4t.max_file_size)
774                    {
775                        CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)",
776                                          length, offset, ce_cb.mem.t4t.max_file_size);
777                        length = 0;
778                    }
779                }
780                else
781                {
782                    CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)",
783                                      length, CE_T4T_MAX_LC);
784                    length = 0;
785                }
786
787                if (length > 0)
788                    ce_t4t_update_binary (offset, length, p_cmd);
789                else
790                    ce_t4t_send_status (T4T_RSP_WRONG_PARAMS);
791            }
792            else
793            {
794                CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected");
795                ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
796            }
797        }
798        else
799        {
800            CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct);
801            ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED);
802        }
803    }
804    else
805    {
806        CE_TRACE_ERROR0 ("CET4T: Application has not been selected");
807        ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED);
808    }
809
810    if (p_c_apdu)
811        GKI_freebuf (p_c_apdu);
812}
813
814/*******************************************************************************
815**
816** Function         ce_select_t4t
817**
818** Description      Select Type 4 Tag
819**
820** Returns          NFC_STATUS_OK if success
821**
822*******************************************************************************/
823tNFC_STATUS ce_select_t4t (void)
824{
825    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
826
827    CE_TRACE_DEBUG0 ("ce_select_t4t ()");
828
829    nfc_stop_quick_timer (&p_t4t->timer);
830
831    /* clear other than read-only flag */
832    p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
833
834    NFC_SetStaticRfCback (ce_t4t_data_cback);
835
836    return NFC_STATUS_OK;
837}
838
839/*******************************************************************************
840**
841** Function         CE_T4tSetLocalNDEFMsg
842**
843** Description      Initialise CE Type 4 Tag with mandatory NDEF message
844**
845**                  The following event may be returned
846**                      CE_T4T_UPDATE_START_EVT for starting update
847**                      CE_T4T_UPDATE_CPLT_EVT for complete update
848**                      CE_T4T_UPDATE_ABORT_EVT for failure of update
849**                      CE_T4T_RAW_FRAME_EVT for raw frame
850**
851**                  read_only:      TRUE if read only
852**                  ndef_msg_max:   Max NDEF message size
853**                  ndef_msg_len:   NDEF message size
854**                  p_ndef_msg:     NDEF message (excluding NLEN)
855**                  p_scratch_buf:  temp storage for update
856**
857** Returns          NFC_STATUS_OK if success
858**
859*******************************************************************************/
860tNFC_STATUS CE_T4tSetLocalNDEFMsg (BOOLEAN    read_only,
861                                   UINT16     ndef_msg_max,
862                                   UINT16     ndef_msg_len,
863                                   UINT8      *p_ndef_msg,
864                                   UINT8      *p_scratch_buf)
865{
866    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
867    UINT8       *p;
868
869    CE_TRACE_API3 ("CE_T4tSetLocalNDEFMsg () read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d",
870                   read_only, ndef_msg_max, ndef_msg_len);
871
872    if (!p_ndef_msg)
873    {
874        p_t4t->p_ndef_msg = NULL;
875
876        CE_TRACE_DEBUG0 ("CE_T4tSetLocalNDEFMsg (): T4T is disabled");
877        return NFC_STATUS_OK;
878    }
879
880    if ((!read_only) && (!p_scratch_buf))
881    {
882        CE_TRACE_ERROR0 ("CE_T4tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only");
883        return NFC_STATUS_FAILED;
884    }
885
886#if (CE_TEST_INCLUDED == TRUE)
887    mapping_aid_test_enabled = FALSE;
888#endif
889
890    /* Initialise CC file */
891    p = p_t4t->cc_file;
892
893    UINT16_TO_BE_STREAM (p, T4T_CC_FILE_MIN_LEN);
894    UINT8_TO_BE_STREAM (p, T4T_MY_VERSION);
895    UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LE);
896    UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LC);
897
898    /* Mandatory NDEF File Control TLV */
899    UINT8_TO_BE_STREAM (p, T4T_NDEF_FILE_CONTROL_TYPE);            /* type */
900    UINT8_TO_BE_STREAM (p, T4T_FILE_CONTROL_LENGTH);               /* length */
901    UINT16_TO_BE_STREAM (p, CE_T4T_MANDATORY_NDEF_FILE_ID);         /* file ID */
902    UINT16_TO_BE_STREAM (p, ndef_msg_max + T4T_FILE_LENGTH_SIZE);   /* max NDEF file size */
903    UINT8_TO_BE_STREAM (p, T4T_FC_READ_ACCESS);                    /* read access */
904
905    if (read_only)
906    {
907        UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS);    /* read only */
908        p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
909    }
910    else
911    {
912        UINT8_TO_BE_STREAM (p, T4T_FC_WRITE_ACCESS);       /* write access */
913        p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_READ_ONLY);
914    }
915
916    /* set mandatory NDEF file */
917    p_t4t->p_ndef_msg    = p_ndef_msg;
918    p_t4t->nlen          = ndef_msg_len;
919    p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE;
920
921    /* Initialize scratch buffer */
922    p_t4t->p_scratch_buf = p_scratch_buf;
923
924    if (p_scratch_buf)
925    {
926        memcpy (p_scratch_buf, p_ndef_msg, ndef_msg_len);
927    }
928
929    return NFC_STATUS_OK;
930}
931
932/*******************************************************************************
933**
934** Function         CE_T4tRegisterAID
935**
936** Description      Register AID in CE T4T
937**
938**                  aid_len: length of AID (up to NFC_MAX_AID_LEN)
939**                  p_aid:   AID
940**                  p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT
941**
942** Returns          tCE_T4T_AID_HANDLE if successful,
943**                  CE_T4T_AID_HANDLE_INVALID otherwisse
944**
945*******************************************************************************/
946tCE_T4T_AID_HANDLE CE_T4tRegisterAID (UINT8 aid_len, UINT8 *p_aid, tCE_CBACK *p_cback)
947{
948    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
949    UINT8       xx;
950
951    /* Handle registering callback for wildcard AID (all AIDs) */
952    if (aid_len == 0)
953    {
954        CE_TRACE_API0 ("CE_T4tRegisterAID (): registering callback for wildcard AID ");
955
956        /* Check if a wildcard callback is already registered (only one is allowed) */
957        if (p_t4t->p_wildcard_aid_cback != NULL)
958        {
959            CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): only one wildcard AID can be registered at time.");
960            return CE_T4T_AID_HANDLE_INVALID;
961        }
962
963        CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered (for wildcard AID)", CE_T4T_WILDCARD_AID_HANDLE);
964        p_t4t->p_wildcard_aid_cback = p_cback;
965        return CE_T4T_WILDCARD_AID_HANDLE;
966    }
967
968
969    CE_TRACE_API5 ("CE_T4tRegisterAID () AID [%02X%02X%02X%02X...], %d bytes",
970                   *p_aid, *(p_aid+1), *(p_aid+2), *(p_aid+3), aid_len);
971
972    if (aid_len > NFC_MAX_AID_LEN)
973    {
974        CE_TRACE_ERROR1 ("CE_T4tRegisterAID (): AID is up to %d bytes", NFC_MAX_AID_LEN);
975        return CE_T4T_AID_HANDLE_INVALID;
976    }
977
978    if (p_cback == NULL)
979    {
980        CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): callback must be provided");
981        return CE_T4T_AID_HANDLE_INVALID;
982    }
983
984    for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++)
985    {
986        if (  (p_t4t->reg_aid[xx].aid_len == aid_len)
987            &&(!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len)))  )
988        {
989            CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): already registered");
990            return CE_T4T_AID_HANDLE_INVALID;
991        }
992    }
993
994    for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++)
995    {
996        if (p_t4t->reg_aid[xx].aid_len == 0)
997        {
998            p_t4t->reg_aid[xx].aid_len = aid_len;
999            p_t4t->reg_aid[xx].p_cback = p_cback;
1000            memcpy (p_t4t->reg_aid[xx].aid, p_aid, aid_len);
1001            break;
1002        }
1003    }
1004
1005    if (xx >= CE_T4T_MAX_REG_AID)
1006    {
1007        CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): No resource");
1008        return CE_T4T_AID_HANDLE_INVALID;
1009    }
1010    else
1011    {
1012        CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered", xx);
1013    }
1014
1015    return (xx);
1016}
1017
1018/*******************************************************************************
1019**
1020** Function         CE_T4tDeregisterAID
1021**
1022** Description      Deregister AID in CE T4T
1023**
1024** Returns          NFC_STATUS_OK if success
1025**
1026*******************************************************************************/
1027NFC_API extern void CE_T4tDeregisterAID (tCE_T4T_AID_HANDLE aid_handle)
1028{
1029    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1030
1031    CE_TRACE_API1 ("CE_T4tDeregisterAID () handle 0x%02x", aid_handle);
1032
1033    /* Check if deregistering wildcard AID */
1034    if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE)
1035    {
1036        if (p_t4t->p_wildcard_aid_cback != NULL)
1037        {
1038            p_t4t->p_wildcard_aid_cback = NULL;
1039        }
1040        else
1041        {
1042            CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle");
1043        }
1044        return;
1045    }
1046
1047    /* Deregister AID */
1048    if ((aid_handle >= CE_T4T_MAX_REG_AID) || (p_t4t->reg_aid[aid_handle].aid_len==0))
1049    {
1050        CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle");
1051    }
1052    else
1053    {
1054        p_t4t->reg_aid[aid_handle].aid_len = 0;
1055        p_t4t->reg_aid[aid_handle].p_cback = NULL;
1056    }
1057}
1058
1059/*******************************************************************************
1060**
1061** Function         CE_T4TTestSetCC
1062**
1063** Description      Set fields in Capability Container File for testing
1064**
1065** Returns          NFC_STATUS_OK if success
1066**
1067*******************************************************************************/
1068tNFC_STATUS CE_T4TTestSetCC (UINT16 cc_len,
1069                             UINT8  version,
1070                             UINT16 max_le,
1071                             UINT16 max_lc)
1072{
1073#if (CE_TEST_INCLUDED == TRUE)
1074    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1075    UINT8       *p;
1076
1077    CE_TRACE_DEBUG4 ("CE_T4TTestSetCC (): CCLen:0x%04X, Ver:0x%02X, MaxLe:0x%04X, MaxLc:0x%04X",
1078                      cc_len, version, max_le, max_lc);
1079
1080    /* CC file */
1081    p = p_t4t->cc_file;
1082
1083    if (cc_len != 0xFFFF)
1084    {
1085        UINT16_TO_BE_STREAM (p, cc_len);
1086    }
1087    else
1088        p += 2;
1089
1090    if (version != 0xFF)
1091    {
1092        mapping_aid_test_enabled = TRUE;
1093        if (version == T4T_VERSION_1_0)
1094            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x00;
1095        else if (version == T4T_VERSION_2_0)
1096            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x01;
1097        else /* Undefined version */
1098            ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0xFF;
1099
1100        UINT8_TO_BE_STREAM (p, version);
1101    }
1102    else
1103    {
1104        mapping_aid_test_enabled = FALSE;
1105        p += 1;
1106    }
1107
1108    if (max_le != 0xFFFF)
1109    {
1110        UINT16_TO_BE_STREAM (p, max_le);
1111    }
1112    else
1113        p += 2;
1114
1115    if (max_lc != 0xFFFF)
1116    {
1117        UINT16_TO_BE_STREAM (p, max_lc);
1118    }
1119    else
1120        p += 2;
1121
1122    return NFC_STATUS_OK;
1123#else
1124    return NFC_STATUS_FAILED;
1125#endif
1126}
1127
1128/*******************************************************************************
1129**
1130** Function         CE_T4TTestSetNDEFCtrlTLV
1131**
1132** Description      Set fields in NDEF File Control TLV for testing
1133**
1134** Returns          NFC_STATUS_OK if success
1135**
1136*******************************************************************************/
1137tNFC_STATUS CE_T4TTestSetNDEFCtrlTLV (UINT8  type,
1138                                      UINT8  length,
1139                                      UINT16 file_id,
1140                                      UINT16 max_file_size,
1141                                      UINT8  read_access,
1142                                      UINT8  write_access)
1143{
1144#if (CE_TEST_INCLUDED == TRUE)
1145    tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t;
1146    UINT8       *p;
1147
1148    CE_TRACE_DEBUG6 ("CE_T4TTestSetNDEFCtrlTLV (): type:0x%02X, len:0x%02X, FileID:0x%04X, MaxFile:0x%04X, RdAcc:0x%02X, WrAcc:0x%02X",
1149                      type, length, file_id, max_file_size, read_access, write_access);
1150
1151    /* NDEF File control TLV */
1152    p = p_t4t->cc_file + T4T_FC_TLV_OFFSET_IN_CC;
1153
1154    if (type != 0xFF)
1155    {
1156        UINT8_TO_BE_STREAM (p, type);
1157    }
1158    else
1159        p += 1;
1160
1161    if (length != 0xFF)
1162    {
1163        UINT8_TO_BE_STREAM (p, length);
1164    }
1165    else
1166        p += 1;
1167
1168    if (file_id != 0xFFFF)
1169    {
1170        UINT16_TO_BE_STREAM (p, file_id);
1171    }
1172    else
1173        p += 2;
1174
1175    if (max_file_size != 0xFFFF)
1176    {
1177        UINT16_TO_BE_STREAM (p, max_file_size);
1178    }
1179    else
1180        p += 2;
1181
1182    if (read_access != 0xFF)
1183    {
1184        UINT8_TO_BE_STREAM (p, read_access);
1185    }
1186    else
1187        p += 1;
1188
1189    if (write_access != 0xFF)
1190    {
1191        UINT8_TO_BE_STREAM (p, write_access);
1192    }
1193    else
1194        p += 1;
1195
1196    return NFC_STATUS_OK;
1197#else
1198    return NFC_STATUS_FAILED;
1199#endif
1200}
1201#endif /* NFC_INCLUDED == TRUE */
1202