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