/******************************************************************************
*
* Copyright (C) 2011-2013 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* NFA interface for card emulation
*
******************************************************************************/
#include <string.h>
#include "nfa_api.h"
#include "nfa_sys.h"
#include "nfa_ce_int.h"
#include "nfa_sys_int.h"
/*******************************************************************************
**
** Function nfa_ce_api_deregister_listen
**
** Description Internal function called by listening for Felica system
** code, ISO-DEP AID, or UICC technology
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_BAD_HANDLE invalid handle
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS nfa_ce_api_deregister_listen (tNFA_HANDLE handle, UINT32 listen_info)
{
tNFA_CE_MSG *p_ce_msg;
/* Validate handle */
if ( (listen_info != NFA_CE_LISTEN_INFO_UICC)
&&((handle & NFA_HANDLE_GROUP_MASK) != NFA_HANDLE_GROUP_CE) )
{
NFA_TRACE_ERROR0 ("nfa_ce_api_reregister_listen: Invalid handle");
return (NFA_STATUS_BAD_HANDLE);
}
if ((p_ce_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) (sizeof (tNFA_CE_MSG)))) != NULL)
{
p_ce_msg->hdr.event = NFA_CE_API_DEREG_LISTEN_EVT;
p_ce_msg->dereg_listen.handle = handle;
p_ce_msg->dereg_listen.listen_info = listen_info;
nfa_sys_sendmsg (p_ce_msg);
return (NFA_STATUS_OK);
}
else
{
NFA_TRACE_ERROR0 ("nfa_ce_api_reregister_listen: Out of buffers");
return (NFA_STATUS_FAILED);
}
}
/*****************************************************************************
** APIs
*****************************************************************************/
/*******************************************************************************
**
** Function NFA_CeConfigureLocalTag
**
** Description Configure local NDEF tag.
**
** Tag events will be notifed using the tNFA_CONN_CBACK
** (registered during NFA_Enable)
**
** The NFA_CE_LOCAL_TAG_CONFIGURED_EVT reports the status of the
** operation.
**
** Activation and deactivation are reported using the
** NFA_ACTIVATED_EVT and NFA_DEACTIVATED_EVT events
**
** If a write-request is received to update the tag memory,
** an NFA_CE_NDEF_WRITE_CPLT_EVT will notify the application, along
** with a buffer containing the updated contents.
**
** To disable the local NDEF tag, set protocol_mask=0
**
** The NDEF data provided by p_ndef_data must be persistent
** as long as the local NDEF tag is enabled.
**
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function. Also, Input parameters p_uid and
** uid_len are reserved for future use.
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_INVALID_PARAM,
** if protocol_maks is not 0 and p_ndef_data is NULL
** (or)uid_len is not 0
** (or)if protocol mask is set for Type 1 or Type 2
**
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeConfigureLocalTag (tNFA_PROTOCOL_MASK protocol_mask,
UINT8 *p_ndef_data,
UINT16 ndef_cur_size,
UINT16 ndef_max_size,
BOOLEAN read_only,
UINT8 uid_len,
UINT8 *p_uid)
{
tNFA_CE_MSG *p_msg;
NFA_TRACE_API0 ("NFA_CeConfigureLocalTag ()");
if (protocol_mask)
{
/* If any protocols are specified, then NDEF buffer pointer must be non-NULL */
if (p_ndef_data == NULL)
{
NFA_TRACE_ERROR0 ("NFA_CeConfigureLocalTag: NULL ndef data pointer");
return (NFA_STATUS_INVALID_PARAM);
}
if ((protocol_mask & NFA_PROTOCOL_MASK_T1T) || (protocol_mask & NFA_PROTOCOL_MASK_T2T))
{
NFA_TRACE_ERROR0 ("NFA_CeConfigureLocalTag: Cannot emulate Type 1 / Type 2 tag");
return (NFA_STATUS_INVALID_PARAM);
}
if (uid_len)
{
NFA_TRACE_ERROR1 ("NFA_CeConfigureLocalTag: Cannot Set UID for Protocol_mask: 0x%x", protocol_mask);
return (NFA_STATUS_INVALID_PARAM);
}
}
if ((p_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) sizeof(tNFA_CE_MSG))) != NULL)
{
p_msg->local_tag.hdr.event = NFA_CE_API_CFG_LOCAL_TAG_EVT;
/* Copy ndef info */
p_msg->local_tag.protocol_mask = protocol_mask;
p_msg->local_tag.p_ndef_data = p_ndef_data;
p_msg->local_tag.ndef_cur_size = ndef_cur_size;
p_msg->local_tag.ndef_max_size = ndef_max_size;
p_msg->local_tag.read_only = read_only;
p_msg->local_tag.uid_len = uid_len;
if (uid_len)
memcpy (p_msg->local_tag.uid, p_uid, uid_len);
nfa_sys_sendmsg (p_msg);
return (NFA_STATUS_OK);
}
return (NFA_STATUS_FAILED);
}
/*******************************************************************************
**
** Function NFA_CeConfigureUiccListenTech
**
** Description Configure listening for the UICC, using the specified
** technologies.
**
** Events will be notifed using the tNFA_CONN_CBACK
** (registered during NFA_Enable)
**
** The NFA_CE_UICC_LISTEN_CONFIGURED_EVT reports the status of the
** operation.
**
** Activation and deactivation are reported using the
** NFA_ACTIVATED_EVT and NFA_DEACTIVATED_EVT events
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeConfigureUiccListenTech (tNFA_HANDLE ee_handle,
tNFA_TECHNOLOGY_MASK tech_mask)
{
#if (NFC_NFCEE_INCLUDED == TRUE)
tNFA_CE_MSG *p_msg;
NFA_TRACE_API1 ("NFA_CeConfigureUiccListenTech () ee_handle = 0x%x", ee_handle);
/* If tech_mask is zero, then app is disabling listening for specified uicc */
if (tech_mask == 0)
{
return (nfa_ce_api_deregister_listen (ee_handle, NFA_CE_LISTEN_INFO_UICC));
}
/* Otherwise then app is configuring uicc listen for the specificed technologies */
if ((p_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) sizeof(tNFA_CE_MSG))) != NULL)
{
p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_UICC;
p_msg->reg_listen.ee_handle = ee_handle;
p_msg->reg_listen.tech_mask = tech_mask;
nfa_sys_sendmsg (p_msg);
return (NFA_STATUS_OK);
}
#else
NFA_TRACE_ERROR0 ("NFA_CeConfigureUiccListenTech () NFCEE related functions are not enabled!");
#endif
return (NFA_STATUS_FAILED);
}
/*******************************************************************************
**
** Function NFA_CeRegisterFelicaSystemCodeOnDH
**
** Description Register listening callback for Felica system code
**
** The NFA_CE_REGISTERED_EVT reports the status of the
** operation.
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeRegisterFelicaSystemCodeOnDH (UINT16 system_code,
UINT8 nfcid2[NCI_RF_F_UID_LEN],
tNFA_CONN_CBACK *p_conn_cback)
{
tNFA_CE_MSG *p_msg;
NFA_TRACE_API0 ("NFA_CeRegisterFelicaSystemCodeOnDH ()");
/* Validate parameters */
if (p_conn_cback==NULL)
return (NFA_STATUS_INVALID_PARAM);
if ((p_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) sizeof(tNFA_CE_MSG))) != NULL)
{
p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
p_msg->reg_listen.p_conn_cback = p_conn_cback;
p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_FELICA;
/* Listen info */
memcpy (p_msg->reg_listen.nfcid2, nfcid2, NCI_RF_F_UID_LEN);
p_msg->reg_listen.system_code = system_code;
nfa_sys_sendmsg (p_msg);
return (NFA_STATUS_OK);
}
return (NFA_STATUS_FAILED);
}
/*******************************************************************************
**
** Function NFA_CeDeregisterFelicaSystemCodeOnDH
**
** Description Deregister listening callback for Felica
** (previously registered using NFA_CeRegisterFelicaSystemCodeOnDH)
**
** The NFA_CE_DEREGISTERED_EVT reports the status of the
** operation.
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns NFA_STATUS_OK if successfully initiated
** NFA_STATUS_BAD_HANDLE if invalid handle
** NFA_STATUS_FAILED otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeDeregisterFelicaSystemCodeOnDH (tNFA_HANDLE handle)
{
NFA_TRACE_API1 ("NFA_CeDeregisterFelicaSystemCodeOnDH (): handle:0x%X", handle);
return (nfa_ce_api_deregister_listen (handle, NFA_CE_LISTEN_INFO_FELICA));
}
/*******************************************************************************
**
** Function NFA_CeRegisterAidOnDH
**
** Description Register listening callback for the specified ISODEP AID
**
** The NFA_CE_REGISTERED_EVT reports the status of the
** operation.
**
** If no AID is specified (aid_len=0), then p_conn_cback will
** will get notifications for any AIDs routed to the DH. This
** over-rides callbacks registered for specific AIDs.
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeRegisterAidOnDH (UINT8 aid[NFC_MAX_AID_LEN],
UINT8 aid_len,
tNFA_CONN_CBACK *p_conn_cback)
{
tNFA_CE_MSG *p_msg;
NFA_TRACE_API0 ("NFA_CeRegisterAidOnDH ()");
/* Validate parameters */
if (p_conn_cback==NULL)
return (NFA_STATUS_INVALID_PARAM);
if ((p_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) sizeof(tNFA_CE_MSG))) != NULL)
{
p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
p_msg->reg_listen.p_conn_cback = p_conn_cback;
p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_ISO_DEP;
/* Listen info */
memcpy (p_msg->reg_listen.aid, aid, aid_len);
p_msg->reg_listen.aid_len = aid_len;
nfa_sys_sendmsg (p_msg);
return (NFA_STATUS_OK);
}
return (NFA_STATUS_FAILED);
}
/*******************************************************************************
**
** Function NFA_CeDeregisterAidOnDH
**
** Description Deregister listening callback for ISODEP AID
** (previously registered using NFA_CeRegisterAidOnDH)
**
** The NFA_CE_DEREGISTERED_EVT reports the status of the
** operation.
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns NFA_STATUS_OK if successfully initiated
** NFA_STATUS_BAD_HANDLE if invalid handle
** NFA_STATUS_FAILED otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeDeregisterAidOnDH (tNFA_HANDLE handle)
{
NFA_TRACE_API1 ("NFA_CeDeregisterAidOnDH (): handle:0x%X", handle);
return (nfa_ce_api_deregister_listen (handle, NFA_CE_LISTEN_INFO_T4T_AID));
}
/*******************************************************************************
**
** Function NFA_CeSetIsoDepListenTech
**
** Description Set the technologies (NFC-A and/or NFC-B) to listen for when
** NFA_CeConfigureLocalTag or NFA_CeDeregisterAidOnDH are called.
**
** By default (if this API is not called), NFA will listen
** for both NFC-A and NFC-B for ISODEP.
**
** Note: If listening for ISODEP on UICC, the DH listen callbacks
** may still get activate notifications for ISODEP if the reader/
** writer selects an AID that is not routed to the UICC (regardless
** of whether A or B was disabled using NFA_CeSetIsoDepListenTech)
**
** Note: If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
** should happen before calling this function
**
** Returns:
** NFA_STATUS_OK, if command accepted
** NFA_STATUS_FAILED: otherwise
**
*******************************************************************************/
tNFA_STATUS NFA_CeSetIsoDepListenTech (tNFA_TECHNOLOGY_MASK tech_mask)
{
tNFA_CE_MSG *p_msg;
tNFA_TECHNOLOGY_MASK use_mask = (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B);
NFA_TRACE_API1 ("NFA_CeSetIsoDepListenTech (): 0x%x", tech_mask);
if (((tech_mask & use_mask) == 0) ||
((tech_mask & ~use_mask) != 0) )
{
NFA_TRACE_ERROR0 ("NFA_CeSetIsoDepListenTech: Invalid technology mask");
return (NFA_STATUS_INVALID_PARAM);
}
if ((p_msg = (tNFA_CE_MSG *) GKI_getbuf ((UINT16) sizeof(tNFA_CE_MSG))) != NULL)
{
p_msg->hdr.event = NFA_CE_API_CFG_ISODEP_TECH_EVT;
p_msg->hdr.layer_specific = tech_mask;
nfa_sys_sendmsg (p_msg);
return (NFA_STATUS_OK);
}
return (NFA_STATUS_FAILED);
}