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