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 3 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 enum {
40 CE_T3T_COMMAND_INVALID,
41 CE_T3T_COMMAND_NFC_FORUM,
42 CE_T3T_COMMAND_FELICA
43 };
44
45 /* T3T CE states */
46 enum {
47 CE_T3T_STATE_NOT_ACTIVATED,
48 CE_T3T_STATE_IDLE,
49 CE_T3T_STATE_UPDATING
50 };
51
52 /* Bitmasks to indicate type of UPDATE */
53 #define CE_T3T_UPDATE_FL_NDEF_UPDATE_START 0x01
54 #define CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT 0x02
55 #define CE_T3T_UPDATE_FL_UPDATE 0x04
56
57 /*******************************************************************************
58 * Static constant definitions
59 *******************************************************************************/
60 /* Default PMm param */
61 static const UINT8 CE_DEFAULT_LF_PMM[NCI_T3T_PMM_LEN] =
62 {
63 0x01, /* This PAD0 is used to identify HCE-F on Android */
64 0xFE, /* This PAD0 is used to identify HCE-F on Android */
65 0xFF,
66 0xFF,
67 0xFF,
68 0xFF,
69 0xFF,
70 0xFF
71 };
72
73 /*******************************************************************************
74 **
75 ** Function ce_t3t_init
76 **
77 ** Description Initialize tag-specific fields of ce control block
78 **
79 ** Returns none
80 **
81 *******************************************************************************/
ce_t3t_init(void)82 void ce_t3t_init (void)
83 {
84 memcpy (ce_cb.mem.t3t.local_pmm, CE_DEFAULT_LF_PMM, NCI_T3T_PMM_LEN);
85 ce_cb.mem.t3t.ndef_info.nbr = CE_T3T_DEFAULT_CHECK_MAXBLOCKS;
86 ce_cb.mem.t3t.ndef_info.nbw = CE_T3T_DEFAULT_UPDATE_MAXBLOCKS;
87 }
88
89 /*******************************************************************************
90 **
91 ** Function ce_t3t_send_to_lower
92 **
93 ** Description Send C-APDU to lower layer
94 **
95 ** Returns none
96 **
97 *******************************************************************************/
ce_t3t_send_to_lower(BT_HDR * p_msg)98 void ce_t3t_send_to_lower (BT_HDR *p_msg)
99 {
100 UINT8 *p;
101
102 /* Set NFC-F SoD field (payload len + 1) */
103 p_msg->offset -= 1; /* Point to SoD field */
104 p = (UINT8 *) (p_msg+1) + p_msg->offset;
105 UINT8_TO_STREAM (p, (p_msg->len+1));
106 p_msg->len += 1; /* Increment len to include SoD */
107
108 #if (BT_TRACE_PROTOCOL == TRUE)
109 DispT3TagMessage (p_msg, FALSE);
110 #endif
111
112 if (NFC_SendData (NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK)
113 {
114 CE_TRACE_ERROR0 ("ce_t3t_send_to_lower (): NFC_SendData () failed");
115 }
116 }
117
118 /*******************************************************************************
119 **
120 ** Function ce_t3t_is_valid_opcode
121 **
122 ** Description Valid opcode
123 **
124 ** Returns Type of command
125 **
126 *******************************************************************************/
ce_t3t_is_valid_opcode(UINT8 cmd_id)127 UINT8 ce_t3t_is_valid_opcode (UINT8 cmd_id)
128 {
129 UINT8 retval = CE_T3T_COMMAND_INVALID;
130
131 if ( (cmd_id == T3T_MSG_OPC_CHECK_CMD)
132 ||(cmd_id == T3T_MSG_OPC_UPDATE_CMD) )
133 {
134 retval = CE_T3T_COMMAND_NFC_FORUM;
135 }
136 else if ( (cmd_id == T3T_MSG_OPC_POLL_CMD)
137 ||(cmd_id == T3T_MSG_OPC_REQ_SERVICE_CMD)
138 ||(cmd_id == T3T_MSG_OPC_REQ_RESPONSE_CMD)
139 ||(cmd_id == T3T_MSG_OPC_REQ_SYSTEMCODE_CMD) )
140 {
141 retval = CE_T3T_COMMAND_FELICA;
142 }
143
144 return (retval);
145 }
146
147 /*****************************************************************************
148 **
149 ** Function ce_t3t_get_rsp_buf
150 **
151 ** Description Get a buffer for sending T3T messages
152 **
153 ** Returns BT_HDR *
154 **
155 *****************************************************************************/
ce_t3t_get_rsp_buf(void)156 BT_HDR *ce_t3t_get_rsp_buf (void)
157 {
158 BT_HDR *p_cmd_buf;
159
160 if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID)) != NULL)
161 {
162 /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */
163 p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1;
164 p_cmd_buf->len = 0;
165 }
166
167 return (p_cmd_buf);
168 }
169
170 /*******************************************************************************
171 **
172 ** Function ce_t3t_send_rsp
173 **
174 ** Description Send response to reader/writer
175 **
176 ** Returns none
177 **
178 *******************************************************************************/
ce_t3t_send_rsp(tCE_CB * p_ce_cb,UINT8 * p_nfcid2,UINT8 opcode,UINT8 status1,UINT8 status2)179 void ce_t3t_send_rsp (tCE_CB *p_ce_cb, UINT8 *p_nfcid2, UINT8 opcode, UINT8 status1, UINT8 status2)
180 {
181 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t;
182 BT_HDR *p_rsp_msg;
183 UINT8 *p_dst, *p_rsp_start;
184
185 /* If p_nfcid2 is NULL, then used activated NFCID2 */
186 if (p_nfcid2 == NULL)
187 {
188 p_nfcid2 = p_cb->local_nfcid2;
189 }
190
191 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL)
192 {
193 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset;
194
195 /* Response Code */
196 UINT8_TO_STREAM (p_dst, opcode);
197
198 /* Manufacturer ID */
199 ARRAY_TO_STREAM (p_dst, p_nfcid2, NCI_RF_F_UID_LEN);
200
201 /* Status1 and Status2 */
202 UINT8_TO_STREAM (p_dst, status1);
203 UINT8_TO_STREAM (p_dst, status2);
204
205 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start);
206 ce_t3t_send_to_lower (p_rsp_msg);
207 }
208 else
209 {
210 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message");
211 }
212 }
213
214 /*******************************************************************************
215 **
216 ** Function ce_t3t_handle_update_cmd
217 **
218 ** Description Handle UPDATE command from reader/writer
219 **
220 ** Returns none
221 **
222 *******************************************************************************/
ce_t3t_handle_update_cmd(tCE_CB * p_ce_cb,BT_HDR * p_cmd_msg)223 void ce_t3t_handle_update_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg)
224 {
225 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t;
226 UINT8 *p_temp;
227 UINT8 *p_block_list = p_cb->cur_cmd.p_block_list_start;
228 UINT8 *p_block_data = p_cb->cur_cmd.p_block_data_start;
229 UINT8 i, j, bl0;
230 UINT16 block_number, service_code, checksum, checksum_rx;
231 UINT32 newlen_hiword;
232 tCE_T3T_NDEF_INFO ndef_info;
233 tNFC_STATUS nfc_status = NFC_STATUS_OK;
234 UINT8 update_flags = 0;
235 tCE_UPDATE_INFO update_info;
236
237 /* If in idle state, notify app that update is starting */
238 if (p_cb->state == CE_T3T_STATE_IDLE)
239 {
240 p_cb->state = CE_T3T_STATE_UPDATING;
241 }
242
243 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++)
244 {
245 /* Read byte0 of block list */
246 STREAM_TO_UINT8 (bl0, p_block_list);
247
248 if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)
249 {
250 STREAM_TO_UINT8 (block_number, p_block_list);
251 }
252 else
253 {
254 STREAM_TO_UINT16 (block_number, p_block_list);
255 }
256
257 /* Read the block from memory */
258 service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK];
259
260 /* Reject UPDATE command if service code=T3T_MSG_NDEF_SC_RO */
261 if (service_code == T3T_MSG_NDEF_SC_RO)
262 {
263 /* Error: invalid block number to update */
264 CE_TRACE_ERROR0 ("CE: UPDATE request using read-only service");
265 nfc_status = NFC_STATUS_FAILED;
266 break;
267 }
268
269 /* Check for NDEF */
270 if (service_code == T3T_MSG_NDEF_SC_RW)
271 {
272 if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbw)
273 {
274 CE_TRACE_ERROR2 ("CE: Requested too many blocks to update (requested: %i, max: %i)", p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbw);
275 nfc_status = NFC_STATUS_FAILED;
276 break;
277 }
278 else if (p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RO)
279 {
280 CE_TRACE_ERROR0 ("CE: error: write-request to read-only NDEF message.");
281 nfc_status = NFC_STATUS_FAILED;
282 break;
283 }
284 else if (block_number == 0)
285 {
286 CE_TRACE_DEBUG2 ("CE: Update sc 0x%04x block %i.", service_code, block_number);
287
288 /* Special caes: NDEF block0 is the ndef attribute block */
289 p_temp = p_block_data;
290 STREAM_TO_UINT8 (ndef_info.version, p_block_data);
291 p_block_data+=8; /* Ignore nbr,nbw,maxb,and reserved (reader/writer not allowed to update this) */
292 STREAM_TO_UINT8 (ndef_info.writef, p_block_data);
293 p_block_data++; /* Ignore rwflag (reader/writer not allowed to update this) */
294 STREAM_TO_UINT8 (newlen_hiword, p_block_data);
295 BE_STREAM_TO_UINT16 (ndef_info.ln, p_block_data);
296 ndef_info.ln += (newlen_hiword<<16);
297 BE_STREAM_TO_UINT16 (checksum_rx, p_block_data);
298
299 checksum=0;
300 for (j=0; j<T3T_MSG_NDEF_ATTR_INFO_SIZE; j++)
301 {
302 checksum+=p_temp[j];
303 }
304
305 /* Compare calcuated checksum with received checksum */
306 if (checksum != checksum_rx)
307 {
308 CE_TRACE_ERROR0 ("CE: Checksum failed for NDEF attribute block.");
309 nfc_status = NFC_STATUS_FAILED;
310 }
311 else
312 {
313 /* Update NDEF attribute block (only allowed to update current length and writef fields) */
314 p_cb->ndef_info.scratch_ln = ndef_info.ln;
315 p_cb->ndef_info.scratch_writef = ndef_info.writef;
316
317 /* If writef=0 indicates completion of NDEF update */
318 if (ndef_info.writef == 0)
319 {
320 update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT;
321 }
322 /* writef=1 indicates start of NDEF update */
323 else
324 {
325 update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_START;
326 }
327 }
328 }
329 else
330 {
331 CE_TRACE_DEBUG2 ("CE: Udpate sc 0x%04x block %i.", service_code, block_number);
332
333 /* Verify that block_number is within NDEF memory */
334 if (block_number > p_cb->ndef_info.nmaxb)
335 {
336 /* Error: invalid block number to update */
337 CE_TRACE_ERROR2 ("CE: Requested invalid NDEF block number to update %i (max is %i).", block_number, p_cb->ndef_info.nmaxb);
338 nfc_status = NFC_STATUS_FAILED;
339 break;
340 }
341 else
342 {
343 /* Update NDEF memory block */
344 STREAM_TO_ARRAY ((&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), p_block_data, T3T_MSG_BLOCKSIZE);
345 }
346
347 /* Set flag to indicate that this UPDATE contained at least one block */
348 update_flags |= CE_T3T_UPDATE_FL_UPDATE;
349 }
350 }
351 else
352 {
353 /* Error: invalid service code */
354 CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code);
355 nfc_status = NFC_STATUS_FAILED;
356 break;
357 }
358 }
359
360 /* Send appropriate response to reader/writer */
361 if (nfc_status == NFC_STATUS_OK)
362 {
363 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_OK, T3T_MSG_RSP_STATUS_OK);
364 }
365 else
366 {
367 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
368 p_cb->state = CE_T3T_STATE_IDLE;
369 }
370
371
372 /* Notify the app of what got updated */
373 if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_START)
374 {
375 /* NDEF attribute got updated with WriteF=TRUE */
376 p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_START_EVT, NULL);
377 }
378
379 if (update_flags & CE_T3T_UPDATE_FL_UPDATE)
380 {
381 /* UPDATE message contained at least one non-NDEF block */
382 p_ce_cb->p_cback (CE_T3T_UPDATE_EVT, NULL);
383 }
384
385
386 if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT)
387 {
388 /* NDEF attribute got updated with WriteF=FALSE */
389 update_info.status = nfc_status;
390 update_info.p_data = p_cb->ndef_info.p_scratch_buf;
391 update_info.length = p_cb->ndef_info.scratch_ln;
392 p_cb->state = CE_T3T_STATE_IDLE;
393 p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_CPLT_EVT, (tCE_DATA *) &update_info);
394 }
395
396 GKI_freebuf (p_cmd_msg);
397 }
398
399 /*******************************************************************************
400 **
401 ** Function ce_t3t_handle_check_cmd
402 **
403 ** Description Handle CHECK command from reader/writer
404 **
405 ** Returns Nothing
406 **
407 *******************************************************************************/
ce_t3t_handle_check_cmd(tCE_CB * p_ce_cb,BT_HDR * p_cmd_msg)408 void ce_t3t_handle_check_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg)
409 {
410 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t;
411 BT_HDR *p_rsp_msg;
412 UINT8 *p_rsp_start;
413 UINT8 *p_dst, *p_temp, *p_status;
414 UINT8 *p_src = p_cb->cur_cmd.p_block_list_start;
415 UINT8 i, bl0;
416 UINT8 ndef_writef;
417 UINT32 ndef_len;
418 UINT16 block_number, service_code, checksum;
419
420 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL)
421 {
422 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset;
423
424 /* Response Code */
425 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP);
426
427 /* Manufacturer ID */
428 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
429
430 /* Save pointer to start of status field */
431 p_status = p_dst;
432
433 /* Status1 and Status2 (assume success initially */
434 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK);
435 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK);
436 UINT8_TO_STREAM (p_dst, p_cb->cur_cmd.num_blocks);
437
438 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++)
439 {
440 /* Read byte0 of block list */
441 STREAM_TO_UINT8 (bl0, p_src);
442
443 if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)
444 {
445 STREAM_TO_UINT8 (block_number, p_src);
446 }
447 else
448 {
449 STREAM_TO_UINT16 (block_number, p_src);
450 }
451
452 /* Read the block from memory */
453 service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK];
454
455 /* Check for NDEF */
456 if ((service_code == T3T_MSG_NDEF_SC_RO) || (service_code == T3T_MSG_NDEF_SC_RW))
457 {
458 /* Verify Nbr (NDEF only) */
459 if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbr)
460 {
461 /* Error: invalid number of blocks to check */
462 CE_TRACE_ERROR2 ("CE: Requested too many blocks to check (requested: %i, max: %i)", p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbr);
463
464 p_dst = p_status;
465 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR);
466 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
467 break;
468 }
469 else if (block_number == 0)
470 {
471 /* Special caes: NDEF block0 is the ndef attribute block */
472 p_temp = p_dst;
473
474 /* For rw ndef, use scratch buffer's attributes (in case reader/writer had previously updated NDEF) */
475 if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf))
476 {
477 ndef_writef = p_cb->ndef_info.scratch_writef;
478 ndef_len = p_cb->ndef_info.scratch_ln;
479 }
480 else
481 {
482 ndef_writef = p_cb->ndef_info.writef;
483 ndef_len = p_cb->ndef_info.ln;
484 }
485
486 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.version);
487 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbr);
488 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbw);
489 UINT16_TO_BE_STREAM (p_dst, p_cb->ndef_info.nmaxb);
490 UINT32_TO_STREAM (p_dst, 0);
491 UINT8_TO_STREAM (p_dst, ndef_writef);
492 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.rwflag);
493 UINT8_TO_STREAM (p_dst, (ndef_len >> 16 & 0xFF));
494 UINT16_TO_BE_STREAM (p_dst, (ndef_len & 0xFFFF));
495
496 checksum = 0;
497 for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++)
498 {
499 checksum+=p_temp[i];
500 }
501 UINT16_TO_BE_STREAM (p_dst, checksum);
502 }
503 else
504 {
505 /* Verify that block_number is within NDEF memory */
506 if (block_number > p_cb->ndef_info.nmaxb)
507 {
508 /* Invalid block number */
509 p_dst = p_status;
510
511 CE_TRACE_ERROR1 ("CE: Requested block number to check %i.", block_number);
512
513 /* Error: invalid number of blocks to check */
514 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR);
515 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
516 break;
517 }
518 else
519 {
520 /* If card is RW, then read from the scratch buffer (so reader/write can read back what it had just written */
521 if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf))
522 {
523 ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE);
524 }
525 else
526 {
527 ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE);
528 }
529 }
530 }
531 }
532 else
533 {
534 /* Error: invalid service code */
535 CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code);
536
537 p_dst = p_status;
538 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR);
539 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
540 break;
541 }
542 }
543
544 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start);
545 ce_t3t_send_to_lower (p_rsp_msg);
546 }
547 else
548 {
549 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message");
550 }
551
552 GKI_freebuf (p_cmd_msg);
553 }
554
555
556 /*******************************************************************************
557 **
558 ** Function ce_t3t_handle_non_nfc_forum_cmd
559 **
560 ** Description Handle POLL command from reader/writer
561 **
562 ** Returns Nothing
563 **
564 *******************************************************************************/
ce_t3t_handle_non_nfc_forum_cmd(tCE_CB * p_mem_cb,UINT8 cmd_id,BT_HDR * p_cmd_msg)565 void ce_t3t_handle_non_nfc_forum_cmd (tCE_CB *p_mem_cb, UINT8 cmd_id, BT_HDR *p_cmd_msg)
566 {
567 tCE_T3T_MEM *p_cb = &p_mem_cb->mem.t3t;
568 BT_HDR *p_rsp_msg;
569 UINT8 *p_rsp_start;
570 UINT8 *p_dst;
571 UINT8 *p = (UINT8 *) (p_cmd_msg +1) + p_cmd_msg->offset;
572 UINT16 sc;
573 UINT8 rc;
574 BOOLEAN send_response = TRUE;
575
576 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL)
577 {
578 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset;
579
580 switch (cmd_id)
581 {
582 case T3T_MSG_OPC_POLL_CMD:
583 /* Get system code and RC */
584 /* Skip over sod and cmd_id */
585 p+=2;
586 BE_STREAM_TO_UINT16 (sc, p);
587 STREAM_TO_UINT8 (rc, p);
588
589 /* If requesting wildcard system code, or specifically our system code, then send POLL response */
590 if ((sc == 0xFFFF) || (sc == p_cb->system_code))
591 {
592 /* Response Code */
593 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_POLL_RSP);
594
595 /* Manufacturer ID */
596 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
597
598 /* Manufacturer Parameter PMm */
599 ARRAY_TO_STREAM (p_dst, p_cb->local_pmm, NCI_T3T_PMM_LEN);
600
601 /* If requesting system code */
602 if (rc == T3T_POLL_RC_SC)
603 {
604 UINT16_TO_BE_STREAM (p_dst, p_cb->system_code);
605 }
606 }
607 else
608 {
609 send_response = FALSE;
610 }
611 break;
612
613
614 case T3T_MSG_OPC_REQ_RESPONSE_CMD:
615 /* Response Code */
616 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_RESPONSE_RSP);
617
618 /* Manufacturer ID */
619 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
620
621 /* Mode */
622 UINT8_TO_STREAM (p_dst, 0);
623 break;
624
625 case T3T_MSG_OPC_REQ_SYSTEMCODE_CMD:
626 /* Response Code */
627 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_SYSTEMCODE_RSP);
628
629 /* Manufacturer ID */
630 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
631
632 /* Number of system codes */
633 UINT8_TO_STREAM (p_dst, 1);
634
635 /* system codes */
636 UINT16_TO_BE_STREAM (p_dst, T3T_SYSTEM_CODE_NDEF);
637 break;
638
639
640 case T3T_MSG_OPC_REQ_SERVICE_CMD:
641 default:
642 /* Unhandled command */
643 CE_TRACE_ERROR1 ("Unhandled CE opcode: %02x", cmd_id);
644 send_response = FALSE;
645 break;
646 }
647
648 if (send_response)
649 {
650 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start);
651 ce_t3t_send_to_lower (p_rsp_msg);
652 }
653 else
654 {
655 GKI_freebuf (p_rsp_msg);
656 }
657 }
658 else
659 {
660 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message");
661 }
662 GKI_freebuf (p_cmd_msg);
663 }
664
665 /*******************************************************************************
666 **
667 ** Function ce_t3t_data_cback
668 **
669 ** Description This callback function receives the data from NFCC.
670 **
671 ** Returns none
672 **
673 *******************************************************************************/
ce_t3t_data_cback(UINT8 conn_id,tNFC_DATA_CEVT * p_data)674 void ce_t3t_data_cback (UINT8 conn_id, tNFC_DATA_CEVT *p_data)
675 {
676 tCE_CB *p_ce_cb = &ce_cb;
677 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t;
678 BT_HDR *p_msg = p_data->p_data;
679 tCE_DATA ce_data;
680 UINT8 cmd_id, bl0, entry_len, i;
681 UINT8 *p_nfcid2 = NULL;
682 UINT8 *p = (UINT8 *) (p_msg +1) + p_msg->offset;
683 UINT8 cmd_nfcid2[NCI_RF_F_UID_LEN];
684 UINT16 block_list_start_offset, remaining;
685 BOOLEAN msg_processed = FALSE;
686 BOOLEAN block_list_ok;
687 UINT8 sod;
688 UINT8 cmd_type;
689
690 #if (BT_TRACE_PROTOCOL == TRUE)
691 DispT3TagMessage (p_msg, TRUE);
692 #endif
693
694 /* If activate system code is not NDEF, or if no local NDEF contents was set, then pass data up to the app */
695 if ((p_cb->system_code != T3T_SYSTEM_CODE_NDEF) || (!p_cb->ndef_info.initialized))
696 {
697 ce_data.raw_frame.status = p_data->status;
698 ce_data.raw_frame.p_data = p_msg;
699 p_ce_cb->p_cback (CE_T3T_RAW_FRAME_EVT, &ce_data);
700 return;
701 }
702
703 /* Verify that message contains at least Sod and cmd_id */
704 if (p_msg->len < 2)
705 {
706 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len);
707 }
708 else
709 {
710
711 /* Get and validate command opcode */
712 STREAM_TO_UINT8 (sod, p);
713 STREAM_TO_UINT8 (cmd_id, p);
714
715 /* Valid command and message length */
716 cmd_type = ce_t3t_is_valid_opcode (cmd_id);
717 if (cmd_type == CE_T3T_COMMAND_INVALID)
718 {
719 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid command: 0x%02X)", cmd_id);
720 }
721 else if (cmd_type == CE_T3T_COMMAND_FELICA)
722 {
723 ce_t3t_handle_non_nfc_forum_cmd (p_ce_cb, cmd_id, p_msg);
724 msg_processed = TRUE;
725 }
726 else
727 {
728 /* Verify that message contains at least NFCID2 and NUM services */
729 if (p_msg->len < T3T_MSG_CMD_COMMON_HDR_LEN)
730 {
731 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len);
732 }
733 else
734 {
735 /* Handle NFC_FORUM command (UPDATE or CHECK) */
736 STREAM_TO_ARRAY (cmd_nfcid2, p, NCI_RF_F_UID_LEN);
737 STREAM_TO_UINT8 (p_cb->cur_cmd.num_services, p);
738
739 /* Calculate offset of block-list-start */
740 block_list_start_offset = T3T_MSG_CMD_COMMON_HDR_LEN + 2*p_cb->cur_cmd.num_services + 1;
741
742 if (p_cb->state == CE_T3T_STATE_NOT_ACTIVATED)
743 {
744 CE_TRACE_ERROR2 ("CE: received command 0x%02X while in bad state (%i))", cmd_id, p_cb->state);
745 }
746 else if (memcmp (cmd_nfcid2, p_cb->local_nfcid2, NCI_RF_F_UID_LEN) != 0)
747 {
748 CE_TRACE_ERROR0 ("CE: received invalid T3t message (invalid NFCID2)");
749 p_nfcid2 = cmd_nfcid2; /* respond with ERROR using the NFCID2 from the command message */
750 }
751 else if (p_msg->len < block_list_start_offset)
752 {
753 /* Does not have minimum (including number_of_blocks field) */
754 CE_TRACE_ERROR0 ("CE: incomplete message");
755 }
756 else
757 {
758 /* Parse service code list */
759 for (i = 0; i < p_cb->cur_cmd.num_services; i++)
760 {
761 STREAM_TO_UINT16 (p_cb->cur_cmd.service_code_list[i], p);
762 }
763
764 /* Verify that block list */
765 block_list_ok = TRUE;
766 STREAM_TO_UINT8 (p_cb->cur_cmd.num_blocks, p);
767 remaining = p_msg->len - block_list_start_offset;
768 p_cb->cur_cmd.p_block_list_start = p;
769 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++)
770 {
771 /* Each entry is at lease 2 bytes long */
772 if (remaining < 2)
773 {
774 /* Unexpected end of message (while reading block-list) */
775 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)");
776 block_list_ok = FALSE;
777 break;
778 }
779
780 /* Get byte0 of block-list entry */
781 bl0 = *p;
782
783 /* Validate service code index and size of block-list */
784 if ((bl0 & T3T_MSG_SERVICE_LIST_MASK) >= p_cb->cur_cmd.num_services)
785 {
786 /* Invalid service code */
787 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid service index: %i)", (bl0 & T3T_MSG_SERVICE_LIST_MASK));
788 block_list_ok = FALSE;
789 break;
790 }
791 else if ((!(bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)) && (remaining < 3))
792 {
793 /* Unexpected end of message (while reading 3-byte entry) */
794 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)");
795 block_list_ok = FALSE;
796 break;
797 }
798
799 /* Advance pointers to next block-list entry */
800 entry_len = (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) ? 2 : 3;
801 p+=entry_len;
802 remaining-=entry_len;
803 }
804
805 /* Block list is verified. Call CHECK or UPDATE handler */
806 if (block_list_ok)
807 {
808 p_cb->cur_cmd.p_block_data_start = p;
809 if (cmd_id == T3T_MSG_OPC_CHECK_CMD)
810 {
811 /* This is a CHECK command. Sanity check: there shouldn't be any more data remaining after reading block list */
812 if (remaining)
813 {
814 CE_TRACE_ERROR1 ("CE: unexpected data after after CHECK command (#i bytes)", remaining);
815 }
816 ce_t3t_handle_check_cmd (p_ce_cb, p_msg);
817 msg_processed = TRUE;
818 }
819 else
820 {
821 /* This is an UPDATE command. See if message contains all the expected block data */
822 if (remaining < p_cb->cur_cmd.num_blocks*T3T_MSG_BLOCKSIZE)
823 {
824 CE_TRACE_ERROR0 ("CE: unexpected end of block-data");
825 }
826 else
827 {
828 ce_t3t_handle_update_cmd (p_ce_cb, p_msg);
829 msg_processed = TRUE;
830 }
831 }
832 }
833 }
834 }
835 }
836 }
837
838 if (!msg_processed)
839 {
840 ce_t3t_send_rsp (p_ce_cb, p_nfcid2, T3T_MSG_OPC_CHECK_RSP, T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_PROCESSING);
841 GKI_freebuf (p_msg);
842 }
843
844
845 }
846
847 /*******************************************************************************
848 **
849 ** Function ce_t3t_conn_cback
850 **
851 ** Description This callback function receives the events/data from NFCC.
852 **
853 ** Returns none
854 **
855 *******************************************************************************/
ce_t3t_conn_cback(UINT8 conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)856 void ce_t3t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
857 {
858 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t;
859
860 CE_TRACE_DEBUG2 ("ce_t3t_conn_cback: conn_id=%i, evt=%i", conn_id, event);
861
862 switch (event)
863 {
864 case NFC_CONN_CREATE_CEVT:
865 break;
866
867 case NFC_CONN_CLOSE_CEVT:
868 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED;
869 break;
870
871 case NFC_DATA_CEVT:
872 if (p_data->data.status == NFC_STATUS_OK)
873 {
874 ce_t3t_data_cback (conn_id, &p_data->data);
875 }
876 break;
877
878 case NFC_DEACTIVATE_CEVT:
879 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED;
880 NFC_SetStaticRfCback (NULL);
881 break;
882
883 default:
884 break;
885
886 }
887 }
888
889 /*******************************************************************************
890 **
891 ** Function ce_select_t3t
892 **
893 ** Description Select Type 3 Tag
894 **
895 ** Returns NFC_STATUS_OK if success
896 **
897 *******************************************************************************/
ce_select_t3t(UINT16 system_code,UINT8 nfcid2[NCI_RF_F_UID_LEN])898 tNFC_STATUS ce_select_t3t (UINT16 system_code, UINT8 nfcid2[NCI_RF_F_UID_LEN])
899 {
900 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t;
901
902 CE_TRACE_DEBUG0 ("ce_select_t3t ()");
903
904 p_cb->state = CE_T3T_STATE_IDLE;
905 p_cb->system_code = system_code;
906 memcpy (p_cb->local_nfcid2, nfcid2, NCI_RF_F_UID_LEN);
907
908 NFC_SetStaticRfCback (ce_t3t_conn_cback);
909 return NFC_STATUS_OK;
910 }
911
912
913 /*******************************************************************************
914 **
915 ** Function CE_T3tSetLocalNDEFMsg
916 **
917 ** Description Initialise CE Type 3 Tag with mandatory NDEF message
918 **
919 ** Returns NFC_STATUS_OK if success
920 **
921 *******************************************************************************/
CE_T3tSetLocalNDEFMsg(BOOLEAN read_only,UINT32 size_max,UINT32 size_current,UINT8 * p_buf,UINT8 * p_scratch_buf)922 tNFC_STATUS CE_T3tSetLocalNDEFMsg (BOOLEAN read_only,
923 UINT32 size_max,
924 UINT32 size_current,
925 UINT8 *p_buf,
926 UINT8 *p_scratch_buf)
927 {
928 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t;
929
930 CE_TRACE_API3 ("CE_T3tSetContent: ro=%i, size_max=%i, size_current=%i", read_only, size_max, size_current);
931
932 /* Verify scratch buffer was provided if NDEF message is read/write */
933 if ((!read_only) && (!p_scratch_buf))
934 {
935 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only");
936 return NFC_STATUS_FAILED;
937 }
938
939 /* Check if disabling the local NDEF */
940 if (!p_buf)
941 {
942 p_cb->ndef_info.initialized = FALSE;
943 }
944 /* Save ndef attributes */
945 else
946 {
947 p_cb->ndef_info.initialized = TRUE;
948 p_cb->ndef_info.ln = size_current; /* Current length */
949 p_cb->ndef_info.nmaxb = (UINT16) ((size_max + 15) / T3T_MSG_BLOCKSIZE); /* Max length (in blocks) */
950 p_cb->ndef_info.rwflag = (read_only) ? T3T_MSG_NDEF_RWFLAG_RO : T3T_MSG_NDEF_RWFLAG_RW;
951 p_cb->ndef_info.writef = T3T_MSG_NDEF_WRITEF_OFF;
952 p_cb->ndef_info.version = 0x10;
953 p_cb->ndef_info.p_buf = p_buf;
954 p_cb->ndef_info.p_scratch_buf = p_scratch_buf;
955
956 /* Initiate scratch buffer with same contents as read-buffer */
957 if (p_scratch_buf)
958 {
959 p_cb->ndef_info.scratch_ln = p_cb->ndef_info.ln;
960 p_cb->ndef_info.scratch_writef = T3T_MSG_NDEF_WRITEF_OFF;
961 memcpy (p_scratch_buf, p_buf, p_cb->ndef_info.ln);
962 }
963 }
964
965 return (NFC_STATUS_OK);
966 }
967
968 /*******************************************************************************
969 **
970 ** Function CE_T3tSetLocalNDefParams
971 **
972 ** Description Sets T3T-specific NDEF parameters. (Optional - if not
973 ** called, then CE will use default parameters)
974 **
975 ** Returns NFC_STATUS_OK if success
976 **
977 *******************************************************************************/
CE_T3tSetLocalNDefParams(UINT8 nbr,UINT8 nbw)978 tNFC_STATUS CE_T3tSetLocalNDefParams (UINT8 nbr, UINT8 nbw)
979 {
980 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t;
981
982 CE_TRACE_API2 ("CE_T3tSetLocalNDefParams: nbr=%i, nbw=%i", nbr, nbw);
983
984 /* Validate */
985 if ((nbr > T3T_MSG_NUM_BLOCKS_CHECK_MAX) || (nbw>T3T_MSG_NUM_BLOCKS_UPDATE_MAX) || (nbr < 1) || (nbw < 1))
986 {
987 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDefParams: invalid params");
988 return NFC_STATUS_FAILED;
989 }
990
991 p_cb->ndef_info.nbr = nbr;
992 p_cb->ndef_info.nbw = nbw;
993
994 return NFC_STATUS_OK;
995 }
996
997 /*******************************************************************************
998 **
999 ** Function CE_T3tSendCheckRsp
1000 **
1001 ** Description Send CHECK response message
1002 **
1003 ** Returns NFC_STATUS_OK if success
1004 **
1005 *******************************************************************************/
CE_T3tSendCheckRsp(UINT8 status1,UINT8 status2,UINT8 num_blocks,UINT8 * p_block_data)1006 tNFC_STATUS CE_T3tSendCheckRsp (UINT8 status1, UINT8 status2, UINT8 num_blocks, UINT8 *p_block_data)
1007 {
1008 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t;
1009 tNFC_STATUS retval = NFC_STATUS_OK;
1010 BT_HDR *p_rsp_msg;
1011 UINT8 *p_dst, *p_rsp_start;
1012
1013 CE_TRACE_API3 ("CE_T3tCheckRsp: status1=0x%02X, status2=0x%02X, num_blocks=%i", status1, status2, num_blocks);
1014
1015 /* Validate num_blocks */
1016 if (num_blocks > T3T_MSG_NUM_BLOCKS_CHECK_MAX)
1017 {
1018 CE_TRACE_ERROR2 ("CE_T3tCheckRsp num_blocks (%i) exceeds maximum (%i)", num_blocks, T3T_MSG_NUM_BLOCKS_CHECK_MAX);
1019 return (NFC_STATUS_FAILED);
1020 }
1021
1022 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL)
1023 {
1024 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset;
1025
1026 /* Response Code */
1027 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP);
1028
1029 /* Manufacturer ID */
1030 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
1031
1032 /* Status1 and Status2 */
1033 UINT8_TO_STREAM (p_dst, status1);
1034 UINT8_TO_STREAM (p_dst, status2);
1035
1036 if (status1 == T3T_MSG_RSP_STATUS_OK)
1037 {
1038 UINT8_TO_STREAM (p_dst, num_blocks);
1039 ARRAY_TO_STREAM (p_dst, p_block_data, (num_blocks * T3T_MSG_BLOCKSIZE));
1040 }
1041
1042 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start);
1043 ce_t3t_send_to_lower (p_rsp_msg);
1044 }
1045 else
1046 {
1047 CE_TRACE_ERROR0 ("CE: Unable to allocate buffer for response message");
1048 }
1049
1050 return (retval);
1051 }
1052
1053 /*******************************************************************************
1054 **
1055 ** Function CE_T3tSendUpdateRsp
1056 **
1057 ** Description Send UPDATE response message
1058 **
1059 ** Returns NFC_STATUS_OK if success
1060 **
1061 *******************************************************************************/
CE_T3tSendUpdateRsp(UINT8 status1,UINT8 status2)1062 tNFC_STATUS CE_T3tSendUpdateRsp (UINT8 status1, UINT8 status2)
1063 {
1064 tNFC_STATUS retval = NFC_STATUS_OK;
1065 tCE_CB *p_ce_cb = &ce_cb;
1066
1067 CE_TRACE_API2 ("CE_T3tUpdateRsp: status1=0x%02X, status2=0x%02X", status1, status2);
1068 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, status1, status2);
1069
1070 return (retval);
1071 }
1072
1073 #endif /* NFC_INCLUDED == TRUE */
1074