/******************************************************************************
*
* Copyright 2018 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.
*
******************************************************************************/
/*
* DAL spi port implementation for linux
*
* Project: Trusted ESE Linux
*
*/
#define LOG_TAG "NxpEseHal"
#include <log/log.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <ese_config.h>
#include <hardware/nfc.h>
#include <phEseStatus.h>
#include <phNxpEsePal.h>
#include <phNxpEsePal_spi.h>
#include <string.h>
#include "NfcAdaptation.h"
#include "hal_nxpese.h"
#include "phNxpEse_Api.h"
#define MAX_RETRY_CNT 10
#define HAL_NFC_SPI_DWP_SYNC 21
#define RF_ON 1
extern int omapi_status;
extern bool ese_debug_enabled;
static int rf_status;
unsigned long int configNum1, configNum2;
// Default max retry count for SPI CLT write blocked in secs
static const uint8_t DEFAULT_MAX_SPI_WRITE_RETRY_COUNT_RF_ON = 10;
static const uint8_t MAX_SPI_WRITE_RETRY_COUNT_HW_ERR = 3;
/*******************************************************************************
**
** Function phPalEse_spi_close
**
** Description Closes PN547 device
**
** Parameters pDevHandle - device handle
**
** Returns None
**
*******************************************************************************/
void phPalEse_spi_close(void* pDevHandle) {
ese_nxp_IoctlInOutData_t inpOutData;
static uint8_t cmd_omapi_concurrent[] = {0x2F, 0x01, 0x01, 0x00};
int retval;
ALOGD_IF(ese_debug_enabled, "halimpl close enter.");
NfcAdaptation& pNfcAdapt = NfcAdaptation::GetInstance();
pNfcAdapt.Initialize();
// nxpesehal_ctrl.p_ese_stack_cback = p_cback;
// nxpesehal_ctrl.p_ese_stack_data_cback = p_data_cback;
memset(&inpOutData, 0x00, sizeof(ese_nxp_IoctlInOutData_t));
inpOutData.inp.data.nxpCmd.cmd_len = sizeof(cmd_omapi_concurrent);
inpOutData.inp.data_source = 1;
memcpy(inpOutData.inp.data.nxpCmd.p_cmd, cmd_omapi_concurrent,
sizeof(cmd_omapi_concurrent));
retval = pNfcAdapt.HalIoctl(HAL_NFC_SPI_DWP_SYNC, &inpOutData);
ALOGD_IF(ese_debug_enabled, "_spi_close() status %x", retval);
if (NULL != pDevHandle) {
close((intptr_t)pDevHandle);
}
ALOGD_IF(ese_debug_enabled, "halimpl close exit.");
return;
}
ESESTATUS phNxpEse_spiIoctl(uint64_t ioctlType, void* p_data) {
ese_nxp_IoctlInOutData_t* inpOutData = (ese_nxp_IoctlInOutData_t*)p_data;
rf_status = inpOutData->inp.data.nxpCmd.p_cmd[0];
if (rf_status == 1) {
ALOGD_IF(ese_debug_enabled,
"******************RF IS ON*************************************");
} else {
ALOGD_IF(
ese_debug_enabled,
"******************RF IS OFF*************************************");
}
if (p_data != NULL) {
ALOGD_IF(ese_debug_enabled,
"halimpl phNxpEse_spiIoctl p_data is not null ioctltyp: %ld",
(long)ioctlType);
}
return ESESTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function phPalEse_spi_open_and_configure
**
** Description Open and configure pn547 device
**
** Parameters pConfig - hardware information
** pLinkHandle - device handle
**
** Returns ESE status:
** ESESTATUS_SUCCESS - open_and_configure operation
*success
** ESESTATUS_INVALID_DEVICE - device open operation failure
**
*******************************************************************************/
ESESTATUS phPalEse_spi_open_and_configure(pphPalEse_Config_t pConfig) {
int nHandle;
int retryCnt = 0, nfc_access_retryCnt = 0;
int retval;
ese_nxp_IoctlInOutData_t inpOutData;
NfcAdaptation& pNfcAdapt = NfcAdaptation::GetInstance();
pNfcAdapt.Initialize();
static uint8_t cmd_omapi_concurrent[] = {0x2F, 0x01, 0x01, 0x01};
if (EseConfig::hasKey(NAME_NXP_SOF_WRITE)) {
configNum1 = EseConfig::getUnsigned(NAME_NXP_SOF_WRITE);
ALOGD_IF(ese_debug_enabled, "NXP_SOF_WRITE value from config file = %ld",
configNum1);
}
if (EseConfig::hasKey(NAME_NXP_SPI_WRITE_TIMEOUT)) {
configNum2 = EseConfig::getUnsigned(NAME_NXP_SPI_WRITE_TIMEOUT);
ALOGD_IF(ese_debug_enabled,
"NXP_SPI_WRITE_TIMEOUT value from config file = %ld", configNum2);
}
ALOGD_IF(ese_debug_enabled, "halimpl open enter.");
memset(&inpOutData, 0x00, sizeof(ese_nxp_IoctlInOutData_t));
inpOutData.inp.data.nxpCmd.cmd_len = sizeof(cmd_omapi_concurrent);
inpOutData.inp.data_source = 1;
memcpy(inpOutData.inp.data.nxpCmd.p_cmd, cmd_omapi_concurrent,
sizeof(cmd_omapi_concurrent));
retry_nfc_access:
omapi_status = ESESTATUS_FAILED;
retval = pNfcAdapt.HalIoctl(HAL_NFC_SPI_DWP_SYNC, &inpOutData);
if (omapi_status != 0) {
ALOGD_IF(ese_debug_enabled, "omapi_status return failed.");
nfc_access_retryCnt++;
phPalEse_sleep(2000000);
if (nfc_access_retryCnt < 5) goto retry_nfc_access;
return ESESTATUS_FAILED;
}
ALOGD_IF(ese_debug_enabled, "Opening port=%s\n", pConfig->pDevName);
/* open port */
retry:
nHandle = open((char const*)pConfig->pDevName, O_RDWR);
if (nHandle < 0) {
ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
if (errno == -EBUSY || errno == EBUSY) {
retryCnt++;
ALOGE("Retry open eSE driver, retry cnt : %d", retryCnt);
if (retryCnt < MAX_RETRY_CNT) {
phPalEse_sleep(1000000);
goto retry;
}
}
ALOGE("_spi_open() Failed: retval %x", nHandle);
pConfig->pDevHandle = NULL;
return ESESTATUS_INVALID_DEVICE;
}
ALOGD_IF(ese_debug_enabled, "eSE driver opened :: fd = [%d]", nHandle);
pConfig->pDevHandle = (void*)((intptr_t)nHandle);
return ESESTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function phPalEse_spi_read
**
** Description Reads requested number of bytes from pn547 device into given
*buffer
**
** Parameters pDevHandle - valid device handle
** pBuffer - buffer for read data
** nNbBytesToRead - number of bytes requested to be read
**
** Returns numRead - number of successfully read bytes
** -1 - read operation failure
**
*******************************************************************************/
int phPalEse_spi_read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead) {
int ret = -1;
ALOGD_IF(ese_debug_enabled, "%s Read Requested %d bytes", __FUNCTION__,
nNbBytesToRead);
ret = read((intptr_t)pDevHandle, (void*)pBuffer, (nNbBytesToRead));
ALOGD_IF(ese_debug_enabled, "Read Returned = %d", ret);
return ret;
}
/*******************************************************************************
**
** Function phPalEse_spi_write
**
** Description Writes requested number of bytes from given buffer into
*pn547 device
**
** Parameters pDevHandle - valid device handle
** pBuffer - buffer for read data
** nNbBytesToWrite - number of bytes requested to be written
**
** Returns numWrote - number of successfully written bytes
** -1 - write operation failure
**
*******************************************************************************/
int phPalEse_spi_write(void* pDevHandle, uint8_t* pBuffer,
int nNbBytesToWrite) {
int ret = -1;
int numWrote = 0;
unsigned long int retryCount = 0;
if (NULL == pDevHandle) {
return -1;
}
if (configNum1 == 1) {
/* Appending SOF for SPI write */
pBuffer[0] = SEND_PACKET_SOF;
} else {
/* Do Nothing */
}
unsigned int maxRetryCount = 0, retryDelay = 0;
while (numWrote < nNbBytesToWrite) {
// usleep(5000);
if (rf_status != RF_ON) {
ret = write((intptr_t)pDevHandle, pBuffer + numWrote,
nNbBytesToWrite - numWrote);
} else {
ret = -1;
}
if (ret > 0) {
numWrote += ret;
} else if (ret == 0) {
ALOGE("_spi_write() EOF");
return -1;
} else {
ALOGE("_spi_write() errno : %x", errno);
if (rf_status == RF_ON) {
maxRetryCount = (configNum2 > 0)
? configNum2
: DEFAULT_MAX_SPI_WRITE_RETRY_COUNT_RF_ON;
retryDelay = 1000 * WRITE_WAKE_UP_DELAY;
ALOGD_IF(ese_debug_enabled, "spi_Write failed as RF is ON.");
} else {
maxRetryCount = MAX_SPI_WRITE_RETRY_COUNT_HW_ERR;
retryDelay = WRITE_WAKE_UP_DELAY;
ALOGD_IF(ese_debug_enabled, "spi_write failed");
}
if (retryCount < maxRetryCount) {
retryCount++;
/*wait for eSE wake up*/
phPalEse_sleep(retryDelay);
ALOGE("_spi_write() failed. Going to retry, counter:%ld !", retryCount);
continue;
}
return -1;
}
}
return numWrote;
}
/*******************************************************************************
**
** Function phPalEse_spi_ioctl
**
** Description Exposed ioctl by p61 spi driver
**
** Parameters pDevHandle - valid device handle
** level - reset level
**
** Returns 0 - ioctl operation success
** -1 - ioctl operation failure
**
*******************************************************************************/
ESESTATUS phPalEse_spi_ioctl(phPalEse_ControlCode_t eControlCode,
void* pDevHandle, long level) {
ESESTATUS ret = ESESTATUS_IOCTL_FAILED;
ALOGD_IF(ese_debug_enabled, "phPalEse_spi_ioctl(), ioctl %x , level %lx",
eControlCode, level);
ese_nxp_IoctlInOutData_t inpOutData;
inpOutData.inp.level = level;
NfcAdaptation& pNfcAdapt = NfcAdaptation::GetInstance();
if (NULL == pDevHandle) {
return ESESTATUS_IOCTL_FAILED;
}
switch (eControlCode) {
// Nfc Driver communication part
case phPalEse_e_ChipRst:
ret = pNfcAdapt.HalIoctl(HAL_NFC_SET_SPM_PWR, &inpOutData);
break;
case phPalEse_e_SetPowerScheme:
// ret = sendIoctlData(p, HAL_NFC_SET_POWER_SCHEME, &inpOutData);
ret = ESESTATUS_SUCCESS;
break;
case phPalEse_e_GetSPMStatus:
// ret = sendIoctlData(p, HAL_NFC_GET_SPM_STATUS, &inpOutData);
ret = ESESTATUS_SUCCESS;
break;
case phPalEse_e_GetEseAccess:
// ret = sendIoctlData(p, HAL_NFC_GET_ESE_ACCESS, &inpOutData);
ret = ESESTATUS_SUCCESS;
break;
#ifdef NXP_ESE_JCOP_DWNLD_PROTECTION
case phPalEse_e_SetJcopDwnldState:
// ret = sendIoctlData(p, HAL_NFC_SET_DWNLD_STATUS, &inpOutData);
ret = ESESTATUS_SUCCESS;
break;
#endif
case phPalEse_e_DisablePwrCntrl:
ret = pNfcAdapt.HalIoctl(HAL_NFC_INHIBIT_PWR_CNTRL, &inpOutData);
break;
default:
ret = ESESTATUS_IOCTL_FAILED;
break;
}
return ret;
}