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