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 */
40 BOOLEAN mapping_aid_test_enabled = FALSE;
41 UINT8 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 *******************************************************************************/
ce_t4t_send_to_lower(BT_HDR * p_r_apdu)53 static 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 *******************************************************************************/
ce_t4t_send_status(UINT16 status)76 static 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 *******************************************************************************/
ce_t4t_select_file(UINT16 file_id)114 static 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 *******************************************************************************/
ce_t4t_read_binary(UINT16 offset,UINT8 length)162 static 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 *******************************************************************************/
ce_t4t_update_binary(UINT16 offset,UINT8 length,UINT8 * p_data)263 static 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 *******************************************************************************/
ce_t4t_set_version_in_cc(UINT8 version)347 static 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 *******************************************************************************/
ce_t4t_process_select_file_cmd(UINT8 * p_cmd)368 static 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 *******************************************************************************/
ce_t4t_process_select_app_cmd(UINT8 * p_cmd,BT_HDR * p_c_apdu)420 static 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 *******************************************************************************/
ce_t4t_process_timeout(TIMER_LIST_ENT * p_tle)564 void 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 *******************************************************************************/
ce_t4t_data_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)598 static 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 *******************************************************************************/
ce_select_t4t(void)823 tNFC_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 *******************************************************************************/
CE_T4tSetLocalNDEFMsg(BOOLEAN read_only,UINT16 ndef_msg_max,UINT16 ndef_msg_len,UINT8 * p_ndef_msg,UINT8 * p_scratch_buf)860 tNFC_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 *******************************************************************************/
CE_T4tRegisterAID(UINT8 aid_len,UINT8 * p_aid,tCE_CBACK * p_cback)946 tCE_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 *******************************************************************************/
CE_T4tDeregisterAID(tCE_T4T_AID_HANDLE aid_handle)1027 NFC_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 *******************************************************************************/
CE_T4TTestSetCC(UINT16 cc_len,UINT8 version,UINT16 max_le,UINT16 max_lc)1068 tNFC_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 *******************************************************************************/
CE_T4TTestSetNDEFCtrlTLV(UINT8 type,UINT8 length,UINT16 file_id,UINT16 max_file_size,UINT8 read_access,UINT8 write_access)1137 tNFC_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