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