blob: da6a0e19e076994d104ac0663bbc249491225a5b [file] [log] [blame]
/******************************************************************************
*
* Copyright 2018-2021 NXP
*
* 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.
*
******************************************************************************/
#define LOG_TAG "NxpEseHal"
#include <log/log.h>
#include <EseTransport.h>
#include <cutils/properties.h>
#include <ese_config.h>
#include <phNxpEseFeatures.h>
#include <phNxpEsePal.h>
#include <phNxpEseProto7816_3.h>
#include <phNxpEse_Internal.h>
#define RECEIVE_PACKET_SOF 0xA5
#define CHAINED_PACKET_WITHSEQN 0x60
#define CHAINED_PACKET_WITHOUTSEQN 0x20
#define PH_PAL_ESE_PRINT_PACKET_TX(data, len) \
({ phPalEse_print_packet("SEND", data, len); })
#define PH_PAL_ESE_PRINT_PACKET_RX(data, len) \
({ phPalEse_print_packet("RECV", data, len); })
/* 32K(0x8000) Datasize + 10(0xA) Byte Max Header Size + 1 byte negative
* testcase support */
#define MAX_SUPPORTED_DATA_SIZE 0x800B
static int phNxpEse_readPacket(void* pDevHandle, uint8_t* pBuffer,
int nNbBytesToRead);
static int phNxpEse_readPacket_legacy(void* pDevHandle, uint8_t* pBuffer,
int nNbBytesToRead);
static ESESTATUS phNxpEse_checkJcopDwnldState(void);
static ESESTATUS phNxpEse_setJcopDwnldState(phNxpEse_JcopDwnldState state);
static ESESTATUS phNxpEse_checkFWDwnldStatus(void);
static void phNxpEse_GetMaxTimer(unsigned long* pMaxTimer);
static unsigned char* phNxpEse_GgetTimerTlvBuffer(unsigned char* timer_buffer,
unsigned int value);
static __inline bool phNxpEse_isColdResetRequired(phNxpEse_initMode mode,
ESESTATUS status);
static int poll_sof_chained_delay = 0;
static phNxpEse_OsVersion_t sOsVersion = INVALID_OS_VERSION;
/* To Overwrite the value of wtx_counter_limit from config file*/
static unsigned long int app_wtx_cnt = RESET_APP_WTX_COUNT;
/*********************** Global Variables *************************************/
/* ESE Context structure */
phNxpEse_Context_t nxpese_ctxt;
bool ese_debug_enabled = false;
/******************************************************************************
* Function phNxpEse_SetEndPoint_Cntxt
*
* Description This function is called set the SE endpoint
*
* Returns None
*
******************************************************************************/
ESESTATUS phNxpEse_SetEndPoint_Cntxt(uint8_t uEndPoint) {
ESESTATUS status = ESESTATUS_FAILED;
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
status = phNxpEseProto7816_SetEndPoint(uEndPoint);
if (status == ESESTATUS_SUCCESS) {
nxpese_ctxt.nadInfo.nadRx = nadInfoRx_ptr[uEndPoint];
nxpese_ctxt.nadInfo.nadTx = nadInfoTx_ptr[uEndPoint];
nxpese_ctxt.endPointInfo = uEndPoint;
}
ALOGD_IF(ese_debug_enabled, "%s: Enpoint=%d", __FUNCTION__, uEndPoint);
} else {
ALOGE("%s- Function not supported", __FUNCTION__);
}
return status;
}
/******************************************************************************
* Function phNxpEse_ResetEndPoint_Cntxt
*
* Description This function is called to reset the SE endpoint
*
* Returns None
*
******************************************************************************/
ESESTATUS phNxpEse_ResetEndPoint_Cntxt(uint8_t uEndPoint) {
ESESTATUS status = ESESTATUS_FAILED;
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
status = phNxpEseProto7816_ResetEndPoint(uEndPoint);
} else {
ALOGE("%s- Function not supported", __FUNCTION__);
}
return status;
}
/******************************************************************************
* Function phNxpLog_InitializeLogLevel
*
* Description This function is called during phNxpEse_init to initialize
* debug log level.
*
* Returns None
*
******************************************************************************/
void phNxpLog_InitializeLogLevel() {
ese_debug_enabled =
(EseConfig::getUnsigned(NAME_SE_DEBUG_ENABLED, 0) != 0) ? true : false;
char valueStr[PROPERTY_VALUE_MAX] = {0};
int len = property_get("vendor.ese.debug_enabled", valueStr, "");
if (len > 0) {
// let Android property override .conf variable
unsigned debug_enabled = 0;
sscanf(valueStr, "%u", &debug_enabled);
ese_debug_enabled = (debug_enabled == 0) ? false : true;
}
ALOGD_IF(ese_debug_enabled, "%s: level=%u", __func__, ese_debug_enabled);
}
/******************************************************************************
* Function phNxpEse_init
*
* Description This function is called by Jni/phNxpEse_open during the
* initialization of the ESE. It initializes protocol stack
* instance variable
*
* Returns This function return ESESTATUS_SUCCESS (0) in case of
* success In case of failure returns other failure value.
*
******************************************************************************/
ESESTATUS phNxpEse_init(phNxpEse_initParams initParams) {
ESESTATUS wConfigStatus = ESESTATUS_FAILED;
unsigned long int num, ifsd_value = 0;
unsigned long maxTimer = 0;
uint8_t retry = 0;
phNxpEseProto7816InitParam_t protoInitParam;
phNxpEse_memset(&protoInitParam, 0x00, sizeof(phNxpEseProto7816InitParam_t));
/* STATUS_OPEN */
nxpese_ctxt.EseLibStatus = ESE_STATUS_OPEN;
if (app_wtx_cnt > RESET_APP_WTX_COUNT) {
protoInitParam.wtx_counter_limit = app_wtx_cnt;
ALOGD_IF(ese_debug_enabled, "Wtx_counter limit from app setting - %lu",
protoInitParam.wtx_counter_limit);
} else {
protoInitParam.wtx_counter_limit = EseConfig::getUnsigned(
NAME_NXP_WTX_COUNT_VALUE, PH_PROTO_WTX_DEFAULT_COUNT);
ALOGD_IF(ese_debug_enabled, "Wtx_counter read from config file - %lu",
protoInitParam.wtx_counter_limit);
}
if (EseConfig::hasKey(NAME_RNACK_RETRY_DELAY)) {
num = EseConfig::getUnsigned(NAME_RNACK_RETRY_DELAY);
nxpese_ctxt.invalidFrame_Rnack_Delay = num;
ALOGD_IF(ese_debug_enabled, "Rnack retry_delay read from config file - %lu",
num);
} else {
nxpese_ctxt.invalidFrame_Rnack_Delay = 7000;
}
if (EseConfig::hasKey(NAME_NXP_MAX_RNACK_RETRY)) {
protoInitParam.rnack_retry_limit =
EseConfig::getUnsigned(NAME_NXP_MAX_RNACK_RETRY);
} else {
protoInitParam.rnack_retry_limit = MAX_RNACK_RETRY_LIMIT;
}
if (ESE_MODE_NORMAL ==
initParams.initMode) /* TZ/Normal wired mode should come here*/
{
if (EseConfig::hasKey(NAME_NXP_SPI_INTF_RST_ENABLE)) {
protoInitParam.interfaceReset =
(EseConfig::getUnsigned(NAME_NXP_SPI_INTF_RST_ENABLE) == 1) ? true
: false;
} else {
protoInitParam.interfaceReset = true;
}
} else /* OSU mode, no interface reset is required */
{
if (phNxpEse_doResetProtection(true)) {
ALOGE("%s Reset Potection failed. returning...", __FUNCTION__);
return ESESTATUS_FAILED;
}
protoInitParam.interfaceReset = false;
}
if (EseConfig::hasKey(NAME_NXP_WTX_NTF_COUNT)) {
num = EseConfig::getUnsigned(NAME_NXP_WTX_NTF_COUNT);
protoInitParam.wtx_ntf_limit = num;
ALOGD_IF(ese_debug_enabled, "Wtx_ntf limit from config file - %lu",
protoInitParam.wtx_ntf_limit);
} else {
protoInitParam.wtx_ntf_limit = PH_DEFAULT_WTX_NTF_LIMIT;
}
nxpese_ctxt.fPtr_WtxNtf = initParams.fPtr_WtxNtf;
/* Sharing lib context for fetching secure timer values */
protoInitParam.pSecureTimerParams =
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams;
ALOGD_IF(ese_debug_enabled,
"%s secureTimer1 0x%x secureTimer2 0x%x secureTimer3 0x%x",
__FUNCTION__, nxpese_ctxt.secureTimerParams.secureTimer1,
nxpese_ctxt.secureTimerParams.secureTimer2,
nxpese_ctxt.secureTimerParams.secureTimer3);
phNxpEse_GetMaxTimer(&maxTimer);
#ifdef SPM_INTEGRATED
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
wConfigStatus = phNxpEse_SPM_DisablePwrControl(maxTimer);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("%s phNxpEse_SPM_DisablePwrControl: failed", __FUNCTION__);
}
}
#endif
do {
/* T=1 Protocol layer open */
wConfigStatus = phNxpEseProto7816_Open(protoInitParam);
if (phNxpEse_isColdResetRequired(initParams.initMode, wConfigStatus))
phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
} while (phNxpEse_isColdResetRequired(initParams.initMode, wConfigStatus) &&
retry++ < 1);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
if (ESESTATUS_TRANSCEIVE_FAILED == wConfigStatus ||
ESESTATUS_FAILED == wConfigStatus) {
nxpese_ctxt.EseLibStatus = ESE_STATUS_RECOVERY;
}
}
if (ESESTATUS_SUCCESS == wConfigStatus) {
ALOGD_IF(ese_debug_enabled, "phNxpEseProto7816_Open completed >>>>>");
/* Retrieving the IFS-D value configured in the config file and applying to
* Card */
if ((nxpese_ctxt.endPointInfo == END_POINT_ESE) &&
(EseConfig::hasKey(NAME_NXP_ESE_IFSD_VALUE))) {
ifsd_value = EseConfig::getUnsigned(NAME_NXP_ESE_IFSD_VALUE);
if ((0xFFFF > ifsd_value) && (ifsd_value > 0)) {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment requested with %ld",
ifsd_value);
phNxpEse_setIfs(ifsd_value);
} else {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment argument invalid");
}
} else if ((nxpese_ctxt.endPointInfo == END_POINT_EUICC) &&
(EseConfig::hasKey(NAME_NXP_EUICC_IFSD_VALUE))) {
ifsd_value = EseConfig::getUnsigned(NAME_NXP_EUICC_IFSD_VALUE);
if ((0xFFFF > ifsd_value) && (ifsd_value > 0)) {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment requested with %ld",
ifsd_value);
phNxpEse_setIfs(ifsd_value);
} else {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment argument invalid");
}
}
} else {
ALOGE("phNxpEseProto7816_Open failed with status = %x", wConfigStatus);
}
return wConfigStatus;
}
/******************************************************************************
* Function phNxpEse_open
*
* Description This function is called by Jni during the
* initialization of the ESE. It opens the physical connection
* with ESE and creates required NAME_NXP_MAX_RNACK_RETRYclient
* thread for operation.
* Returns This function return ESESTATUS_SUCCESS (0) in case of
* success. In case of failure returns other failure values.
*
******************************************************************************/
ESESTATUS phNxpEse_open(phNxpEse_initParams initParams) {
phPalEse_Config_t tPalConfig;
ESESTATUS wConfigStatus = ESESTATUS_SUCCESS;
unsigned long int num = 0, tpm_enable = 0;
char ese_dev_node[64];
std::string ese_node;
#ifdef SPM_INTEGRATED
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
spm_state_t current_spm_state = SPM_STATE_INVALID;
#endif
/* initialize trace level */
phNxpLog_InitializeLogLevel();
ALOGD_IF(ese_debug_enabled, "phNxpEse_open Enter");
/*When spi channel is already opened return status as FAILED*/
if (nxpese_ctxt.EseLibStatus != ESE_STATUS_CLOSE) {
ALOGD_IF(ese_debug_enabled, "already opened\n");
return ESESTATUS_BUSY;
}
phNxpEse_memset(&nxpese_ctxt, 0x00, sizeof(nxpese_ctxt));
phNxpEse_memset(&tPalConfig, 0x00, sizeof(tPalConfig));
ALOGD_IF(ese_debug_enabled, "MW SEAccessKit Version");
ALOGD_IF(ese_debug_enabled, "Android Version:0x%x", NXP_ANDROID_VER);
ALOGD_IF(ese_debug_enabled, "Major Version:0x%x", ESELIB_MW_VERSION_MAJ);
ALOGD_IF(ese_debug_enabled, "Minor Version:0x%x", ESELIB_MW_VERSION_MIN);
if (EseConfig::hasKey(NAME_NXP_OS_VERSION)) {
num = EseConfig::getUnsigned(NAME_NXP_OS_VERSION);
ALOGD_IF(ese_debug_enabled, "Chip type read from config file - %lu", num);
sOsVersion = (num == 1) ? OS_VERSION_4_0
: ((num == 2) ? OS_VERSION_5_1 : OS_VERSION_5_2);
} else {
sOsVersion = OS_VERSION_5_2;
ALOGD_IF(ese_debug_enabled,
"Chip type not defined in config file osVersion- %d", sOsVersion);
}
if (EseConfig::hasKey(NAME_NXP_TP_MEASUREMENT)) {
tpm_enable = EseConfig::getUnsigned(NAME_NXP_TP_MEASUREMENT);
ALOGD_IF(
ese_debug_enabled,
"SPI Throughput measurement enable/disable read from config file - %lu",
tpm_enable);
} else {
ALOGD_IF(ese_debug_enabled,
"SPI Throughput not defined in config file - %lu", tpm_enable);
}
#if (NXP_POWER_SCHEME_SUPPORT == true)
if (EseConfig::hasKey(NAME_NXP_POWER_SCHEME)) {
num = EseConfig::getUnsigned(NAME_NXP_POWER_SCHEME);
nxpese_ctxt.pwr_scheme = num;
ALOGD_IF(ese_debug_enabled, "Power scheme read from config file - %lu",
num);
} else {
nxpese_ctxt.pwr_scheme = PN67T_POWER_SCHEME;
ALOGD_IF(ese_debug_enabled, "Power scheme not defined in config file - %lu",
num);
}
#else
nxpese_ctxt.pwr_scheme = PN67T_POWER_SCHEME;
tpm_enable = 0x00;
#endif
if (EseConfig::hasKey(NAME_NXP_NAD_POLL_RETRY_TIME)) {
num = EseConfig::getUnsigned(NAME_NXP_NAD_POLL_RETRY_TIME);
nxpese_ctxt.nadPollingRetryTime = num;
} else {
nxpese_ctxt.nadPollingRetryTime = 5;
}
ALOGD_IF(ese_debug_enabled, "Nad poll retry time in us - %lu us",
nxpese_ctxt.nadPollingRetryTime * GET_WAKE_UP_DELAY() *
NAD_POLLING_SCALER);
/*Read device node path*/
ese_node = EseConfig::getString(NAME_NXP_ESE_DEV_NODE, "/dev/pn81a");
strlcpy(ese_dev_node, ese_node.c_str(), sizeof(ese_dev_node));
tPalConfig.pDevName = (int8_t*)ese_dev_node;
/* Initialize PAL layer */
wConfigStatus = phPalEse_open_and_configure(&tPalConfig);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_Init Failed");
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
if (ESESTATUS_DRIVER_BUSY == wConfigStatus)
ALOGE("Ese Driver is Busy!!!");
}
goto clean_and_return;
}
/* Copying device handle to ESE Lib context*/
nxpese_ctxt.pDevHandle = tPalConfig.pDevHandle;
if (ESE_PROTOCOL_MEDIA_SPI == initParams.mediaType) {
ALOGD_IF(ese_debug_enabled,
"Inform eSE about the starting of trusted Mode");
wConfigStatus =
phPalEse_ioctl(phPalEse_e_SetSecureMode, tPalConfig.pDevHandle, 0x01);
if (ESESTATUS_SUCCESS != wConfigStatus) goto clean_and_return_2;
}
#ifdef SPM_INTEGRATED
/* Get the Access of ESE*/
wSpmStatus = phNxpEse_SPM_Init(nxpese_ctxt.pDevHandle);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_Init Failed");
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_2;
}
wSpmStatus = phNxpEse_SPM_SetPwrScheme(nxpese_ctxt.pwr_scheme);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE(" %s : phNxpEse_SPM_SetPwrScheme Failed", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
wConfigStatus = phNxpEse_checkFWDwnldStatus();
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("Failed to open SPI due to VEN pin used by FW download \n");
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
}
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
} else {
if (((current_spm_state & SPM_STATE_SPI) |
(current_spm_state & SPM_STATE_SPI_PRIO)) &&
!(current_spm_state & SPM_STATE_SPI_FAILED)) {
ALOGE(" %s : SPI is already opened...second instance not allowed",
__FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
}
if (current_spm_state & SPM_STATE_JCOP_DWNLD) {
ALOGE(" %s : Denying to open JCOP Download in progress", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
phNxpEse_memcpy(&nxpese_ctxt.initParams, &initParams,
sizeof(phNxpEse_initParams));
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
/* Updating ESE power state based on the init mode */
if (ESE_MODE_OSU == nxpese_ctxt.initParams.initMode) {
ALOGD_IF(ese_debug_enabled, "%s Init mode ---->OSU", __FUNCTION__);
wConfigStatus = phNxpEse_checkJcopDwnldState();
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_checkJcopDwnldState failed");
goto clean_and_return_1;
}
}
}
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_ENABLE);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: enabling power Failed");
if (wSpmStatus == ESESTATUS_BUSY) {
wConfigStatus = ESESTATUS_BUSY;
} else if (wSpmStatus == ESESTATUS_DWNLD_BUSY) {
wConfigStatus = ESESTATUS_DWNLD_BUSY;
} else {
wConfigStatus = ESESTATUS_FAILED;
}
goto clean_and_return;
} else {
ALOGD_IF(ese_debug_enabled, "nxpese_ctxt.spm_power_state true");
nxpese_ctxt.spm_power_state = true;
}
#endif
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
if (tpm_enable) {
wConfigStatus = phPalEse_ioctl(phPalEse_e_EnableThroughputMeasurement,
nxpese_ctxt.pDevHandle, 0);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_IoCtl Failed");
goto clean_and_return;
}
}
}
ALOGD_IF(ese_debug_enabled, "wConfigStatus %x", wConfigStatus);
return wConfigStatus;
clean_and_return:
#ifdef SPM_INTEGRATED
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_DISABLE);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: disabling power Failed");
}
clean_and_return_1:
phNxpEse_SPM_DeInit();
clean_and_return_2:
#endif
if (NULL != nxpese_ctxt.pDevHandle) {
phPalEse_close(nxpese_ctxt.pDevHandle);
phNxpEse_memset(&nxpese_ctxt, 0x00, sizeof(nxpese_ctxt));
}
nxpese_ctxt.EseLibStatus = ESE_STATUS_CLOSE;
nxpese_ctxt.spm_power_state = false;
return ESESTATUS_FAILED;
}
/******************************************************************************
* \ingroup spi_libese
*
* \brief Check if libese has opened
*
* \retval return false if it is close, otherwise true.
**
******************************************************************************/
bool phNxpEse_isOpen() { return nxpese_ctxt.EseLibStatus != ESE_STATUS_CLOSE; }
/******************************************************************************
* Function phNxpEse_openPrioSession
*
* Description This function is called by Jni during the
* initialization of the ESE. It opens the physical connection
* with ESE () and creates required client thread for
* operation. This will get priority access to ESE for timeout
duration.
* Returns This function return ESESTATUS_SUCCESS (0) in case of
success
* In case of failure returns other failure value.
*
******************************************************************************/
ESESTATUS phNxpEse_openPrioSession(phNxpEse_initParams initParams) {
phPalEse_Config_t tPalConfig;
ESESTATUS wConfigStatus = ESESTATUS_SUCCESS;
unsigned long int num = 0, tpm_enable = 0;
/* initialize trace level */
phNxpLog_InitializeLogLevel();
ALOGD_IF(ese_debug_enabled, "phNxpEse_openPrioSession Enter");
#ifdef SPM_INTEGRATED
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
spm_state_t current_spm_state = SPM_STATE_INVALID;
#endif
phNxpEse_memset(&nxpese_ctxt, 0x00, sizeof(nxpese_ctxt));
phNxpEse_memset(&tPalConfig, 0x00, sizeof(tPalConfig));
ALOGD_IF(ese_debug_enabled, "MW SEAccessKit Version");
ALOGD_IF(ese_debug_enabled, "Android Version:0x%x", NXP_ANDROID_VER);
ALOGD_IF(ese_debug_enabled, "Major Version:0x%x", ESELIB_MW_VERSION_MAJ);
ALOGD_IF(ese_debug_enabled, "Minor Version:0x%x", ESELIB_MW_VERSION_MIN);
#if (NXP_POWER_SCHEME_SUPPORT == true)
if (EseConfig::hasKey(NAME_NXP_POWER_SCHEME)) {
num = EseConfig::getUnsigned(NAME_NXP_POWER_SCHEME);
nxpese_ctxt.pwr_scheme = num;
ALOGD_IF(ese_debug_enabled, "Power scheme read from config file - %lu",
num);
} else
#endif
{
nxpese_ctxt.pwr_scheme = PN67T_POWER_SCHEME;
ALOGD_IF(ese_debug_enabled, "Power scheme not defined in config file - %lu",
num);
}
if (EseConfig::hasKey(NAME_NXP_TP_MEASUREMENT)) {
tpm_enable = EseConfig::getUnsigned(NAME_NXP_TP_MEASUREMENT);
ALOGD_IF(
ese_debug_enabled,
"SPI Throughput measurement enable/disable read from config file - %lu",
tpm_enable);
} else {
ALOGD_IF(ese_debug_enabled,
"SPI Throughput not defined in config file - %lu", num);
}
tPalConfig.pDevName = (int8_t*)"/dev/p73";
/* Initialize PAL layer */
wConfigStatus = phPalEse_open_and_configure(&tPalConfig);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_Init Failed");
goto clean_and_return;
}
/* Copying device handle to hal context*/
nxpese_ctxt.pDevHandle = tPalConfig.pDevHandle;
#ifdef SPM_INTEGRATED
/* Get the Access of ESE*/
wSpmStatus = phNxpEse_SPM_Init(nxpese_ctxt.pDevHandle);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_Init Failed");
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_2;
}
wSpmStatus = phNxpEse_SPM_SetPwrScheme(nxpese_ctxt.pwr_scheme);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE(" %s : phNxpEse_SPM_SetPwrScheme Failed", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
} else {
if ((current_spm_state & SPM_STATE_SPI) |
(current_spm_state & SPM_STATE_SPI_PRIO)) {
ALOGE(" %s : SPI is already opened...second instance not allowed",
__FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
if (current_spm_state & SPM_STATE_JCOP_DWNLD) {
ALOGE(" %s : Denying to open JCOP Download in progress", __FUNCTION__);
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
wConfigStatus = phNxpEse_checkFWDwnldStatus();
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"Failed to open SPI due to VEN pin used by FW download \n");
wConfigStatus = ESESTATUS_FAILED;
goto clean_and_return_1;
}
}
}
phNxpEse_memcpy(&nxpese_ctxt.initParams, &initParams.initMode,
sizeof(phNxpEse_initParams));
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
/* Updating ESE power state based on the init mode */
if (ESE_MODE_OSU == nxpese_ctxt.initParams.initMode) {
wConfigStatus = phNxpEse_checkJcopDwnldState();
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_checkJcopDwnldState failed");
goto clean_and_return_1;
}
}
}
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_PRIO_ENABLE);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: enabling power for spi prio Failed");
if (wSpmStatus == ESESTATUS_BUSY) {
wConfigStatus = ESESTATUS_BUSY;
} else if (wSpmStatus == ESESTATUS_DWNLD_BUSY) {
wConfigStatus = ESESTATUS_DWNLD_BUSY;
} else {
wConfigStatus = ESESTATUS_FAILED;
}
goto clean_and_return;
} else {
ALOGE("nxpese_ctxt.spm_power_state true");
nxpese_ctxt.spm_power_state = true;
}
#endif
#ifndef SPM_INTEGRATED
wConfigStatus =
phPalEse_ioctl(phPalEse_e_ResetDevice, nxpese_ctxt.pDevHandle, 2);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_IoCtl Failed");
goto clean_and_return;
}
#endif
wConfigStatus =
phPalEse_ioctl(phPalEse_e_EnableLog, nxpese_ctxt.pDevHandle, 0);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_IoCtl Failed");
goto clean_and_return;
}
wConfigStatus =
phPalEse_ioctl(phPalEse_e_EnablePollMode, nxpese_ctxt.pDevHandle, 1);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_IoCtl Failed");
goto clean_and_return;
}
ALOGD_IF(ese_debug_enabled, "wConfigStatus %x", wConfigStatus);
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
if (tpm_enable) {
wConfigStatus = phPalEse_ioctl(phPalEse_e_EnableThroughputMeasurement,
nxpese_ctxt.pDevHandle, 0);
if (wConfigStatus != ESESTATUS_SUCCESS) {
ALOGE("phPalEse_IoCtl Failed");
goto clean_and_return;
}
}
}
return wConfigStatus;
clean_and_return:
#ifdef SPM_INTEGRATED
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_DISABLE);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: disabling power Failed");
}
clean_and_return_1:
phNxpEse_SPM_DeInit();
clean_and_return_2:
#endif
if (NULL != nxpese_ctxt.pDevHandle) {
phPalEse_close(nxpese_ctxt.pDevHandle);
phNxpEse_memset(&nxpese_ctxt, 0x00, sizeof(nxpese_ctxt));
}
nxpese_ctxt.EseLibStatus = ESE_STATUS_CLOSE;
nxpese_ctxt.spm_power_state = false;
return ESESTATUS_FAILED;
}
/******************************************************************************
* Function phNxpEse_setJcopDwnldState
*
* Description This function is used to check whether JCOP OS
* download can be started or not.
*
* Returns returns ESESTATUS_SUCCESS or ESESTATUS_FAILED
*
******************************************************************************/
static ESESTATUS phNxpEse_setJcopDwnldState(phNxpEse_JcopDwnldState state) {
ESESTATUS wConfigStatus = ESESTATUS_FAILED;
ALOGD_IF(ese_debug_enabled, "phNxpEse_setJcopDwnldState Enter");
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
wConfigStatus = phNxpEse_SPM_SetJcopDwnldState(state);
} else {
ALOGE("%s function not supported", __FUNCTION__);
}
return wConfigStatus;
}
/******************************************************************************
* Function phNxpEse_checkJcopDwnldState
*
* Description This function is used to check whether JCOP OS
* download can be started or not.
*
* Returns returns ESESTATUS_SUCCESS or ESESTATUS_BUSY
*
******************************************************************************/
static ESESTATUS phNxpEse_checkJcopDwnldState(void) {
ALOGD_IF(ese_debug_enabled, "phNxpEse_checkJcopDwnld Enter");
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
spm_state_t current_spm_state = SPM_STATE_INVALID;
uint8_t ese_dwnld_retry = 0x00;
ESESTATUS status = ESESTATUS_FAILED;
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus == ESESTATUS_SUCCESS) {
/* Check current_spm_state and update config/Spm status*/
if ((current_spm_state & SPM_STATE_JCOP_DWNLD) ||
(current_spm_state & SPM_STATE_WIRED))
return ESESTATUS_BUSY;
status = phNxpEse_setJcopDwnldState(JCP_DWNLD_INIT);
if (status == ESESTATUS_SUCCESS) {
while (ese_dwnld_retry < ESE_JCOP_OS_DWNLD_RETRY_CNT) {
ALOGD_IF(ese_debug_enabled, "ESE_JCOP_OS_DWNLD_RETRY_CNT retry count");
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus == ESESTATUS_SUCCESS) {
if ((current_spm_state & SPM_STATE_JCOP_DWNLD)) {
status = ESESTATUS_SUCCESS;
break;
}
} else {
status = ESESTATUS_FAILED;
break;
}
phNxpEse_Sleep(
200000); /*sleep for 200 ms checking for jcop dwnld status*/
ese_dwnld_retry++;
}
}
}
ALOGD_IF(ese_debug_enabled, "phNxpEse_checkJcopDwnldState status %x", status);
return status;
}
/******************************************************************************
* Function phNxpEse_Transceive
*
* Description This function update the len and provided buffer
*
* Returns On Success ESESTATUS_SUCCESS else proper error code
*
******************************************************************************/
ESESTATUS phNxpEse_Transceive(phNxpEse_data* pCmd, phNxpEse_data* pRsp) {
ESESTATUS status = ESESTATUS_FAILED;
if ((NULL == pCmd) || (NULL == pRsp)) return ESESTATUS_INVALID_PARAMETER;
if ((pCmd->len == 0) || pCmd->p_data == NULL) {
ALOGE(" phNxpEse_Transceive - Invalid Parameter no data\n");
return ESESTATUS_INVALID_PARAMETER;
} else if (pCmd->len > MAX_SUPPORTED_DATA_SIZE) {
ALOGE(" phNxpEse_Transceive - Invalid data size \n");
return ESESTATUS_INVALID_RECEIVE_LENGTH;
} else if ((ESE_STATUS_CLOSE == nxpese_ctxt.EseLibStatus)) {
ALOGE(" %s ESE Not Initialized \n", __FUNCTION__);
return ESESTATUS_NOT_INITIALISED;
} else if ((ESE_STATUS_BUSY == nxpese_ctxt.EseLibStatus)) {
ALOGE(" %s ESE - BUSY \n", __FUNCTION__);
return ESESTATUS_BUSY;
} else if ((ESE_STATUS_RECOVERY == nxpese_ctxt.EseLibStatus)) {
ALOGE(" %s ESE - RECOVERY \n", __FUNCTION__);
return ESESTATUS_RECOVERY_STARTED;
} else {
nxpese_ctxt.EseLibStatus = ESE_STATUS_BUSY;
status = phNxpEseProto7816_Transceive((phNxpEse_data*)pCmd,
(phNxpEse_data*)pRsp);
if (ESESTATUS_SUCCESS != status) {
ALOGE(" %s phNxpEseProto7816_Transceive- Failed \n", __FUNCTION__);
if (ESESTATUS_TRANSCEIVE_FAILED == status) {
/*MAX WTX reached*/
nxpese_ctxt.EseLibStatus = ESE_STATUS_RECOVERY;
} else {
/*Timeout/ No response*/
nxpese_ctxt.EseLibStatus = ESE_STATUS_IDLE;
}
} else {
nxpese_ctxt.EseLibStatus = ESE_STATUS_IDLE;
}
nxpese_ctxt.rnack_sent = false;
ALOGD_IF(ese_debug_enabled, " %s Exit status 0x%x \n", __FUNCTION__,
status);
return status;
}
}
/******************************************************************************
* Function phNxpEse_coldReset
*
* Description This function power cycles the ESE
* (cold reset by prop. FW command) interface by
* talking to NFC HAL
*
* Note:
* After cold reset, phNxpEse_init need to be called to
* reset the host AP T=1 stack parameters
*
* Returns It returns ESESTATUS_SUCCESS (0) if the operation is
*successful else
* ESESTATUS_FAILED(1)
******************************************************************************/
ESESTATUS phNxpEse_coldReset(void) {
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
ALOGD_IF(ese_debug_enabled, " %s Enter \n", __FUNCTION__);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
} else {
wSpmStatus = ESESTATUS_FAILED;
ALOGE(" %s Function not supported \n", __FUNCTION__);
}
ALOGD_IF(ese_debug_enabled, " %s Exit status 0x%x \n", __FUNCTION__,
wSpmStatus);
return wSpmStatus;
}
/******************************************************************************
* Function phNxpEse_reset
*
* Description This function reset the ESE interface and free all
*
* Returns It returns ESESTATUS_SUCCESS (0) if the operation is
*successful else
* ESESTATUS_FAILED(1)
******************************************************************************/
ESESTATUS phNxpEse_reset(void) {
ESESTATUS status = ESESTATUS_FAILED;
unsigned long maxTimer = 0;
#ifdef SPM_INTEGRATED
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
#endif
/* TBD : Call the ioctl to reset the ESE */
ALOGD_IF(ese_debug_enabled, " %s Enter \n", __FUNCTION__);
/* Do an interface reset, don't wait to see if JCOP went through a full power
* cycle or not */
status = phNxpEseProto7816_IntfReset(
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams);
if (status) {
ALOGE("%s Ese status Failed", __FUNCTION__);
}
ALOGD_IF(ese_debug_enabled,
"%s secureTimer1 0x%x secureTimer2 0x%x secureTimer3 0x%x",
__FUNCTION__, nxpese_ctxt.secureTimerParams.secureTimer1,
nxpese_ctxt.secureTimerParams.secureTimer2,
nxpese_ctxt.secureTimerParams.secureTimer3);
phNxpEse_GetMaxTimer(&maxTimer);
#ifdef SPM_INTEGRATED
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
status = phNxpEse_SPM_DisablePwrControl(maxTimer);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s phNxpEse_SPM_DisablePwrControl: failed", __FUNCTION__);
}
}
if ((nxpese_ctxt.pwr_scheme == PN67T_POWER_SCHEME) ||
(nxpese_ctxt.pwr_scheme == PN80T_LEGACY_SCHEME)) {
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_RESET);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: reset Failed");
}
}
#else
/* if arg ==2 (hard reset)
* if arg ==1 (soft reset)
*/
status = phPalEse_ioctl(phPalEse_e_ResetDevice, nxpese_ctxt.pDevHandle, 2);
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_reset Failed");
}
#endif
ALOGD_IF(ese_debug_enabled, " %s Exit \n", __FUNCTION__);
return status;
}
/******************************************************************************
* Function phNxpEse_resetJcopUpdate
*
* Description This function reset the ESE interface during JCOP Update
*
* Returns It returns ESESTATUS_SUCCESS (0) if the operation is
*successful else
* ESESTATUS_FAILED(1)
******************************************************************************/
ESESTATUS phNxpEse_resetJcopUpdate(void) {
ESESTATUS status = ESESTATUS_SUCCESS;
uint8_t retry = 0;
#ifdef SPM_INTEGRATED
unsigned long int num = 0;
#endif
/* TBD : Call the ioctl to reset the */
ALOGD_IF(ese_debug_enabled, " %s Enter \n", __FUNCTION__);
/* Reset interface after every reset irrespective of
whether JCOP did a full power cycle or not. */
do {
status = phNxpEseProto7816_Reset();
if (status != ESESTATUS_SUCCESS) phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
} while (status != ESESTATUS_SUCCESS && retry++ < 1);
/* Retrieving the IFS-D value configured in the config file and applying to
* Card */
if (EseConfig::hasKey(NAME_NXP_ESE_IFSD_VALUE)) {
unsigned long int ifsd_value = 0;
ifsd_value = EseConfig::getUnsigned(NAME_NXP_ESE_IFSD_VALUE);
if ((0xFFFF > ifsd_value) && (ifsd_value > 0)) {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment requested with %ld",
ifsd_value);
phNxpEse_setIfs(ifsd_value);
} else {
ALOGD_IF(ese_debug_enabled,
"phNxpEseProto7816_SetIFS IFS adjustment argument invalid");
}
}
#ifdef SPM_INTEGRATED
#if (NXP_POWER_SCHEME_SUPPORT == true)
if (EseConfig::hasKey(NAME_NXP_POWER_SCHEME)) {
num = EseConfig::getUnsigned(NAME_NXP_POWER_SCHEME);
if ((num == 1) || (num == 2)) {
ALOGD_IF(ese_debug_enabled, " %s Call Config Pwr Reset \n", __FUNCTION__);
status = phNxpEse_SPM_ConfigPwr(SPM_POWER_RESET);
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_resetJcopUpdate: reset Failed");
status = ESESTATUS_FAILED;
}
} else if (num == 3) {
ALOGD_IF(ese_debug_enabled, " %s Call eSE Chip Reset \n", __FUNCTION__);
status = phNxpEse_chipReset();
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_resetJcopUpdate: chip reset Failed");
status = ESESTATUS_FAILED;
}
} else {
ALOGD_IF(ese_debug_enabled, " %s Invalid Power scheme \n", __FUNCTION__);
}
}
#else
{
status = phNxpEse_SPM_ConfigPwr(SPM_POWER_RESET);
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: reset Failed");
status = ESESTATUS_FAILED;
}
}
#endif
#else
/* if arg ==2 (hard reset)
* if arg ==1 (soft reset)
*/
status = phPalEse_ioctl(phPalEse_e_ResetDevice, nxpese_ctxt.pDevHandle, 2);
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_resetJcopUpdate Failed");
}
#endif
ALOGD_IF(ese_debug_enabled, " %s Exit \n", __FUNCTION__);
return status;
}
/******************************************************************************
* Function phNxpEse_EndOfApdu
*
* Description This function is used to send S-frame to indicate
*END_OF_APDU
*
* Returns It returns ESESTATUS_SUCCESS (0) if the operation is
*successful else
* ESESTATUS_FAILED(1)
*
******************************************************************************/
ESESTATUS phNxpEse_EndOfApdu(void) {
ESESTATUS status = ESESTATUS_SUCCESS;
#if (NXP_ESE_END_OF_SESSION == true)
status = phNxpEseProto7816_Close(
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams);
#endif
return status;
}
/******************************************************************************
* Function phNxpEse_chipReset
*
* Description This function is used to reset the ESE.
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
ESESTATUS phNxpEse_chipReset(void) {
ESESTATUS status = ESESTATUS_FAILED;
ESESTATUS bStatus = ESESTATUS_FAILED;
if (nxpese_ctxt.pwr_scheme == PN80T_EXT_PMU_SCHEME) {
bStatus = phNxpEseProto7816_Reset();
if (!bStatus) {
ALOGE("Inside phNxpEse_chipReset, phNxpEseProto7816_Reset Failed");
}
status = phPalEse_ioctl(phPalEse_e_ChipRst, nxpese_ctxt.pDevHandle, 6);
if (status != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_chipReset Failed");
}
} else {
ALOGD_IF(ese_debug_enabled,
"phNxpEse_chipReset is not supported in legacy power scheme");
}
return status;
}
/******************************************************************************
* Function phNxpEse_GetOsMode
*
* Description This function is used to get OS mode(JCOP/OSU)
*
* Returns 0x01 : JCOP_MODE
* 0x02 : OSU_MODE
*
******************************************************************************/
phNxpEseProto7816_OsType_t phNxpEse_GetOsMode(void) {
return phNxpEseProto7816_GetOsMode();
}
/******************************************************************************
* Function phNxpEse_isColdResetRequired
*
* Description This function determines whether hard reset recovery is
* required or not on protocol recovery failure.
* Returns TRUE(required)/FALSE(not required).
*
******************************************************************************/
static __inline bool phNxpEse_isColdResetRequired(phNxpEse_initMode mode,
ESESTATUS status) {
return (mode == ESE_MODE_OSU && status != ESESTATUS_SUCCESS);
}
/******************************************************************************
* Function phNxpEse_doResetProtection
*
* Description This function enables/disables reset protection
*
* Returns SUCCESS(0)/FAIL(-1).
*
******************************************************************************/
ESESTATUS phNxpEse_doResetProtection(bool flag) {
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
ALOGD_IF(ese_debug_enabled, " %s Enter \n", __FUNCTION__);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
wSpmStatus = phPalEse_ioctl(phPalEse_e_ResetProtection,
nxpese_ctxt.pDevHandle, flag);
} else {
wSpmStatus = ESESTATUS_FAILED;
ALOGE(" %s Function not supported \n", __FUNCTION__);
}
ALOGD_IF(ese_debug_enabled, " %s Exit status 0x%x \n", __FUNCTION__,
wSpmStatus);
return wSpmStatus;
}
/******************************************************************************
* Function phNxpEse_deInit
*
* Description This function de-initializes all the ESE protocol params
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
ESESTATUS phNxpEse_deInit(void) {
ESESTATUS status = ESESTATUS_SUCCESS;
unsigned long maxTimer = 0;
unsigned long num = 0;
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0 &&
(ESE_STATUS_RECOVERY == nxpese_ctxt.EseLibStatus) &&
ESE_PROTOCOL_MEDIA_SPI != nxpese_ctxt.initParams.mediaType) {
return status;
}
if (nxpese_ctxt.initParams.initMode == ESE_MODE_OSU) {
phNxpEse_doResetProtection(false);
}
/*TODO : to be removed after JCOP fix*/
if (EseConfig::hasKey(NAME_NXP_VISO_DPD_ENABLED)) {
num = EseConfig::getUnsigned(NAME_NXP_VISO_DPD_ENABLED);
}
if (num == 0 && nxpese_ctxt.nadInfo.nadRx == EUICC_NAD_RX) {
// do nothing
} else {
status = phNxpEseProto7816_Close(
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams);
if (status == ESESTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s secureTimer1 0x%x secureTimer2 0x%x secureTimer3 0x%x",
__FUNCTION__, nxpese_ctxt.secureTimerParams.secureTimer1,
nxpese_ctxt.secureTimerParams.secureTimer2,
nxpese_ctxt.secureTimerParams.secureTimer3);
phNxpEse_GetMaxTimer(&maxTimer);
#ifdef SPM_INTEGRATED
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
status = phNxpEse_SPM_DisablePwrControl(maxTimer);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s phNxpEseP61_DisablePwrCntrl: failed", __FUNCTION__);
}
} else {
ALOGD_IF(ese_debug_enabled, "Interface reset for DPD");
status = phNxpEseProto7816_IntfReset(
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s IntfReset Failed ", __FUNCTION__);
}
}
#endif
}
}
return status;
}
/******************************************************************************
* Function phNxpEse_close
*
* Description This function close the ESE interface and free all
* resources.
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
ESESTATUS phNxpEse_close(ESESTATUS deInitStatus) {
ESESTATUS status = ESESTATUS_SUCCESS;
ALOGD_IF(ese_debug_enabled, "phNxpEse_close Enter");
if ((ESE_STATUS_CLOSE == nxpese_ctxt.EseLibStatus)) {
ALOGE(" %s ESE Not Initialized \n", __FUNCTION__);
return ESESTATUS_NOT_INITIALISED;
}
#ifdef SPM_INTEGRATED
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
#endif
#ifdef SPM_INTEGRATED
/* Release the Access of */
wSpmStatus = phNxpEse_SPM_ConfigPwr(SPM_POWER_DISABLE);
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_ConfigPwr: disabling power Failed");
} else {
nxpese_ctxt.spm_power_state = false;
}
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
if (ESE_MODE_OSU == nxpese_ctxt.initParams.initMode) {
status = phNxpEse_setJcopDwnldState(JCP_SPI_DWNLD_COMPLETE);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s: phNxpEse_setJcopDwnldState failed", __FUNCTION__);
}
}
} else {
if (NULL != nxpese_ctxt.pDevHandle) {
if (ESE_PROTOCOL_MEDIA_SPI == nxpese_ctxt.initParams.mediaType) {
ALOGD_IF(ese_debug_enabled, "Inform eSE that trusted Mode is over");
status = phPalEse_ioctl(phPalEse_e_SetSecureMode,
nxpese_ctxt.pDevHandle, 0x00);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s: phPalEse_e_SetSecureMode failed", __FUNCTION__);
}
if (ESESTATUS_SUCCESS != phNxpEseProto7816_CloseAllSessions()) {
ALOGD_IF(ese_debug_enabled, "eSE not responding perform hard reset");
phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
}
} else {
if (nxpese_ctxt.EseLibStatus == ESE_STATUS_RECOVERY ||
(deInitStatus == ESESTATUS_RESPONSE_TIMEOUT) ||
ESESTATUS_SUCCESS != phNxpEseProto7816_CloseAllSessions()) {
ALOGD_IF(ese_debug_enabled, "eSE not responding perform hard reset");
phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
}
}
ALOGD_IF(ese_debug_enabled, "Interface reset for DPD");
status = phNxpEseProto7816_IntfReset(
(phNxpEseProto7816SecureTimer_t*)&nxpese_ctxt.secureTimerParams);
if (status == ESESTATUS_TRANSCEIVE_FAILED || status == ESESTATUS_FAILED) {
ALOGE("%s IntfReset Failed, perform hard reset", __FUNCTION__);
// max wtx or no response of interface reset after protocol recovery
phNxpEse_SPM_ConfigPwr(SPM_RECOVERY_RESET);
}
}
}
wSpmStatus = phNxpEse_SPM_DeInit();
if (wSpmStatus != ESESTATUS_SUCCESS) {
ALOGE("phNxpEse_SPM_DeInit Failed");
}
#endif
if (NULL != nxpese_ctxt.pDevHandle) {
phPalEse_close(nxpese_ctxt.pDevHandle);
phNxpEse_memset(&nxpese_ctxt, 0x00, sizeof(nxpese_ctxt));
ALOGD_IF(ese_debug_enabled,
"phNxpEse_close - ESE Context deinit completed");
}
/* Return success always */
return status;
}
/******************************************************************************
* Function phNxpEse_read
*
* Description This function write the data to ESE through physical
* interface (e.g. I2C) using the driver interface.
* Before sending the data to ESE, phNxpEse_write_ext
* is called to check if there is any extension processing
* is required for the SPI packet being sent out.
*
* Returns It returns ESESTATUS_SUCCESS (0) if read successful else
* ESESTATUS_FAILED(1)
*
******************************************************************************/
ESESTATUS phNxpEse_read(uint32_t* data_len, uint8_t** pp_data) {
ESESTATUS status = ESESTATUS_SUCCESS;
int ret = -1;
ALOGD_IF(ese_debug_enabled, "%s Enter ..", __FUNCTION__);
ret = phNxpEse_readPacket(nxpese_ctxt.pDevHandle, nxpese_ctxt.p_read_buff,
MAX_DATA_LEN);
if (ret < 0) {
ALOGE("PAL Read status error status = %x", status);
*data_len = 2;
*pp_data = nxpese_ctxt.p_read_buff;
status = ESESTATUS_FAILED;
} else {
PH_PAL_ESE_PRINT_PACKET_RX(nxpese_ctxt.p_read_buff, (uint16_t)ret);
*data_len = ret;
*pp_data = nxpese_ctxt.p_read_buff;
status = ESESTATUS_SUCCESS;
}
ALOGD_IF(ese_debug_enabled, "%s Exit", __FUNCTION__);
return status;
}
/******************************************************************************
* Function phNxpEse_readPacket
*
* Description This function Reads requested number of bytes from
* pn547 device into given buffer.
*
* Returns nNbBytesToRead- number of successfully read bytes
* -1 - read operation failure
*
******************************************************************************/
static int phNxpEse_readPacket(void* pDevHandle, uint8_t* pBuffer,
int nNbBytesToRead) {
bool flushData = false;
int ret = -1;
int sof_counter = 0; /* one read may take 1 ms*/
int total_count = 0, numBytesToRead = 0, headerIndex = 0;
ALOGD_IF(ese_debug_enabled, "%s Enter", __FUNCTION__);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
int max_sof_counter = 0;
/*Max retry to get SOF in case of chaining*/
if (poll_sof_chained_delay == 1) {
/*Wait Max for 1.3 sec before retry/recvoery*/
/*(max_sof_counter(1300) * 10 us) = 1.3 sec */
max_sof_counter = ESE_POLL_TIMEOUT * 10;
}
/*Max retry to get SOF in case of Non-chaining*/
else {
/*wait based on config option */
/*(nadPollingRetryTime * WAKE_UP_DELAY_SN1xx * NAD_POLLING_SCALER_SN1xx)*/
max_sof_counter = ((ESE_POLL_TIMEOUT * 1000) /
(nxpese_ctxt.nadPollingRetryTime *
GET_WAKE_UP_DELAY() * NAD_POLLING_SCALER));
}
if (nxpese_ctxt.rnack_sent) {
phPalEse_sleep(nxpese_ctxt.invalidFrame_Rnack_Delay);
}
ALOGD_IF(ese_debug_enabled,
"read() max_sof_counter: "
"%X ESE_POLL_TIMEOUT %2X",
max_sof_counter, ESE_POLL_TIMEOUT);
do {
ret = -1;
ret = phPalEse_read(pDevHandle, pBuffer, 2);
if (ret < 0) {
/*Polling for read on spi, hence Debug log*/
ALOGD_IF(ese_debug_enabled, "_spi_read() [HDR]errno : %x ret : %X",
errno, ret);
} else {
if ((pBuffer[0] == nxpese_ctxt.nadInfo.nadRx) ||
(pBuffer[0] == RECEIVE_PACKET_SOF)) {
/* Read the HEADR of one byte*/
ALOGD_IF(ese_debug_enabled, "%s Read HDR SOF + PCB", __FUNCTION__);
numBytesToRead = 1; /*Read only INF LEN*/
headerIndex = 1;
break;
} else if (((pBuffer[0] == 0x00) || (pBuffer[0] == 0xFF)) &&
((pBuffer[1] == nxpese_ctxt.nadInfo.nadRx) ||
(pBuffer[1] == RECEIVE_PACKET_SOF))) {
/* Read the HEADR of Two bytes*/
ALOGD_IF(ese_debug_enabled, "%s Read HDR only SOF", __FUNCTION__);
pBuffer[0] = pBuffer[1];
numBytesToRead = 2; /*Read PCB + INF LEN*/
headerIndex = 0;
break;
} else if (((pBuffer[0] == 0x00) && (pBuffer[1] == 0x00)) ||
((pBuffer[0] == 0xFF) && (pBuffer[1] == 0xFF))) {
// LOG(ERROR) << StringPrintf("_spi_read() Buf[0]: %X Buf[1]: %X",
// pBuffer[0], pBuffer[1]);
} else if (ret >= 0) { /* Corruption happened during the receipt from
Card, go flush out the data */
ALOGE("_spi_read() Corruption Buf[0]: %X Buf[1]: %X ..len=%d",
pBuffer[0], pBuffer[1], ret);
break;
}
}
/*If it is Chained packet wait for 100 usec*/
if (poll_sof_chained_delay == 1) {
ALOGD_IF(ese_debug_enabled, "%s Chained Pkt, delay read %dus",
__FUNCTION__, GET_WAKE_UP_DELAY() * CHAINED_PKT_SCALER);
phPalEse_sleep(GET_WAKE_UP_DELAY() * CHAINED_PKT_SCALER);
} else {
/*DLOG_IF(INFO, ese_debug_enabled)
<< StringPrintf("%s Normal Pkt, delay read %dus", __FUNCTION__,
WAKE_UP_DELAY_SN1xx * NAD_POLLING_SCALER_SN1xx);*/
phPalEse_sleep(nxpese_ctxt.nadPollingRetryTime * GET_WAKE_UP_DELAY() *
NAD_POLLING_SCALER);
}
sof_counter++;
} while (sof_counter < max_sof_counter);
/*SOF Read timeout happened, go for frame retransmission*/
if (sof_counter == max_sof_counter) {
ret = -1;
}
if (ret < 0) {
/*In case of IO Error*/
ret = -2;
pBuffer[0] = 0x64;
pBuffer[1] = 0xFF;
} else if ((pBuffer[0] == nxpese_ctxt.nadInfo.nadRx) ||
(pBuffer[0] == RECEIVE_PACKET_SOF)) {
ALOGD_IF(ese_debug_enabled, "%s SOF FOUND", __FUNCTION__);
/* Read the HEADR of one/Two bytes based on how two bytes read A5 PCB or
* 00 A5*/
ret =
phPalEse_read(pDevHandle, &pBuffer[1 + headerIndex], numBytesToRead);
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
flushData = true;
} else {
if ((pBuffer[1] == CHAINED_PACKET_WITHOUTSEQN) ||
(pBuffer[1] == CHAINED_PACKET_WITHSEQN)) {
poll_sof_chained_delay = 1;
ALOGD_IF(ese_debug_enabled, "poll_sof_chained_delay value is %d ",
poll_sof_chained_delay);
} else {
poll_sof_chained_delay = 0;
ALOGD_IF(ese_debug_enabled, "poll_sof_chained_delay value is %d ",
poll_sof_chained_delay);
}
total_count = 3;
uint8_t pcb;
phNxpEseProto7816_PCB_bits_t pcb_bits;
pcb = pBuffer[PH_PROPTO_7816_PCB_OFFSET];
phNxpEse_memset(&pcb_bits, 0x00, sizeof(phNxpEseProto7816_PCB_bits_t));
phNxpEse_memcpy(&pcb_bits, &pcb, sizeof(uint8_t));
/*For I-Frame Only*/
if (0 == pcb_bits.msb) {
if (pBuffer[2] != EXTENDED_FRAME_MARKER) {
nNbBytesToRead = (pBuffer[2] & 0x000000FF);
headerIndex = 3;
} else {
ret = phPalEse_read(pDevHandle, &pBuffer[3], 2);
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
flushData = true;
} else {
nNbBytesToRead = (pBuffer[3] << 8);
nNbBytesToRead = nNbBytesToRead | pBuffer[4];
/*If I-Frame received with invalid length respond with RNACK*/
if ((nNbBytesToRead == 0) || (nNbBytesToRead > MAX_DATA_LEN) ||
(nNbBytesToRead > phNxpEseProto7816_GetIfs())) {
ALOGD_IF(ese_debug_enabled, "I-Frame with invalid len == %d",
nNbBytesToRead);
flushData = true;
} else {
ALOGE("_spi_read() [HDR]EXTENDED_FRAME_MARKER, ret=%d", ret);
total_count += 2;
headerIndex = 5;
}
}
}
} else {
/*For Non-IFrame*/
nNbBytesToRead = (pBuffer[2] & 0x000000FF);
headerIndex = 3;
}
if (!flushData) {
/* Read the Complete data + one byte CRC*/
ret = phPalEse_read(pDevHandle, &pBuffer[headerIndex],
(nNbBytesToRead + 1));
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
ret = -1;
} else {
ret = (total_count + (nNbBytesToRead + 1));
}
nxpese_ctxt.rnack_sent = false;
}
}
} else {
flushData = true;
}
if (flushData) {
/* Received corrupted frame:
Flushing out data in the Rx buffer so that Card can switch the mode */
uint16_t ifsd_size = phNxpEseProto7816_GetIfs();
uint32_t total_frame_size = 0;
ALOGE("_spi_read() corrupted, IFSD size=%d flushing it out!!", ifsd_size);
/* If a non-zero byte is received while polling for NAD byte and the byte
is not a valid NAD byte (0xA5 or 0xB4): 1) Read & discard (without
de-asserting SPI CS line) : a. Max IFSD size + 5 (remaining four
prologue + one LRC bytes) bytes from eSE if max IFS size is greater
than 254 bytes OR b. Max IFSD size + 3 (remaining two prologue + one
LRC bytes) bytes from eSE if max IFS size is less than 255 bytes.
2) Send R-NACK to request eSE to re-transmit the frame*/
if (ifsd_size > IFSC_SIZE_SEND) {
total_frame_size = ifsd_size + 4;
} else {
total_frame_size = ifsd_size + 2;
}
nxpese_ctxt.rnack_sent = true;
phPalEse_sleep(nxpese_ctxt.invalidFrame_Rnack_Delay);
ret = phPalEse_read(pDevHandle, &pBuffer[2], total_frame_size);
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
} else { /* LRC fail expected for this frame to send R-NACK*/
ALOGD_IF(
ese_debug_enabled,
"_spi_read() SUCCESS ret : %X LRC fail excpected for this frame",
ret);
PH_PAL_ESE_PRINT_PACKET_RX(pBuffer, ret);
}
pBuffer[0] = 0x90;
pBuffer[1] = RECEIVE_PACKET_SOF;
ret = 0x02;
phPalEse_sleep(nxpese_ctxt.invalidFrame_Rnack_Delay);
}
} else {
ret = phNxpEse_readPacket_legacy(pDevHandle, pBuffer, nNbBytesToRead);
}
ALOGD_IF(ese_debug_enabled, "%s Exit ret = %d", __FUNCTION__, ret);
return ret;
}
/******************************************************************************
* Function phNxpEse_readPacket_legacy
*
* Description This function Reads requested number of bytes from
* pn547 device into given buffer.
*
* Returns nNbBytesToRead- number of successfully read bytes
* -1 - read operation failure
*
******************************************************************************/
static int phNxpEse_readPacket_legacy(void* pDevHandle, uint8_t* pBuffer,
int nNbBytesToRead) {
int ret = -1;
int sof_counter = 0; /* one read may take 1 ms*/
int total_count = 0, numBytesToRead = 0, headerIndex = 0;
do {
sof_counter++;
ret = -1;
ret = phPalEse_read(pDevHandle, pBuffer, 2);
if (ret < 0) {
/*Polling for read on spi, hence Debug log*/
ALOGD_IF(ese_debug_enabled, "_spi_read() [HDR]errno : %x ret : %X", errno,
ret);
}
if (pBuffer[0] == RECEIVE_PACKET_SOF) {
/* Read the HEADR of one byte*/
ALOGD_IF(ese_debug_enabled, "%s Read HDR", __FUNCTION__);
numBytesToRead = 1;
headerIndex = 1;
break;
} else if (pBuffer[1] == RECEIVE_PACKET_SOF) {
/* Read the HEADR of Two bytes*/
ALOGD_IF(ese_debug_enabled, "%s Read HDR", __FUNCTION__);
pBuffer[0] = RECEIVE_PACKET_SOF;
numBytesToRead = 2;
headerIndex = 0;
break;
}
/*If it is Chained packet wait for 100 usec*/
if (poll_sof_chained_delay == 1) {
ALOGD_IF(ese_debug_enabled, "%s Chained Pkt, delay read %dus",
__FUNCTION__, GET_WAKE_UP_DELAY() * CHAINED_PKT_SCALER);
phPalEse_sleep(GET_WAKE_UP_DELAY() * CHAINED_PKT_SCALER);
} else {
ALOGD_IF(ese_debug_enabled, "%s Normal Pkt, delay read %dus",
__FUNCTION__, GET_WAKE_UP_DELAY() * NAD_POLLING_SCALER);
phPalEse_sleep(GET_WAKE_UP_DELAY() * NAD_POLLING_SCALER);
}
} while (sof_counter < ESE_NAD_POLLING_MAX);
if (pBuffer[0] == RECEIVE_PACKET_SOF) {
ALOGD_IF(ese_debug_enabled, "%s SOF FOUND", __FUNCTION__);
/* Read the HEADR of one/Two bytes based on how two bytes read A5 PCB or
* 00 A5*/
ret = phPalEse_read(pDevHandle, &pBuffer[1 + headerIndex], numBytesToRead);
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
}
if ((pBuffer[1] == CHAINED_PACKET_WITHOUTSEQN) ||
(pBuffer[1] == CHAINED_PACKET_WITHSEQN)) {
poll_sof_chained_delay = 1;
ALOGD_IF(ese_debug_enabled, "poll_sof_chained_delay value is %d ",
poll_sof_chained_delay);
} else {
poll_sof_chained_delay = 0;
ALOGD_IF(ese_debug_enabled, "poll_sof_chained_delay value is %d ",
poll_sof_chained_delay);
}
total_count = 3;
nNbBytesToRead = (pBuffer[2] & 0x000000FF);
/* Read the Complete data + one byte CRC*/
ret = phPalEse_read(pDevHandle, &pBuffer[3], (nNbBytesToRead + 1));
if (ret < 0) {
ALOGE("_spi_read() [HDR]errno : %x ret : %X", errno, ret);
ret = -1;
} else {
ret = (total_count + (nNbBytesToRead + 1));
}
} else if (ret < 0) {
/*In case of IO Error*/
ret = -2;
pBuffer[0] = 0x64;
pBuffer[1] = 0xFF;
} else {
ret = -1;
}
return ret;
}
/******************************************************************************
* Function phNxpEse_WriteFrame
*
* Description This is the actual function which is being called by
* phNxpEse_write. This function writes the data to ESE.
* It waits till write callback provide the result of write
* process.
*
* Returns It returns ESESTATUS_SUCCESS (0) if write successful else
* ESESTATUS_FAILED(1)
*
******************************************************************************/
ESESTATUS phNxpEse_WriteFrame(uint32_t data_len, uint8_t* p_data) {
ESESTATUS status = ESESTATUS_INVALID_PARAMETER;
int32_t dwNoBytesWrRd = 0;
ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
/* TODO where to set the nad id */
p_data[0] = nxpese_ctxt.nadInfo.nadTx;
} else {
p_data[0] = ESE_NAD_TX;
}
/* Create local copy of cmd_data */
phNxpEse_memcpy(nxpese_ctxt.p_cmd_data, p_data, data_len);
nxpese_ctxt.cmd_len = data_len;
dwNoBytesWrRd = phPalEse_write(nxpese_ctxt.pDevHandle, nxpese_ctxt.p_cmd_data,
nxpese_ctxt.cmd_len);
if (-1 == dwNoBytesWrRd) {
ALOGE(" - Error in SPI Write.....%d\n", errno);
status = ESESTATUS_FAILED;
} else {
status = ESESTATUS_SUCCESS;
PH_PAL_ESE_PRINT_PACKET_TX(nxpese_ctxt.p_cmd_data, nxpese_ctxt.cmd_len);
}
ALOGD_IF(ese_debug_enabled, "Exit %s status %x\n", __FUNCTION__, status);
return status;
}
/******************************************************************************
* Function phNxpEse_getAtr
*
* Description This function retrieves ATR bytes from 7816-3 layer
*Update.
*
* Returns It returns ESESTATUS_SUCCESS (0) if write successful else
* ESESTATUS_FAILED(1
*
******************************************************************************/
ESESTATUS phNxpEse_getAtr(phNxpEse_data* pATR) {
ESESTATUS status = ESESTATUS_FAILED;
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
status = phNxpEseProto7816_getAtr(pATR);
} else {
ALOGE(" %s - Function not supported\n", __FUNCTION__);
}
return status;
}
/******************************************************************************
* Function phNxpEse_setIfs
*
* Description This function sets the IFS size to 240/254 support JCOP OS
*Update.
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
ESESTATUS phNxpEse_setIfs(uint16_t IFS_Size) {
phNxpEseProto7816_SetIfs(IFS_Size);
return ESESTATUS_SUCCESS;
}
/******************************************************************************
* Function phNxpEse_Sleep
*
* Description This function suspends execution of the calling thread for
* (at least) usec microseconds
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
ESESTATUS phNxpEse_Sleep(uint32_t usec) {
phPalEse_sleep(usec);
return ESESTATUS_SUCCESS;
}
/******************************************************************************
* Function phNxpEse_memset
*
* Description This function updates destination buffer with val
* data in len size
*
* Returns Always return ESESTATUS_SUCCESS (0).
*
******************************************************************************/
void* phNxpEse_memset(void* buff, int val, size_t len) {
return phPalEse_memset(buff, val, len);
}
/******************************************************************************
* Function phNxpEse_memcpy
*
* Description This function copies source buffer to destination buffer
* data in len size
*
* Returns Return pointer to allocated memory location.
*
******************************************************************************/
void* phNxpEse_memcpy(void* dest, const void* src, size_t len) {
return phPalEse_memcpy(dest, src, len);
}
/******************************************************************************
* Function phNxpEse_Memalloc
*
* Description This function allocation memory
*
* Returns Return pointer to allocated memory or NULL.
*
******************************************************************************/
void* phNxpEse_memalloc(uint32_t size) {
return phPalEse_memalloc(size);
;
}
/******************************************************************************
* Function phNxpEse_calloc
*
* Description This is utility function for runtime heap memory allocation
*
* Returns Return pointer to allocated memory or NULL.
*
******************************************************************************/
void* phNxpEse_calloc(size_t datatype, size_t size) {
return phPalEse_calloc(datatype, size);
}
/******************************************************************************
* Function phNxpEse_free
*
* Description This function de-allocation memory
*
* Returns void.
*
******************************************************************************/
void phNxpEse_free(void* ptr) { return phPalEse_free(ptr); }
/******************************************************************************
* Function phNxpEse_GetMaxTimer
*
* Description This function finds out the max. timer value returned from
*JCOP
*
* Returns void.
*
******************************************************************************/
static void phNxpEse_GetMaxTimer(unsigned long* pMaxTimer) {
/* Finding the max. of the timer value */
*pMaxTimer = nxpese_ctxt.secureTimerParams.secureTimer1;
if (*pMaxTimer < nxpese_ctxt.secureTimerParams.secureTimer2)
*pMaxTimer = nxpese_ctxt.secureTimerParams.secureTimer2;
*pMaxTimer = (*pMaxTimer < nxpese_ctxt.secureTimerParams.secureTimer3)
? (nxpese_ctxt.secureTimerParams.secureTimer3)
: *pMaxTimer;
/* Converting timer to millisecond from sec */
*pMaxTimer = SECOND_TO_MILLISECOND(*pMaxTimer);
/* Add extra 5% to the timer */
*pMaxTimer +=
CONVERT_TO_PERCENTAGE(*pMaxTimer, ADDITIONAL_SECURE_TIME_PERCENTAGE);
ALOGD_IF(ese_debug_enabled, "%s Max timer value = %lu", __FUNCTION__,
*pMaxTimer);
return;
}
/******************************************************************************
* Function phNxpEseP61_DisablePwrCntrl
*
* Description This function disables eSE GPIO power off/on control
* when enabled
*
* Returns SUCCESS/FAIL.
*
******************************************************************************/
ESESTATUS phNxpEse_DisablePwrCntrl(void) {
ESESTATUS status = ESESTATUS_SUCCESS;
unsigned long maxTimer = 0;
ALOGE("%s Enter", __FUNCTION__);
phNxpEse_GetMaxTimer(&maxTimer);
if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
status = phNxpEse_SPM_DisablePwrControl(maxTimer);
if (status != ESESTATUS_SUCCESS) {
ALOGE("%s phNxpEseP61_DisablePwrCntrl: failed", __FUNCTION__);
}
} else {
ALOGE("%s phNxpEseP61_DisablePwrCntrl: not supported", __FUNCTION__);
status = ESESTATUS_FAILED;
}
return status;
}
/******************************************************************************
* Function phNxpEse_getOsVersion
*
* Description This function returns OS version from config file &
* runtime from ATR response
*
* Returns SUCCESS/FAIL.
*
******************************************************************************/
phNxpEse_OsVersion_t phNxpEse_getOsVersion() { return sOsVersion; }
/******************************************************************************
* Function phNxpEse_setOsVersion
*
* Description This function sets chip type based on ATR response
*
* Returns None.
*
******************************************************************************/
void phNxpEse_setOsVersion(phNxpEse_OsVersion_t chipType) {
sOsVersion = chipType;
}
/******************************************************************************
* Function phNxpEse_checkFWDwnldStatus
*
* Description This function is used to check whether FW download
* is completed or not.
*
* Returns returns ESESTATUS_SUCCESS or ESESTATUS_BUSY
*
******************************************************************************/
static ESESTATUS phNxpEse_checkFWDwnldStatus(void) {
ALOGD_IF(ese_debug_enabled, "phNxpEse_checkFWDwnldStatus Enter");
ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
spm_state_t current_spm_state = SPM_STATE_INVALID;
uint8_t ese_dwnld_retry = 0x00;
ESESTATUS status = ESESTATUS_FAILED;
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus == ESESTATUS_SUCCESS) {
/* Check current_spm_state and update config/Spm status*/
while (ese_dwnld_retry < ESE_FW_DWNLD_RETRY_CNT) {
ALOGD_IF(ese_debug_enabled, "ESE_FW_DWNLD_RETRY_CNT retry count");
wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
if (wSpmStatus == ESESTATUS_SUCCESS) {
if ((current_spm_state & SPM_STATE_DWNLD)) {
status = ESESTATUS_FAILED;
} else {
ALOGE("Exit polling no FW Download ..");
status = ESESTATUS_SUCCESS;
break;
}
} else {
status = ESESTATUS_FAILED;
break;
}
phNxpEse_Sleep(500000); /*sleep for 500 ms checking for fw dwnld status*/
ese_dwnld_retry++;
}
}
ALOGD_IF(ese_debug_enabled, "phNxpEse_checkFWDwnldStatus status %x", status);
return status;
}
/******************************************************************************
* Function phNxpEse_GetEseStatus(unsigned char *timer_buffer)
*
* Description This function returns the all three timer
* Timeout buffer length should be minimum 18 bytes. Response will be in below
format:
* <0xF1><Len><Timer Value><0xF2><Len><Timer Value><0xF3><Len><Timer Value>
*
* Returns SUCCESS/FAIL.
* ESESTATUS_SUCCESS if 0xF1 or 0xF2 tag timeout >= 0 & 0xF3 == 0
* ESESTATUS_BUSY if 0xF3 tag timeout > 0
* ESESTATUS_FAILED if any other error
******************************************************************************/
ESESTATUS phNxpEse_GetEseStatus(phNxpEse_data* timer_buffer) {
ESESTATUS status = ESESTATUS_FAILED;
phNxpEse_SecureTimer_t secureTimerParams;
uint8_t* temp_timer_buffer = NULL;
ALOGD_IF(ese_debug_enabled, "%s Enter", __FUNCTION__);
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
ALOGE("%s function not supported", __FUNCTION__);
return status;
}
if (timer_buffer != NULL) {
timer_buffer->len =
(sizeof(secureTimerParams.secureTimer1) +
sizeof(secureTimerParams.secureTimer2) +
sizeof(secureTimerParams.secureTimer3)) +
PH_PROPTO_7816_FRAME_LENGTH_OFFSET * PH_PROPTO_7816_FRAME_LENGTH_OFFSET;
temp_timer_buffer = (uint8_t*)phNxpEse_memalloc(timer_buffer->len);
timer_buffer->p_data = temp_timer_buffer;
phNxpEse_memcpy(&secureTimerParams, &nxpese_ctxt.secureTimerParams,
sizeof(phNxpEse_SecureTimer_t));
ALOGD_IF(
ese_debug_enabled,
"%s secureTimer1 0x%x secureTimer2 0x%x secureTimer3 0x%x len = %d",
__FUNCTION__, secureTimerParams.secureTimer1,
secureTimerParams.secureTimer2, secureTimerParams.secureTimer3,
timer_buffer->len);
*temp_timer_buffer++ = PH_PROPTO_7816_SFRAME_TIMER1;
*temp_timer_buffer++ = sizeof(secureTimerParams.secureTimer1);
temp_timer_buffer = phNxpEse_GgetTimerTlvBuffer(
temp_timer_buffer, secureTimerParams.secureTimer1);
if (temp_timer_buffer != NULL) {
*temp_timer_buffer++ = PH_PROPTO_7816_SFRAME_TIMER2;
*temp_timer_buffer++ = sizeof(secureTimerParams.secureTimer2);
temp_timer_buffer = phNxpEse_GgetTimerTlvBuffer(
temp_timer_buffer, secureTimerParams.secureTimer2);
if (temp_timer_buffer != NULL) {
*temp_timer_buffer++ = PH_PROPTO_7816_SFRAME_TIMER3;
*temp_timer_buffer++ = sizeof(secureTimerParams.secureTimer3);
temp_timer_buffer = phNxpEse_GgetTimerTlvBuffer(
temp_timer_buffer, secureTimerParams.secureTimer3);
if (temp_timer_buffer != NULL) {
if (secureTimerParams.secureTimer3 > 0) {
status = ESESTATUS_BUSY;
} else {
status = ESESTATUS_SUCCESS;
}
}
}
}
} else {
ALOGE("%s Invalid timer buffer ", __FUNCTION__);
}
ALOGD_IF(ese_debug_enabled, "%s Exit status = 0x%x", __FUNCTION__, status);
return status;
}
static unsigned char* phNxpEse_GgetTimerTlvBuffer(uint8_t* timer_buffer,
unsigned int value) {
short int count = 0, shift = 3;
unsigned int mask = 0x000000FF;
if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
ALOGE("%s function not supported", __FUNCTION__);
} else {
ALOGD_IF(ese_debug_enabled, "value = %x \n", value);
for (count = 0; count < 4; count++) {
if (timer_buffer != NULL) {
*timer_buffer = (value >> (shift * 8) & mask);
ALOGD_IF(ese_debug_enabled, "*timer_buffer=0x%x shift=0x%x",
*timer_buffer, shift);
timer_buffer++;
shift--;
} else {
break;
}
}
}
return timer_buffer;
}
/******************************************************************************
* Function phNxpEse_NotifySEWtxRequest
*
* Description This function notifies SE hal service if it registers
* about WTX ongoing & end status
*
* Returns None
*
******************************************************************************/
void phNxpEse_NotifySEWtxRequest(phNxpEse_wtxState state) {
if (nxpese_ctxt.fPtr_WtxNtf) {
(nxpese_ctxt.fPtr_WtxNtf)(state);
} else {
ALOGE("%s function not supported", __FUNCTION__);
}
}
/******************************************************************************
* Function phNxpEse_setWtxCountLimit
*
* Description This function sets the counter limit for wtx
*
* Returns None
*
******************************************************************************/
void phNxpEse_setWtxCountLimit(unsigned long int wtxCount) {
app_wtx_cnt = wtxCount;
}