blob: 9178c16d9e413679487ea47d3e97e05bb28ebe2e [file] [log] [blame]
/******************************************************************************
*
* 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.
*
* Copyright 2018-2019 NXP
*
******************************************************************************/
#include "MposManager.h"
#include <nativehelper/ScopedLocalRef.h>
#include <base/logging.h>
#include "config.h"
#include "SecureElement.h"
#include <android-base/stringprintf.h>
#include "nfc_config.h"
#include "nfa_rw_api.h"
using android::base::StringPrintf;
//#include "TransactionController.h"
using namespace android;
extern bool nfc_debug_enabled;
typedef struct nxp_feature_data
{
SyncEvent NxpFeatureConfigEvt;
tNFA_STATUS wstatus;
uint8_t rsp_data[255];
uint8_t rsp_len;
}Nxp_Feature_Data_t;
static Nxp_Feature_Data_t gnxpfeature_conf;
namespace android {
extern bool isDiscoveryStarted ();
extern void startRfDiscovery (bool isStart);
}
tNFA_STATUS EmvCo_dosetPoll(jboolean enable);
//#define ALOGV ALOGD
MposManager MposManager::mMposMgr;
int32_t MposManager::mDiscNtfTimeout = 10;
int32_t MposManager::mRdrTagOpTimeout = 20;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderRequested;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderRequestedFail;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderModeStartConfig;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderModeStopConfig;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderModeSwpTimeout;
jmethodID MposManager::gCachedMposManagerNotifyETSIReaderRestart;
/*******************************************************************************
**
** Function: initMposNativeStruct
**
** Description: Used to initialize the Native MPOS notification methods
**
** Returns: None.
**
*******************************************************************************/
void MposManager::initMposNativeStruct(JNIEnv* e, jobject o)
{
ScopedLocalRef<jclass> cls(e, e->GetObjectClass(o));
gCachedMposManagerNotifyETSIReaderRequested = e->GetMethodID (cls.get(),
"notifyETSIReaderRequested", "(ZZ)V");
gCachedMposManagerNotifyETSIReaderRequestedFail= e->GetMethodID (cls.get(),
"notifyETSIReaderRequestedFail", "(I)V");
gCachedMposManagerNotifyETSIReaderModeStartConfig = e->GetMethodID (cls.get(),
"notifyonETSIReaderModeStartConfig", "(I)V");
gCachedMposManagerNotifyETSIReaderModeStopConfig = e->GetMethodID (cls.get(),
"notifyonETSIReaderModeStopConfig", "(I)V");
gCachedMposManagerNotifyETSIReaderModeSwpTimeout = e->GetMethodID (cls.get(),
"notifyonETSIReaderModeSwpTimeout", "(I)V");
gCachedMposManagerNotifyETSIReaderRestart = e->GetMethodID (cls.get(),
"notifyonETSIReaderModeRestart", "()V");
}
/*******************************************************************************
**
** Function: getInstance
**
** Description: Get the SecureElement singleton object.
**
** Returns: SecureElement object.
**
*******************************************************************************/
MposManager& MposManager::getInstance()
{
return mMposMgr;
}
/*******************************************************************************
**
** Function: initialize
**
** Description: Initialize all member variables.
**
** Returns: True if ok.
**
*******************************************************************************/
bool MposManager::initialize(nfc_jni_native_data* native) {
mNativeData = native;
initializeReaderInfo();
if (NfcConfig::hasKey(NAME_NXP_NFA_DM_DISC_NTF_TIMEOUT))
mDiscNtfTimeout = NfcConfig::getUnsigned(NAME_NXP_NFA_DM_DISC_NTF_TIMEOUT);
if (NfcConfig::hasKey(NAME_NXP_SWP_RD_TAG_OP_TIMEOUT))
mRdrTagOpTimeout = NfcConfig::getUnsigned(NAME_NXP_SWP_RD_TAG_OP_TIMEOUT);
return true;
}
/*******************************************************************************
**
** Function: initializeReaderInfo
**
** Description: Initialize all MPOS member variables.
**
** Returns: none.
**
*******************************************************************************/
void MposManager::initializeReaderInfo()
{
swp_rdr_req_ntf_info.mMutex.lock();
memset(&(swp_rdr_req_ntf_info.swp_rd_req_info), 0x00, sizeof(rd_swp_req_t));
memset(&(swp_rdr_req_ntf_info.swp_rd_req_current_info), 0x00, sizeof(rd_swp_req_t));
swp_rdr_req_ntf_info.swp_rd_req_current_info.src = NFA_HANDLE_INVALID;
swp_rdr_req_ntf_info.swp_rd_req_info.src = NFA_HANDLE_INVALID;
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_STOPPED;
swp_rdr_req_ntf_info.mMutex.unlock();
}
/*******************************************************************************
**
** Function: finalize
**
** Description: Release all resources.
**
** Returns: None
**
*******************************************************************************/
void MposManager::finalize()
{
}
/*******************************************************************************
**
** Function: setDedicatedReaderMode
**
** Description: Set/reset MPOS dedicated mode.
**
** Returns: SUCCESS/FAILED/BUSY
**
*******************************************************************************/
tNFA_STATUS MposManager::setDedicatedReaderMode(bool on)
{
tNFA_STATUS status = NFA_STATUS_OK;
bool rfStat = false;
int32_t state;
SecureElement &se = SecureElement::getInstance();
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s:enter, Reader Mode %s", __FUNCTION__, on?"ON":"OFF");
if(se.isRfFieldOn() || se.mActivatedInListenMode)
{
status = NFA_STATUS_BUSY;
}
if(status == NFA_STATUS_OK)
{
state = getEtsiReaederState();
rfStat = isDiscoveryStarted();
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%x, rfStat=%x", on, rfStat);
if (on) {
if(rfStat)
{
startRfDiscovery(false);
}
}
else
{
if (state != STATE_SE_RDR_MODE_STOPPED) {
setEtsiReaederState (STATE_SE_RDR_MODE_STOP_CONFIG);
etsiInitConfig();
startRfDiscovery(false);
status = etsiResetReaderConfig();
setEtsiReaederState (STATE_SE_RDR_MODE_STOPPED);
}
initializeReaderInfo();
}
}
else
{
DLOG_IF(ERROR, nfc_debug_enabled)
<< StringPrintf("Payment is in progress, aborting reader mode start");
}
return status;
}
/*******************************************************************************
**
** Function: setEtsiReaederState
**
** Description: Set the current ETSI Reader state
**
** Returns: None
**
*******************************************************************************/
void MposManager::setEtsiReaederState(se_rd_req_state_t newState)
{
swp_rdr_req_ntf_info.mMutex.lock();
if (newState == STATE_SE_RDR_MODE_STOPPED) {
swp_rdr_req_ntf_info.swp_rd_req_current_info.tech_mask &= ~NFA_TECHNOLOGY_MASK_A;
swp_rdr_req_ntf_info.swp_rd_req_current_info.tech_mask &= ~NFA_TECHNOLOGY_MASK_B;
//If all the requested tech are removed, set the hande to invalid , so that next time poll add request can be handled
swp_rdr_req_ntf_info.swp_rd_req_current_info.src = NFA_HANDLE_INVALID;
swp_rdr_req_ntf_info.swp_rd_req_info = swp_rdr_req_ntf_info.swp_rd_req_current_info;
}
swp_rdr_req_ntf_info.swp_rd_state = newState;
swp_rdr_req_ntf_info.mMutex.unlock();
}
/*******************************************************************************
**
** Function: getEtsiReaederState
**
** Description: Get the current ETSI Reader state
**
** Returns: Current ETSI state
**
*******************************************************************************/
se_rd_req_state_t MposManager::getEtsiReaederState()
{
return swp_rdr_req_ntf_info.swp_rd_state;
}
/*******************************************************************************
**
** Function: etsiInitConfig
**
** Description: Chnage the ETSI state before start configuration
**
** Returns: None
**
*******************************************************************************/
void MposManager::etsiInitConfig()
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enter", __func__);
swp_rdr_req_ntf_info.mMutex.lock();
if ((swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_START_CONFIG)
&& ((swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask
& NFA_TECHNOLOGY_MASK_A)
|| (swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask
& NFA_TECHNOLOGY_MASK_B))) {
if ((swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_A)) {
swp_rdr_req_ntf_info.swp_rd_req_current_info.tech_mask |=
NFA_TECHNOLOGY_MASK_A;
}
if ((swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_B)) {
swp_rdr_req_ntf_info.swp_rd_req_current_info.tech_mask |=
NFA_TECHNOLOGY_MASK_B;
}
swp_rdr_req_ntf_info.swp_rd_req_current_info.src = swp_rdr_req_ntf_info.swp_rd_req_info.src;
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_START_IN_PROGRESS;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: new ETSI state : STATE_SE_RDR_MODE_START_IN_PROGRESS", __func__);
} else if ((swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOP_CONFIG)
&& (swp_rdr_req_ntf_info.swp_rd_req_current_info.src
== swp_rdr_req_ntf_info.swp_rd_req_info.src)) {
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_STOP_IN_PROGRESS;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: new ETSI state : STATE_SE_RDR_MODE_STOP_IN_PROGRESS", __func__);
}
swp_rdr_req_ntf_info.mMutex.unlock();
}
/*******************************************************************************
**
** Function: etsiReaderConfig
**
** Description: Configuring to Emvco Profile
**
** Returns: Status - NFA_STATUS_FAILED
** NFA_STATUS_OK
** NFA_STATUS_INVALID_PARAM
**
*******************************************************************************/
tNFA_STATUS MposManager::etsiReaderConfig(int32_t eeHandle)
{
tNFC_STATUS status = NFA_STATUS_FAILED;
SecureElement& se = SecureElement::getInstance();
jboolean enable = true;
const tNCI_DISCOVER_MAPS nfc_interface_mapping_uicc[NFC_SWP_RD_NUM_INTERFACE_MAP] =
{
/* Protocols that use Frame Interface do not need to be included in the interface mapping */
{ NCI_PROTOCOL_ISO_DEP, NCI_INTERFACE_MODE_POLL, NCI_INTERFACE_UICC_DIRECT }
};
const tNCI_DISCOVER_MAPS nfc_interface_mapping_ese[NFC_SWP_RD_NUM_INTERFACE_MAP] =
{
/* Protocols that use Frame Interface do not need to be included in the interface mapping */
{ NCI_PROTOCOL_ISO_DEP, NCI_INTERFACE_MODE_POLL, NCI_INTERFACE_ESE_DIRECT }
};
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enter; eeHandle : 0x%4x", __func__, eeHandle);
/* Setting up the emvco poll profile*/
status = EmvCo_dosetPoll(enable);
if (status != NFA_STATUS_OK) {
DLOG_IF(ERROR, nfc_debug_enabled)
<< StringPrintf("%s: fail enable polling; error=0x%X", __func__, status);
return status;
}
if (eeHandle == se.EE_HANDLE_0xF4) //UICC
{
SyncEventGuard guard(mDiscMapEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: mapping intf for UICC", __func__);
status = NFC_DiscoveryMap(NFC_SWP_RD_NUM_INTERFACE_MAP,
(tNCI_DISCOVER_MAPS *) nfc_interface_mapping_uicc,
MposManager::discoveryMapCb);
if (status != NFA_STATUS_OK) {
DLOG_IF(ERROR, nfc_debug_enabled)
<< StringPrintf("%s: fail intf mapping for UICC; error=0x%X", __func__, status);
return status;
}
status = mDiscMapEvent.wait(NFC_CMD_TIMEOUT)?NFA_STATUS_OK:NFA_STATUS_FAILED;
} else if (eeHandle == SecureElement::EE_HANDLE_0xF3) {//ESE
SyncEventGuard guard(mDiscMapEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: mapping intf for ESE", __func__);
status = NFC_DiscoveryMap(NFC_SWP_RD_NUM_INTERFACE_MAP,
(tNCI_DISCOVER_MAPS *) nfc_interface_mapping_ese,
MposManager::discoveryMapCb);
if (status != NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: fail intf mapping for ESE; error=0x%X", __func__, status);
return status;
}
status = mDiscMapEvent.wait(NFC_CMD_TIMEOUT)?NFA_STATUS_OK:NFA_STATUS_FAILED;
} else {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: UNKNOWN SOURCE!!! ", __func__);
return NFA_STATUS_FAILED;
}
return NFA_STATUS_OK;
}
/*******************************************************************************
**
** Function: etsiResetReaderConfig
**
** Description: Configuring from Emvco profile to Nfc forum profile
**
** Returns: Status
**
*******************************************************************************/
tNFA_STATUS MposManager::etsiResetReaderConfig()
{
tNFC_STATUS status = NFA_STATUS_FAILED;
const tNCI_DISCOVER_MAPS nfc_interface_mapping_default[NFC_NUM_INTERFACE_MAP] =
{
/* Protocols that use Frame Interface do not need to be included in the interface mapping */
{ NCI_PROTOCOL_ISO_DEP, NCI_INTERFACE_MODE_POLL_N_LISTEN, NCI_INTERFACE_ISO_DEP },
{ NCI_PROTOCOL_NFC_DEP, NCI_INTERFACE_MODE_POLL_N_LISTEN, NCI_INTERFACE_NFC_DEP },
{ NCI_PROTOCOL_T3T, NCI_INTERFACE_MODE_LISTEN, NCI_INTERFACE_FRAME}
};
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enter", __func__);
status = EmvCo_dosetPoll(false);
if (status != NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: fail enable polling; error=0x%X", __func__, status);
status = NFA_STATUS_FAILED;
} else {
SyncEventGuard guard(mDiscMapEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: mapping intf for DH", __func__);
status = NFC_DiscoveryMap(NFC_NUM_INTERFACE_MAP,
(tNCI_DISCOVER_MAPS *) nfc_interface_mapping_default,
MposManager::discoveryMapCb);
if (status != NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: fail intf mapping for ESE; error=0x%X", __func__, status);
return status;
}
status = mDiscMapEvent.wait(NFC_CMD_TIMEOUT)?NFA_STATUS_OK:NFA_STATUS_FAILED;
}
return status;
}
/*******************************************************************************
**
** Function: notifyEEReaderEvent
**
** Description: Notify with the Reader event
**
** Returns: None
**
*******************************************************************************/
void MposManager::notifyEEReaderEvent (etsi_rd_event_t evt)
{
SecureElement& se = SecureElement::getInstance();
struct timespec mLastRfFieldToggle = se.getLastRfFiledToggleTime();
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; event=%x", __func__, evt);
swp_rdr_req_ntf_info.mMutex.lock();
int ret = clock_gettime(CLOCK_MONOTONIC, &mLastRfFieldToggle);
if (ret == -1) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: clock_gettime failed", __func__);
// There is no good choice here...
}
switch (evt) {
case ETSI_READER_START_SUCCESS:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: ETSI_READER_START_SUCCESS", __func__);
{
mSwpReaderTimer.kill();
/*
* This is to give user a specific time window to wait for card to be found and
* Notify to user if no card found within the give interval of timeout.
*
* configuring timeout.
* */
if (mRdrTagOpTimeout > 0)
mSwpReaderTimer.set(ONE_SECOND_MS * mRdrTagOpTimeout, MposManager::startStopSwpReaderProc);
}
break;
case ETSI_READER_ACTIVATED:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: ETSI_READER_ACTIVATED", __func__);
break;
case ETSI_READER_STOP:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: ETSI_READER_STOP", __func__);
break;
default:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: UNKNOWN EVENT ??", __func__);
break;
}
swp_rdr_req_ntf_info.mMutex.unlock();
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: exit", __func__);
}
/*******************************************************************************
**
** Function: notifyMPOSReaderEvent
**
** Description: Notify the Reader current status event to NFC service
**
** Returns: None
**
*******************************************************************************/
void MposManager::notifyMPOSReaderEvent(mpos_rd_state_t aEvent)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; event type is %s", __FUNCTION__, convertMposEventToString(aEvent));
JNIEnv* e = NULL;
ScopedAttach attach(mNativeData->vm, &e);
if (e == NULL) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: jni env is null", __FUNCTION__);
return;
}
switch(aEvent)
{
case MPOS_READER_MODE_START:
e->CallVoidMethod(mNativeData->manager,
gCachedMposManagerNotifyETSIReaderModeStartConfig,
(uint16_t) swp_rdr_req_ntf_info.swp_rd_req_info.src);
break;
case MPOS_READER_MODE_STOP:
mSwpReaderTimer.kill();
e->CallVoidMethod(mNativeData->manager,
gCachedMposManagerNotifyETSIReaderModeStopConfig,
mDiscNtfTimeout);
break;
case MPOS_READER_MODE_TIMEOUT:
e->CallVoidMethod(mNativeData->manager,
gCachedMposManagerNotifyETSIReaderModeSwpTimeout,
mDiscNtfTimeout);
break;
case MPOS_READER_MODE_RESTART:
e->CallVoidMethod(mNativeData->manager,
gCachedMposManagerNotifyETSIReaderRestart);
break;
default:
break;
}
}
void MposManager::hanldeEtsiReaderReqEvent (tNFA_EE_DISCOVER_REQ* aInfo)
{
/* Handle Reader over SWP.
* 1. Check if the event is for Reader over SWP.
* 2. IF yes than send this info(READER_REQUESTED_EVENT) till FWK level.
* 3. Stop the discovery.
* 4. MAP the proprietary interface for Reader over SWP.NFC_DiscoveryMap, nfc_api.h
* 5. start the discovery with reader req, type and DH configuration.
*
* 6. IF yes than send this info(STOP_READER_EVENT) till FWK level.
* 7. MAP the DH interface for Reader over SWP. NFC_DiscoveryMap, nfc_api.h
* 8. start the discovery with DH configuration.
*/
swp_rdr_req_ntf_info.mMutex.lock();
for (unsigned char xx = 0; xx < aInfo->num_ee; xx++) {
//for each technology (A, B, F, B'), print the bit field that shows
//what protocol(s) is support by that technology
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("EE[%u] Handle: 0x%04x PA: 0x%02x PB: 0x%02x",
xx, aInfo->ee_disc_info[xx].ee_handle, aInfo->ee_disc_info[xx].pa_protocol, aInfo->ee_disc_info[xx].pb_protocol);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("swp_rd_state is %s", convertRdrStateToString(swp_rdr_req_ntf_info.swp_rd_state));
if ((aInfo->ee_disc_info[xx].ee_req_op == NFC_EE_DISC_OP_ADD)
&& (swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOPPED
|| swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_START_CONFIG
|| swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOP_CONFIG)
&& (aInfo->ee_disc_info[xx].pa_protocol == NCI_PROTOCOL_ISO_DEP
|| aInfo->ee_disc_info[xx].pb_protocol == NCI_PROTOCOL_ISO_DEP)) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf( "NFA_RD_SWP_READER_REQUESTED EE[%u] Handle: 0x%04x PA: 0x%02x PB: 0x%02x",
xx, aInfo->ee_disc_info[xx].ee_handle, aInfo->ee_disc_info[xx].pa_protocol, aInfo->ee_disc_info[xx].pb_protocol);
swp_rdr_req_ntf_info.swp_rd_req_info.src = aInfo->ee_disc_info[xx].ee_handle;
swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask = 0;
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = false;
if (!(swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_A)) {
if (aInfo->ee_disc_info[xx].pa_protocol == NCI_PROTOCOL_ISO_DEP) {
swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask |= NFA_TECHNOLOGY_MASK_A;
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = true;
}
}
if (!(swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_B)) {
if (aInfo->ee_disc_info[xx].pb_protocol == NCI_PROTOCOL_ISO_DEP) {
swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask |= NFA_TECHNOLOGY_MASK_B;
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = true;
}
}
if (swp_rdr_req_ntf_info.swp_rd_req_info.reCfg) {
mSwpRdrReqTimer.kill();
if (swp_rdr_req_ntf_info.swp_rd_state != STATE_SE_RDR_MODE_STOP_CONFIG) {
if(swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask != (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B)) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf( "swp_rd_state is %s evt: NFA_RD_SWP_READER_REQUESTED mSwpRdrReqTimer start",
convertRdrStateToString(swp_rdr_req_ntf_info.swp_rd_state));
mSwpRdrReqTimer.set(rdr_req_handling_timeout, readerReqEventNtf);
}
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_START_CONFIG;
}
/*RestartReadermode procedure special case should not de-activate*/
else if (swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOP_CONFIG) {
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_STARTED;
/*RFDEACTIVATE_DISCOVERY*/
NFA_Deactivate(false);
}
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = false;
}
break;
} else if ((aInfo->ee_disc_info[xx].ee_req_op == NFC_EE_DISC_OP_REMOVE)
&& ((swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STARTED)
|| (swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_START_CONFIG)
|| (swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOP_CONFIG)
|| (swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_ACTIVATED))
&& (aInfo->ee_disc_info[xx].pa_protocol == 0xFF
|| aInfo->ee_disc_info[xx].pb_protocol == 0xFF)) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf( "NFA_RD_SWP_READER_STOP EE[%u] Handle: 0x%04x PA: 0x%02x PB: 0x%02x",
xx, aInfo->ee_disc_info[xx].ee_handle, aInfo->ee_disc_info[xx].pa_protocol, aInfo->ee_disc_info[xx].pb_protocol);
if (swp_rdr_req_ntf_info.swp_rd_req_info.src == aInfo->ee_disc_info[xx].ee_handle) {
if (aInfo->ee_disc_info[xx].pa_protocol == 0xFF) {
if (swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_A) {
swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask &= ~NFA_TECHNOLOGY_MASK_A;
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = true;
}
}
if (aInfo->ee_disc_info[xx].pb_protocol == 0xFF) {
if (swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_B) {
swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask &= ~NFA_TECHNOLOGY_MASK_B;
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = true;
}
}
if (swp_rdr_req_ntf_info.swp_rd_req_info.reCfg) {
swp_rdr_req_ntf_info.swp_rd_state = STATE_SE_RDR_MODE_STOP_CONFIG;
mSwpRdrReqTimer.kill();
if(swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("swp_rd_state is %s evt: NFA_RD_SWP_READER_STOP mSwpRdrReqTimer start",
convertRdrStateToString(swp_rdr_req_ntf_info.swp_rd_state));
mSwpRdrReqTimer.set(rdr_req_handling_timeout, readerReqEventNtf);
}
swp_rdr_req_ntf_info.swp_rd_req_info.reCfg = false;
}
}
break;
}
}
swp_rdr_req_ntf_info.mMutex.unlock();
if ((swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask == 0) ||
(swp_rdr_req_ntf_info.swp_rd_req_info.tech_mask == (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B)))
{
if(swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_STOP_CONFIG) {
notifyMPOSReaderEvent(MPOS_READER_MODE_STOP);
}
else if(swp_rdr_req_ntf_info.swp_rd_state == STATE_SE_RDR_MODE_START_CONFIG) {
notifyMPOSReaderEvent(MPOS_READER_MODE_START);
}
}
}
void MposManager::discoveryMapCb (tNFC_DISCOVER_EVT event, tNFC_DISCOVER *p_data)
{
(void) event;
(void) p_data;
SyncEventGuard guard(mMposMgr.mDiscMapEvent);
mMposMgr.mDiscMapEvent.notifyOne();
}
/*******************************************************************************
**
** Function: getSwpRrdReqInfo
**
** Description: get swp_rdr_req_ntf_info
**
** Returns: swp_rdr_req_ntf_info
**
*******************************************************************************/
Rdr_req_ntf_info_t MposManager::getSwpRrdReqInfo()
{
DLOG_IF(ERROR, nfc_debug_enabled)
<< StringPrintf("%s Enter", __func__);
if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_ETSI_READER_ENABLE) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s : nfcNxpEse or ETSI_READER not avaialble.Returning", __func__);
}
return swp_rdr_req_ntf_info;
}
/*******************************************************************************
**
** Function: readerReqEventNtf
**
** Description: This is used to send the reader start or stop request
** event to service
**
** Returns: None
**
*******************************************************************************/
void MposManager::readerReqEventNtf (union sigval)
{
if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_ETSI_READER_ENABLE) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: nfcNxpEse or ETSI_READER not available. Returning", __func__);
return;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: ", __func__);
JNIEnv* e = NULL;
ScopedAttach attach(mMposMgr.mNativeData->vm, &e);
if (e == NULL) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: jni env is null", __func__);
return;
}
Rdr_req_ntf_info_t mSwp_info = mMposMgr.getSwpRrdReqInfo();
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: swp_rdr_req_ntf_info.swp_rd_req_info.src = 0x%4x ", __func__,
mSwp_info.swp_rd_req_info.src);
if (mMposMgr.getEtsiReaederState() == STATE_SE_RDR_MODE_START_CONFIG) {
e->CallVoidMethod(mMposMgr.mNativeData->manager,
mMposMgr.gCachedMposManagerNotifyETSIReaderModeStartConfig,
(uint16_t) mSwp_info.swp_rd_req_info.src);
} else if (mMposMgr.getEtsiReaederState() == STATE_SE_RDR_MODE_STOP_CONFIG) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: mSwpReaderTimer.kill() ", __func__);
mMposMgr.mSwpReaderTimer.kill();
e->CallVoidMethod(mMposMgr.mNativeData->manager,
mMposMgr.gCachedMposManagerNotifyETSIReaderModeStopConfig,
mDiscNtfTimeout);
}
}
/*******************************************************************************
**
** Function: startStopSwpReaderProc
**
** Description: Notify the reader timeout
**
** Returns: None
**
*******************************************************************************/
void MposManager::startStopSwpReaderProc (union sigval)
{
if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_ETSI_READER_ENABLE) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: nfcNxpEse or ETSI_READER not enabled. Returning", __func__);
return;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Timeout!!!", __func__);
mMposMgr.notifyMPOSReaderEvent(MPOS_READER_MODE_TIMEOUT);
}
/*******************************************************************************
**
** Function: etsiReaderReStart
**
** Description: Notify's the mPOS restart event
**
** Returns: void.
**
*******************************************************************************/
void MposManager::etsiReaderReStart()
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf (" %s: Enter",__FUNCTION__);
notifyMPOSReaderEvent(MPOS_READER_MODE_RESTART);
}
/*******************************************************************************
**
** Function: validateHCITransactionEventParams
**
** Description: Decodes the HCI_TRANSACTION_EVT to check for
** reader restart and POWER_OFF evt
**
** Returns: OK/FAILED.
**
*******************************************************************************/
tNFA_STATUS MposManager::validateHCITransactionEventParams(uint8_t *aData, int32_t aDatalen)
{
tNFA_STATUS status = NFA_STATUS_OK;
uint8_t Event, Version, Code;
if(aData != NULL && aDatalen >= 3)
{
Event = *aData++;
Version = *aData++;
Code = *aData;
if(Event == EVENT_RF_ERROR && Version == EVENT_RF_VERSION)
{
if(Code == EVENT_RDR_MODE_RESTART)
{
status = NFA_STATUS_FAILED;
etsiReaderReStart();
}
else
{
}
}
}
else if (aData != NULL && aDatalen == 0x01 && *aData == EVENT_EMV_POWER_OFF)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf ("Power off procedure to be triggered");
unsigned long num;
if (NfcConfig::hasKey(NAME_NFA_CONFIG_FORMAT))
{
num = NfcConfig::getUnsigned(NAME_NFA_CONFIG_FORMAT);
if (num == 0x05)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf ("Power off procedure is triggered");
NFA_Deactivate(false);
}
else
{
//DO nothing
}
}
else
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf ("NAME_NFA_CONFIG_FORMAT not found");
}
}
else
{
}
return status;
}
/*******************************************************************************
**
** Function: convertMposEventToString
**
** Description: Converts the MPOS status events to String format
**
** Returns: Name of the event
**
*******************************************************************************/
const char* MposManager::convertMposEventToString(mpos_rd_state_t aEvent)
{
switch(aEvent)
{
case MPOS_READER_MODE_INVALID:
return "MPOS_READER_MODE_INVALID";
case MPOS_READER_MODE_START:
return "MPOS_READER_MODE_START";
case MPOS_READER_MODE_START_SUCCESS:
return "MPOS_READER_MODE_START_SUCCESS";
case MPOS_READER_MODE_RESTART:
return "MPOS_READER_MODE_RESTART";
case MPOS_READER_MODE_STOP:
return "MPOS_READER_MODE_STOP";
case MPOS_READER_MODE_STOP_SUCCESS:
return "MPOS_READER_MODE_STOP_SUCCESS";
case MPOS_READER_MODE_TIMEOUT:
return "MPOS_READER_MODE_TIMEOUT";
case MPOS_READER_MODE_REMOVE_CARD:
return "MPOS_READER_MODE_REMOVE_CARD";
case MPOS_READER_MODE_RECOVERY:
return "MPOS_READER_MODE_RECOVERY";
case MPOS_READER_MODE_FAIL:
return "MPOS_READER_MODE_FAIL";
default:
return "UNKNOWN";
}
}
/*******************************************************************************
**
** Function: convertRdrStateToString
**
** Description: Converts the MPOS state to String format
**
** Returns: Name of the event
**
*******************************************************************************/
const char* MposManager::convertRdrStateToString(se_rd_req_state_t aState)
{
switch(aState)
{
case STATE_SE_RDR_MODE_INVALID:
return "STATE_SE_RDR_MODE_INVALID";
case STATE_SE_RDR_MODE_START_CONFIG:
return "STATE_SE_RDR_MODE_START_CONFIG";
case STATE_SE_RDR_MODE_START_IN_PROGRESS:
return "STATE_SE_RDR_MODE_START_IN_PROGRESS";
case STATE_SE_RDR_MODE_STARTED:
return "STATE_SE_RDR_MODE_STARTED";
case STATE_SE_RDR_MODE_ACTIVATED:
return "STATE_SE_RDR_MODE_ACTIVATED";
case STATE_SE_RDR_MODE_STOP_CONFIG:
return "STATE_SE_RDR_MODE_STOP_CONFIG";
case STATE_SE_RDR_MODE_STOP_IN_PROGRESS:
return "STATE_SE_RDR_MODE_STOP_IN_PROGRESS";
case STATE_SE_RDR_MODE_STOPPED:
return "STATE_SE_RDR_MODE_STOPPED";
default:
return "UNKNOWN";
}
}
void SetCbStatus(tNFA_STATUS status)
{
gnxpfeature_conf.wstatus = status;
}
tNFA_STATUS GetCbStatus(void)
{
return gnxpfeature_conf.wstatus;
}
static void NxpResponse_Cb(uint8_t event, uint16_t param_len, uint8_t *p_param)
{
(void)event;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NxpResponse_Cb Received length data = 0x%x status = 0x%x", param_len, p_param[3]);
if (p_param != NULL) {
if (p_param[3] == 0x00) {
SetCbStatus(NFA_STATUS_OK);
} else {
SetCbStatus(NFA_STATUS_FAILED);
}
gnxpfeature_conf.rsp_len = (uint8_t)param_len;
if (param_len > 0) {
memcpy(gnxpfeature_conf.rsp_data, p_param, param_len);
}
SyncEventGuard guard(gnxpfeature_conf.NxpFeatureConfigEvt);
gnxpfeature_conf.NxpFeatureConfigEvt.notifyOne();
}
}
/*******************************************************************************
**
** Function: EmvCo_dosetPoll
**
** Description: Enable/disable Emv Co polling
**
** Returns: success/failure
**
*******************************************************************************/
tNFA_STATUS EmvCo_dosetPoll(jboolean enable)
{
tNFA_STATUS status = NFA_STATUS_FAILED;
uint8_t cmd_buf[] ={0x20, 0x02, 0x05, 0x01, 0xA0, 0x44, 0x01, 0x00};
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
SetCbStatus(NFA_STATUS_FAILED);
SyncEventGuard guard (gnxpfeature_conf.NxpFeatureConfigEvt);
if(enable)
{
NFA_SetEmvCoState(true);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("EMV-CO polling profile");
cmd_buf[7] = 0x01; /*EMV-CO Poll*/
}
else
{
NFA_SetEmvCoState(false);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NFC forum polling profile");
}
status = NFA_SendRawVsCommand(sizeof(cmd_buf), cmd_buf, NxpResponse_Cb);
if (status == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Success NFA_SendRawVsCommand", __func__);
gnxpfeature_conf.NxpFeatureConfigEvt.wait(); /* wait for callback */
} else {
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("%s: Failed NFA_SendRawVsCommand", __func__);
}
status = GetCbStatus();
return status;
}