ce_t3t.c revision e9df6ba5a8fcccf306a80b1670b423be8fe7746a
1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com/****************************************************************************** 2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * 3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Copyright (C) 2010-2012 Broadcom Corporation 4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * 5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Licensed under the Apache License, Version 2.0 (the "License"); 6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * you may not use this file except in compliance with the License. 7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * You may obtain a copy of the License at: 8cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * 9cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * http://www.apache.org/licenses/LICENSE-2.0 108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * 118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * Unless required by applicable law or agreed to in writing, software 128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * distributed under the License is distributed on an "AS IS" BASIS, 138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * See the License for the specific language governing permissions and 158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * limitations under the License. 168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * 178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ******************************************************************************/ 188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/****************************************************************************** 208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * 218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * This file contains the implementation for Type 3 tag in Card Emulation 228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * mode. 238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * 248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ******************************************************************************/ 258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include <string.h> 268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "nfc_target.h" 278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "bt_types.h" 288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "trace_api.h" 298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#if (NFC_INCLUDED == TRUE) 318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "nfc_api.h" 328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "nfc_int.h" 338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "ce_api.h" 348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "ce_int.h" 358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "tags_int.h" 368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "gki.h" 378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comenum { 398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_COMMAND_INVALID, 408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_COMMAND_NFC_FORUM, 418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_COMMAND_FELICA 428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com}; 438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/* T3T CE states */ 458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comenum { 468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_STATE_NOT_ACTIVATED, 478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_STATE_IDLE, 488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_T3T_STATE_UPDATING 498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com}; 508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/* Bitmasks to indicate type of UPDATE */ 528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#define CE_T3T_UPDATE_FL_NDEF_UPDATE_START 0x01 538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#define CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT 0x02 548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#define CE_T3T_UPDATE_FL_UPDATE 0x04 558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com* Static constant definitions 588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comstatic const UINT8 CE_DEFAULT_LF_PMM[NCI_T3T_PMM_LEN] = {0x20, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; /* Default PMm param */ 608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_init 648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Initialize tag-specific fields of ce control block 668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns none 688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid ce_t3t_init (void) 718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com memcpy (ce_cb.mem.t3t.local_pmm, CE_DEFAULT_LF_PMM, NCI_T3T_PMM_LEN); 738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_cb.mem.t3t.ndef_info.nbr = CE_T3T_DEFAULT_CHECK_MAXBLOCKS; 748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_cb.mem.t3t.ndef_info.nbw = CE_T3T_DEFAULT_UPDATE_MAXBLOCKS; 758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_send_to_lower 808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Send C-APDU to lower layer 828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns none 848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid ce_t3t_send_to_lower (BT_HDR *p_msg) 878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p; 898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Set NFC-F SoD field (payload len + 1) */ 918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_msg->offset -= 1; /* Point to SoD field */ 928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p = (UINT8 *) (p_msg+1) + p_msg->offset; 938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p, (p_msg->len+1)); 948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_msg->len += 1; /* Increment len to include SoD */ 958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#if (BT_TRACE_PROTOCOL == TRUE) 978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com DispT3TagMessage (p_msg, FALSE); 988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#endif 998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (NFC_SendData (NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK) 1018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("ce_t3t_send_to_lower (): NFC_SendData () failed"); 1038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 1078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_is_valid_opcode 1098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Valid opcode 1118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns Type of command 1138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 1158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comUINT8 ce_t3t_is_valid_opcode (UINT8 cmd_id) 1168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 1178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 retval = CE_T3T_COMMAND_INVALID; 1188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ( (cmd_id == T3T_MSG_OPC_CHECK_CMD) 1208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ||(cmd_id == T3T_MSG_OPC_UPDATE_CMD) ) 1218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com retval = CE_T3T_COMMAND_NFC_FORUM; 1238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else if ( (cmd_id == T3T_MSG_OPC_POLL_CMD) 1258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ||(cmd_id == T3T_MSG_OPC_REQ_SERVICE_CMD) 1268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ||(cmd_id == T3T_MSG_OPC_REQ_RESPONSE_CMD) 1278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ||(cmd_id == T3T_MSG_OPC_REQ_SYSTEMCODE_CMD) ) 1288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com retval = CE_T3T_COMMAND_FELICA; 1308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return (retval); 1338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/***************************************************************************** 1368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_get_rsp_buf 1388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Get a buffer for sending T3T messages 1408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns BT_HDR * 1428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*****************************************************************************/ 1448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comBT_HDR *ce_t3t_get_rsp_buf (void) 1458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 1468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com BT_HDR *p_cmd_buf; 1478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID)) != NULL) 1498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */ 1518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1; 1528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cmd_buf->len = 0; 1538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return (p_cmd_buf); 1568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 1598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_send_rsp 1618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Send response to reader/writer 1638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns none 1658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 1668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 1678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid ce_t3t_send_rsp (tCE_CB *p_ce_cb, UINT8 *p_nfcid2, UINT8 opcode, UINT8 status1, UINT8 status2) 1688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 1698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 1708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com BT_HDR *p_rsp_msg; 1718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_dst, *p_rsp_start; 1728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* If p_nfcid2 is NULL, then used activated NFCID2 */ 1748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (p_nfcid2 == NULL) 1758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_nfcid2 = p_cb->local_nfcid2; 1778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 1808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 1828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Response Code */ 1848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, opcode); 1858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Manufacturer ID */ 1878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ARRAY_TO_STREAM (p_dst, p_nfcid2, NCI_RF_F_UID_LEN); 1888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Status1 and Status2 */ 1908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, status1); 1918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, status2); 1928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 1948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_t3t_send_to_lower (p_rsp_msg); 1958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 1978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 1988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 1998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 2018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 2038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 2048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_handle_update_cmd 2058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 2068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Handle UPDATE command from reader/writer 2078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 2088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns none 2098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 2108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 2118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid ce_t3t_handle_update_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg) 2128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 2138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 2148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_temp; 2158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_block_list = p_cb->cur_cmd.p_block_list_start; 2168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_block_data = p_cb->cur_cmd.p_block_data_start; 2178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 i, j, bl0; 2188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT16 block_number, service_code, checksum, checksum_rx; 2198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT32 newlen_hiword; 2208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tCE_T3T_NDEF_INFO ndef_info; 2218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tNFC_STATUS nfc_status = NFC_STATUS_OK; 2228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 update_flags = 0; 2238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tCE_UPDATE_INFO update_info; 2248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* If in idle state, notify app that update is starting */ 2268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (p_cb->state == CE_T3T_STATE_IDLE) 2278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cb->state = CE_T3T_STATE_UPDATING; 2298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 2328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Read byte0 of block list */ 2348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (bl0, p_block_list); 2358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) 2378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (block_number, p_block_list); 2398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 2418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT16 (block_number, p_block_list); 2438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Read the block from memory */ 2468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK]; 2478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Reject UPDATE command if service code=T3T_MSG_NDEF_SC_RO */ 2498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (service_code == T3T_MSG_NDEF_SC_RO) 2508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid block number to update */ 2528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("CE: UPDATE request using read-only service"); 2538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 2548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 2558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Check for NDEF */ 2588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (service_code == T3T_MSG_NDEF_SC_RW) 2598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbw) 2618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 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); 2638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 2648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 2658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else if (p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RO) 2678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("CE: error: write-request to read-only NDEF message."); 2698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 2708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 2718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else if (block_number == 0) 2738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_DEBUG2 ("CE: Update sc 0x%04x block %i.", service_code, block_number); 2758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Special caes: NDEF block0 is the ndef attribute block */ 2778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_temp = p_block_data; 2788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (ndef_info.version, p_block_data); 2798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_block_data+=8; /* Ignore nbr,nbw,maxb,and reserved (reader/writer not allowed to update this) */ 2808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (ndef_info.writef, p_block_data); 2818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_block_data++; /* Ignore rwflag (reader/writer not allowed to update this) */ 2828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (newlen_hiword, p_block_data); 2838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com BE_STREAM_TO_UINT16 (ndef_info.ln, p_block_data); 2848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ndef_info.ln += (newlen_hiword<<16); 2858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com BE_STREAM_TO_UINT16 (checksum_rx, p_block_data); 2868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com checksum=0; 2888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com for (j=0; j<T3T_MSG_NDEF_ATTR_INFO_SIZE; j++) 2898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com checksum+=p_temp[j]; 2918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Compare calcuated checksum with received checksum */ 2948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (checksum != checksum_rx) 2958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 2968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("CE: Checksum failed for NDEF attribute block."); 2978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 2988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Update NDEF attribute block (only allowed to update current length and writef fields) */ 3028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cb->ndef_info.scratch_ln = ndef_info.ln; 3038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cb->ndef_info.scratch_writef = ndef_info.writef; 3048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* If writef=0 indicates completion of NDEF update */ 3068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (ndef_info.writef == 0) 3078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT; 3098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* writef=1 indicates start of NDEF update */ 3118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_START; 3148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_DEBUG2 ("CE: Udpate sc 0x%04x block %i.", service_code, block_number); 3208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Verify that block_number is within NDEF memory */ 3228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (block_number > p_cb->ndef_info.nmaxb) 3238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid block number to update */ 3258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR2 ("CE: Requested invalid NDEF block number to update %i (max is %i).", block_number, p_cb->ndef_info.nmaxb); 3268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 3278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 3288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Update NDEF memory block */ 3328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_ARRAY ((&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), p_block_data, T3T_MSG_BLOCKSIZE); 3338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Set flag to indicate that this UPDATE contained at least one block */ 3368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_flags |= CE_T3T_UPDATE_FL_UPDATE; 3378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid service code */ 3428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code); 3438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com nfc_status = NFC_STATUS_FAILED; 3448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 3458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Send appropriate response to reader/writer */ 3498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (nfc_status == NFC_STATUS_OK) 3508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_OK, T3T_MSG_RSP_STATUS_OK); 3528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 3548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 3568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cb->state = CE_T3T_STATE_IDLE; 3578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Notify the app of what got updated */ 3618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_START) 3628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* NDEF attribute got updated with WriteF=TRUE */ 3648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_START_EVT, NULL); 3658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (update_flags & CE_T3T_UPDATE_FL_UPDATE) 3688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* UPDATE message contained at least one non-NDEF block */ 3708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_ce_cb->p_cback (CE_T3T_UPDATE_EVT, NULL); 3718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT) 3758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 3768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* NDEF attribute got updated with WriteF=FALSE */ 3778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_info.status = nfc_status; 3788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_info.p_data = p_cb->ndef_info.p_scratch_buf; 3798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com update_info.length = p_cb->ndef_info.scratch_ln; 3808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_cb->state = CE_T3T_STATE_IDLE; 3818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_CPLT_EVT, (tCE_DATA *) &update_info); 3828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com GKI_freebuf (p_cmd_msg); 3858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/******************************************************************************* 3888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 3898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Function ce_t3t_handle_check_cmd 3908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 3918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Description Handle CHECK command from reader/writer 3928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 3938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** Returns Nothing 3948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com** 3958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com*******************************************************************************/ 3968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid ce_t3t_handle_check_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg) 3978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com{ 3988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 3998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com BT_HDR *p_rsp_msg; 4008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_rsp_start; 4018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_dst, *p_temp, *p_status; 4028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 *p_src = p_cb->cur_cmd.p_block_list_start; 4038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 i, bl0; 4048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8 ndef_writef; 4058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT32 ndef_len; 4068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT16 block_number, service_code, checksum; 4078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 4098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 4118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Response Code */ 4138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP); 4148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Manufacturer ID */ 4168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 4178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Save pointer to start of status field */ 4198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_status = p_dst; 4208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Status1 and Status2 (assume success initially */ 4228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK); 4238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK); 4248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, p_cb->cur_cmd.num_blocks); 4258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 4278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Read byte0 of block list */ 4298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (bl0, p_src); 4308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) 4328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT8 (block_number, p_src); 4348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 4368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com STREAM_TO_UINT16 (block_number, p_src); 4388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Read the block from memory */ 4418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK]; 4428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Check for NDEF */ 4448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((service_code == T3T_MSG_NDEF_SC_RO) || (service_code == T3T_MSG_NDEF_SC_RW)) 4458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Verify Nbr (NDEF only) */ 4478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbr) 4488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid number of blocks to check */ 4508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 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); 4518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_dst = p_status; 4538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 4548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 4558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 4568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else if (block_number == 0) 4588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Special caes: NDEF block0 is the ndef attribute block */ 4608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_temp = p_dst; 4618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* For rw ndef, use scratch buffer's attributes (in case reader/writer had previously updated NDEF) */ 4638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf)) 4648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ndef_writef = p_cb->ndef_info.scratch_writef; 4668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ndef_len = p_cb->ndef_info.scratch_ln; 4678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 4698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ndef_writef = p_cb->ndef_info.writef; 4718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ndef_len = p_cb->ndef_info.ln; 4728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, p_cb->ndef_info.version); 4758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbr); 4768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbw); 4778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT16_TO_BE_STREAM (p_dst, p_cb->ndef_info.nmaxb); 4788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT32_TO_STREAM (p_dst, 0); 4798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, ndef_writef); 4808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, p_cb->ndef_info.rwflag); 4818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, (ndef_len >> 16 & 0xFF)); 4828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT16_TO_BE_STREAM (p_dst, (ndef_len & 0xFFFF)); 4838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com checksum = 0; 4858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) 4868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com checksum+=p_temp[i]; 4888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT16_TO_BE_STREAM (p_dst, checksum); 4908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 4928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Verify that block_number is within NDEF memory */ 4948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (block_number > p_cb->ndef_info.nmaxb) 4958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 4968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Invalid block number */ 4978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_dst = p_status; 4988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR1 ("CE: Requested block number to check %i.", block_number); 5008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid number of blocks to check */ 5028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 5038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 5048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 5058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 5078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 5088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* If card is RW, then read from the scratch buffer (so reader/write can read back what it had just written */ 5098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf)) 5108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 5118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE); 5128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 5148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 5158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE); 5168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 5218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 5228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com /* Error: invalid service code */ 5238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code); 5248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_dst = p_status; 5268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 5278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 5288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com break; 5298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 5338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ce_t3t_send_to_lower (p_rsp_msg); 5348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com else 5368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com { 5378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 5388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 539cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com 540 GKI_freebuf (p_cmd_msg); 541} 542 543 544/******************************************************************************* 545** 546** Function ce_t3t_handle_non_nfc_forum_cmd 547** 548** Description Handle POLL command from reader/writer 549** 550** Returns Nothing 551** 552*******************************************************************************/ 553void ce_t3t_handle_non_nfc_forum_cmd (tCE_CB *p_mem_cb, UINT8 cmd_id, BT_HDR *p_cmd_msg) 554{ 555 tCE_T3T_MEM *p_cb = &p_mem_cb->mem.t3t; 556 BT_HDR *p_rsp_msg; 557 UINT8 *p_rsp_start; 558 UINT8 *p_dst; 559 UINT8 *p = (UINT8 *) (p_cmd_msg +1) + p_cmd_msg->offset; 560 UINT16 sc; 561 UINT8 rc; 562 BOOLEAN send_response = TRUE; 563 564 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 565 { 566 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 567 568 switch (cmd_id) 569 { 570 case T3T_MSG_OPC_POLL_CMD: 571 /* Get system code and RC */ 572 /* Skip over sod and cmd_id */ 573 p+=2; 574 BE_STREAM_TO_UINT16 (sc, p); 575 STREAM_TO_UINT8 (rc, p); 576 577 /* If requesting wildcard system code, or specifically our system code, then send POLL response */ 578 if ((sc == 0xFFFF) || (sc == p_cb->system_code)) 579 { 580 /* Response Code */ 581 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_POLL_RSP); 582 583 /* Manufacturer ID */ 584 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 585 586 /* Manufacturer Parameter PMm */ 587 ARRAY_TO_STREAM (p_dst, p_cb->local_pmm, NCI_T3T_PMM_LEN); 588 589 /* If requesting system code */ 590 if (rc == T3T_POLL_RC_SC) 591 { 592 UINT16_TO_BE_STREAM (p_dst, p_cb->system_code); 593 } 594 } 595 else 596 { 597 send_response = FALSE; 598 } 599 break; 600 601 602 case T3T_MSG_OPC_REQ_RESPONSE_CMD: 603 /* Response Code */ 604 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_RESPONSE_RSP); 605 606 /* Manufacturer ID */ 607 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 608 609 /* Mode */ 610 UINT8_TO_STREAM (p_dst, 0); 611 break; 612 613 case T3T_MSG_OPC_REQ_SYSTEMCODE_CMD: 614 /* Response Code */ 615 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_SYSTEMCODE_RSP); 616 617 /* Manufacturer ID */ 618 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 619 620 /* Number of system codes */ 621 UINT8_TO_STREAM (p_dst, 1); 622 623 /* system codes */ 624 UINT16_TO_BE_STREAM (p_dst, T3T_SYSTEM_CODE_NDEF); 625 break; 626 627 628 case T3T_MSG_OPC_REQ_SERVICE_CMD: 629 default: 630 /* Unhandled command */ 631 CE_TRACE_ERROR1 ("Unhandled CE opcode: %02x", cmd_id); 632 send_response = FALSE; 633 break; 634 } 635 636 if (send_response) 637 { 638 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 639 ce_t3t_send_to_lower (p_rsp_msg); 640 } 641 else 642 { 643 GKI_freebuf (p_rsp_msg); 644 } 645 } 646 else 647 { 648 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 649 } 650 GKI_freebuf (p_cmd_msg); 651} 652 653/******************************************************************************* 654** 655** Function ce_t3t_data_cback 656** 657** Description This callback function receives the data from NFCC. 658** 659** Returns none 660** 661*******************************************************************************/ 662void ce_t3t_data_cback (UINT8 conn_id, BT_HDR *p_msg) 663{ 664 tCE_CB *p_ce_cb = &ce_cb; 665 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 666 tCE_DATA ce_data; 667 UINT8 cmd_id, bl0, entry_len, i; 668 UINT8 *p_nfcid2 = NULL; 669 UINT8 *p = (UINT8 *) (p_msg +1) + p_msg->offset; 670 UINT8 cmd_nfcid2[NCI_RF_F_UID_LEN]; 671 UINT16 block_list_start_offset, remaining; 672 BOOLEAN msg_processed = FALSE; 673 BOOLEAN block_list_ok; 674 UINT8 sod; 675 UINT8 cmd_type; 676 677#if (BT_TRACE_PROTOCOL == TRUE) 678 DispT3TagMessage (p_msg, TRUE); 679#endif 680 681 /* If activate system code is not NDEF, or if no local NDEF contents was set, then pass data up to the app */ 682 if ((p_cb->system_code != T3T_SYSTEM_CODE_NDEF) || (!p_cb->ndef_info.initialized)) 683 { 684 ce_data.raw_frame.status = NFC_STATUS_OK; 685 ce_data.raw_frame.p_data = p_msg; 686 p_ce_cb->p_cback (CE_T3T_RAW_FRAME_EVT, &ce_data); 687 return; 688 } 689 690 /* Verify that message contains at least Sod and cmd_id */ 691 if (p_msg->len < 2) 692 { 693 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len); 694 } 695 else 696 { 697 698 /* Get and validate command opcode */ 699 STREAM_TO_UINT8 (sod, p); 700 STREAM_TO_UINT8 (cmd_id, p); 701 702 /* Valid command and message length */ 703 cmd_type = ce_t3t_is_valid_opcode (cmd_id); 704 if (cmd_type == CE_T3T_COMMAND_INVALID) 705 { 706 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid command: 0x%02X)", cmd_id); 707 } 708 else if (cmd_type == CE_T3T_COMMAND_FELICA) 709 { 710 ce_t3t_handle_non_nfc_forum_cmd (p_ce_cb, cmd_id, p_msg); 711 msg_processed = TRUE; 712 } 713 else 714 { 715 /* Verify that message contains at least NFCID2 and NUM services */ 716 if (p_msg->len < T3T_MSG_CMD_COMMON_HDR_LEN) 717 { 718 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len); 719 } 720 else 721 { 722 /* Handle NFC_FORUM command (UPDATE or CHECK) */ 723 STREAM_TO_ARRAY (cmd_nfcid2, p, NCI_RF_F_UID_LEN); 724 STREAM_TO_UINT8 (p_cb->cur_cmd.num_services, p); 725 726 /* Calculate offset of block-list-start */ 727 block_list_start_offset = T3T_MSG_CMD_COMMON_HDR_LEN + 2*p_cb->cur_cmd.num_services + 1; 728 729 if (p_cb->state == CE_T3T_STATE_NOT_ACTIVATED) 730 { 731 CE_TRACE_ERROR2 ("CE: received command 0x%02X while in bad state (%i))", cmd_id, p_cb->state); 732 } 733 else if (memcmp (cmd_nfcid2, p_cb->local_nfcid2, NCI_RF_F_UID_LEN) != 0) 734 { 735 CE_TRACE_ERROR0 ("CE: received invalid T3t message (invalid NFCID2)"); 736 p_nfcid2 = cmd_nfcid2; /* respond with ERROR using the NFCID2 from the command message */ 737 } 738 else if (p_msg->len < block_list_start_offset) 739 { 740 /* Does not have minimum (including number_of_blocks field) */ 741 CE_TRACE_ERROR0 ("CE: incomplete message"); 742 } 743 else 744 { 745 /* Parse service code list */ 746 for (i = 0; i < p_cb->cur_cmd.num_services; i++) 747 { 748 STREAM_TO_UINT16 (p_cb->cur_cmd.service_code_list[i], p); 749 } 750 751 /* Verify that block list */ 752 block_list_ok = TRUE; 753 STREAM_TO_UINT8 (p_cb->cur_cmd.num_blocks, p); 754 remaining = p_msg->len - block_list_start_offset; 755 p_cb->cur_cmd.p_block_list_start = p; 756 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 757 { 758 /* Each entry is at lease 2 bytes long */ 759 if (remaining < 2) 760 { 761 /* Unexpected end of message (while reading block-list) */ 762 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)"); 763 block_list_ok = FALSE; 764 break; 765 } 766 767 /* Get byte0 of block-list entry */ 768 bl0 = *p; 769 770 /* Validate service code index and size of block-list */ 771 if ((bl0 & T3T_MSG_SERVICE_LIST_MASK) >= p_cb->cur_cmd.num_services) 772 { 773 /* Invalid service code */ 774 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid service index: %i)", (bl0 & T3T_MSG_SERVICE_LIST_MASK)); 775 block_list_ok = FALSE; 776 break; 777 } 778 else if ((!(bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)) && (remaining < 3)) 779 { 780 /* Unexpected end of message (while reading 3-byte entry) */ 781 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)"); 782 block_list_ok = FALSE; 783 break; 784 } 785 786 /* Advance pointers to next block-list entry */ 787 entry_len = (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) ? 2 : 3; 788 p+=entry_len; 789 remaining-=entry_len; 790 } 791 792 /* Block list is verified. Call CHECK or UPDATE handler */ 793 if (block_list_ok) 794 { 795 p_cb->cur_cmd.p_block_data_start = p; 796 if (cmd_id == T3T_MSG_OPC_CHECK_CMD) 797 { 798 /* This is a CHECK command. Sanity check: there shouldn't be any more data remaining after reading block list */ 799 if (remaining) 800 { 801 CE_TRACE_ERROR1 ("CE: unexpected data after after CHECK command (#i bytes)", remaining); 802 } 803 ce_t3t_handle_check_cmd (p_ce_cb, p_msg); 804 msg_processed = TRUE; 805 } 806 else 807 { 808 /* This is an UPDATE command. See if message contains all the expected block data */ 809 if (remaining < p_cb->cur_cmd.num_blocks*T3T_MSG_BLOCKSIZE) 810 { 811 CE_TRACE_ERROR0 ("CE: unexpected end of block-data"); 812 } 813 else 814 { 815 ce_t3t_handle_update_cmd (p_ce_cb, p_msg); 816 msg_processed = TRUE; 817 } 818 } 819 } 820 } 821 } 822 } 823 } 824 825 if (!msg_processed) 826 { 827 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); 828 GKI_freebuf (p_msg); 829 } 830 831 832} 833 834/******************************************************************************* 835** 836** Function ce_t3t_conn_cback 837** 838** Description This callback function receives the events/data from NFCC. 839** 840** Returns none 841** 842*******************************************************************************/ 843void ce_t3t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) 844{ 845 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 846 847 CE_TRACE_DEBUG2 ("ce_t3t_conn_cback: conn_id=%i, evt=%i", conn_id, event); 848 849 switch (event) 850 { 851 case NFC_CONN_CREATE_CEVT: 852 break; 853 854 case NFC_CONN_CLOSE_CEVT: 855 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED; 856 break; 857 858 case NFC_DATA_CEVT: 859 if (p_data->data.status == NFC_STATUS_OK) 860 { 861 ce_t3t_data_cback (conn_id, p_data->data.p_data); 862 } 863 break; 864 865 case NFC_DEACTIVATE_CEVT: 866 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED; 867 NFC_SetStaticRfCback (NULL); 868 break; 869 870 default: 871 break; 872 873 } 874} 875 876/******************************************************************************* 877** 878** Function ce_select_t3t 879** 880** Description Select Type 3 Tag 881** 882** Returns NFC_STATUS_OK if success 883** 884*******************************************************************************/ 885tNFC_STATUS ce_select_t3t (UINT16 system_code, UINT8 nfcid2[NCI_RF_F_UID_LEN]) 886{ 887 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 888 889 CE_TRACE_DEBUG0 ("ce_select_t3t ()"); 890 891 p_cb->state = CE_T3T_STATE_IDLE; 892 p_cb->system_code = system_code; 893 memcpy (p_cb->local_nfcid2, nfcid2, NCI_RF_F_UID_LEN); 894 895 NFC_SetStaticRfCback (ce_t3t_conn_cback); 896 return NFC_STATUS_OK; 897} 898 899 900/******************************************************************************* 901** 902** Function CE_T3tSetLocalNDEFMsg 903** 904** Description Initialise CE Type 3 Tag with mandatory NDEF message 905** 906** Returns NFC_STATUS_OK if success 907** 908*******************************************************************************/ 909tNFC_STATUS CE_T3tSetLocalNDEFMsg (BOOLEAN read_only, 910 UINT32 size_max, 911 UINT32 size_current, 912 UINT8 *p_buf, 913 UINT8 *p_scratch_buf) 914{ 915 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 916 917 CE_TRACE_API3 ("CE_T3tSetContent: ro=%i, size_max=%i, size_current=%i", read_only, size_max, size_current); 918 919 /* Verify scratch buffer was provided if NDEF message is read/write */ 920 if ((!read_only) && (!p_scratch_buf)) 921 { 922 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only"); 923 return NFC_STATUS_FAILED; 924 } 925 926 /* Check if disabling the local NDEF */ 927 if (!p_buf) 928 { 929 p_cb->ndef_info.initialized = FALSE; 930 } 931 /* Save ndef attributes */ 932 else 933 { 934 p_cb->ndef_info.initialized = TRUE; 935 p_cb->ndef_info.ln = size_current; /* Current length */ 936 p_cb->ndef_info.nmaxb = (UINT16) ((size_max + 15) / T3T_MSG_BLOCKSIZE); /* Max length (in blocks) */ 937 p_cb->ndef_info.rwflag = (read_only) ? T3T_MSG_NDEF_RWFLAG_RO : T3T_MSG_NDEF_RWFLAG_RW; 938 p_cb->ndef_info.writef = T3T_MSG_NDEF_WRITEF_OFF; 939 p_cb->ndef_info.version = 0x10; 940 p_cb->ndef_info.p_buf = p_buf; 941 p_cb->ndef_info.p_scratch_buf = p_scratch_buf; 942 943 /* Initiate scratch buffer with same contents as read-buffer */ 944 if (p_scratch_buf) 945 { 946 p_cb->ndef_info.scratch_ln = p_cb->ndef_info.ln; 947 p_cb->ndef_info.scratch_writef = T3T_MSG_NDEF_WRITEF_OFF; 948 memcpy (p_scratch_buf, p_buf, p_cb->ndef_info.ln); 949 } 950 } 951 952 return (NFC_STATUS_OK); 953} 954 955/******************************************************************************* 956** 957** Function CE_T3tSetLocalNDefParams 958** 959** Description Sets T3T-specific NDEF parameters. (Optional - if not 960** called, then CE will use default parameters) 961** 962** Returns NFC_STATUS_OK if success 963** 964*******************************************************************************/ 965tNFC_STATUS CE_T3tSetLocalNDefParams (UINT8 nbr, UINT8 nbw) 966{ 967 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 968 969 CE_TRACE_API2 ("CE_T3tSetLocalNDefParams: nbr=%i, nbw=%i", nbr, nbw); 970 971 /* Validate */ 972 if ((nbr > T3T_MSG_NUM_BLOCKS_CHECK_MAX) || (nbw>T3T_MSG_NUM_BLOCKS_UPDATE_MAX) || (nbr < 1) || (nbw < 1)) 973 { 974 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDefParams: invalid params"); 975 return NFC_STATUS_FAILED; 976 } 977 978 p_cb->ndef_info.nbr = nbr; 979 p_cb->ndef_info.nbw = nbw; 980 981 return NFC_STATUS_OK; 982} 983 984/******************************************************************************* 985** 986** Function CE_T3tSendCheckRsp 987** 988** Description Send CHECK response message 989** 990** Returns NFC_STATUS_OK if success 991** 992*******************************************************************************/ 993tNFC_STATUS CE_T3tSendCheckRsp (UINT8 status1, UINT8 status2, UINT8 num_blocks, UINT8 *p_block_data) 994{ 995 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 996 tNFC_STATUS retval = NFC_STATUS_OK; 997 BT_HDR *p_rsp_msg; 998 UINT8 *p_dst, *p_rsp_start; 999 1000 CE_TRACE_API3 ("CE_T3tCheckRsp: status1=0x%02X, status2=0x%02X, num_blocks=%i", status1, status2, num_blocks); 1001 1002 /* Validate num_blocks */ 1003 if (num_blocks > T3T_MSG_NUM_BLOCKS_CHECK_MAX) 1004 { 1005 CE_TRACE_ERROR2 ("CE_T3tCheckRsp num_blocks (%i) exceeds maximum (%i)", num_blocks, T3T_MSG_NUM_BLOCKS_CHECK_MAX); 1006 return (NFC_STATUS_FAILED); 1007 } 1008 1009 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 1010 { 1011 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 1012 1013 /* Response Code */ 1014 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP); 1015 1016 /* Manufacturer ID */ 1017 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 1018 1019 /* Status1 and Status2 */ 1020 UINT8_TO_STREAM (p_dst, status1); 1021 UINT8_TO_STREAM (p_dst, status2); 1022 1023 if (status1 == T3T_MSG_RSP_STATUS_OK) 1024 { 1025 UINT8_TO_STREAM (p_dst, num_blocks); 1026 ARRAY_TO_STREAM (p_dst, p_block_data, (num_blocks * T3T_MSG_BLOCKSIZE)); 1027 } 1028 1029 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 1030 ce_t3t_send_to_lower (p_rsp_msg); 1031 } 1032 else 1033 { 1034 CE_TRACE_ERROR0 ("CE: Unable to allocate buffer for response message"); 1035 } 1036 1037 return (retval); 1038} 1039 1040/******************************************************************************* 1041** 1042** Function CE_T3tSendUpdateRsp 1043** 1044** Description Send UPDATE response message 1045** 1046** Returns NFC_STATUS_OK if success 1047** 1048*******************************************************************************/ 1049tNFC_STATUS CE_T3tSendUpdateRsp (UINT8 status1, UINT8 status2) 1050{ 1051 tNFC_STATUS retval = NFC_STATUS_OK; 1052 tCE_CB *p_ce_cb = &ce_cb; 1053 1054 CE_TRACE_API2 ("CE_T3tUpdateRsp: status1=0x%02X, status2=0x%02X", status1, status2); 1055 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, status1, status2); 1056 1057 return (retval); 1058} 1059 1060#endif /* NFC_INCLUDED == TRUE */ 1061