/****************************************************************************** * * 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. * ******************************************************************************/ #define LOG_TAG "NxpEseHal" #include <log/log.h> #include <errno.h> #include <fcntl.h> #include <phNxpEsePal.h> #include <phNxpEse_Internal.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "phNxpEseFeatures.h" #include "phNxpEse_Spm.h" /*********************** Global Variables *************************************/ extern bool ese_debug_enabled; static void* pEseDeviceHandle = NULL; #define MAX_ESE_ACCESS_TIME_OUT_MS 2000 /*2 seconds*/ /** * \addtogroup SPI_Power_Management * * @{ */ /****************************************************************************** \section Introduction Introduction * This module provide power request to Pn54x nfc-i2c driver, it cheks if * wired access is already granted. It should have access to pn54x drive. * Below are the apis provided by the SPM module. ******************************************************************************/ /****************************************************************************** * Function phNxpEse_SPM_Init * * Description This function opens the nfc i2c driver to manage power * and synchronization for ese secure element. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_Init(void* pDevHandle) { ESESTATUS status = ESESTATUS_SUCCESS; pEseDeviceHandle = pDevHandle; if (NULL == pEseDeviceHandle) { ALOGE("%s : failed, device handle is null", __FUNCTION__); status = ESESTATUS_FAILED; } ALOGD_IF(ese_debug_enabled, "%s : exit status = %d", __FUNCTION__, status); return status; } /****************************************************************************** * Function phNxpEse_SPM_DeInit * * Description This function closes the nfc i2c driver node. * * Returns Always returns ESESTATUS_SUCCESS * ******************************************************************************/ ESESTATUS phNxpEse_SPM_DeInit(void) { pEseDeviceHandle = NULL; return ESESTATUS_SUCCESS; } /****************************************************************************** * Function phNxpEse_SPM_ConfigPwr * * Description This function request to the nfc i2c driver * to enable/disable power to ese. This api should be called *before * sending any apdu to ese/once apdu exchange is done. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_ConfigPwr(spm_power_t arg) { int32_t ret = -1; ESESTATUS wSpmStatus = ESESTATUS_SUCCESS; spm_state_t current_spm_state = SPM_STATE_INVALID; ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, arg); switch (arg) { case SPM_POWER_DISABLE: { if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); wSpmStatus = ESESTATUS_FAILED; } } break; case SPM_POWER_ENABLE: { if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); if (errno == -EBUSY) { wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state); if (wSpmStatus != ESESTATUS_SUCCESS) { ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__); return wSpmStatus; } else { if (current_spm_state & SPM_STATE_DWNLD) { wSpmStatus = ESESTATUS_DWNLD_BUSY; } else { wSpmStatus = ESESTATUS_BUSY; } } } else { wSpmStatus = ESESTATUS_FAILED; } } } break; case SPM_POWER_RESET: { if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); if (errno == -EBUSY) { wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state); if (wSpmStatus != ESESTATUS_SUCCESS) { ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__); return wSpmStatus; } else { if (current_spm_state & SPM_STATE_DWNLD) { wSpmStatus = ESESTATUS_DWNLD_BUSY; } else { wSpmStatus = ESESTATUS_BUSY; } } } else { wSpmStatus = ESESTATUS_FAILED; } } } break; case SPM_POWER_PRIO_ENABLE: { if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); if (errno == -EBUSY) { wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state); if (wSpmStatus != ESESTATUS_SUCCESS) { ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__); return wSpmStatus; } else { if (current_spm_state & SPM_STATE_DWNLD) { wSpmStatus = ESESTATUS_DWNLD_BUSY; } else { wSpmStatus = ESESTATUS_BUSY; } } } else { wSpmStatus = ESESTATUS_FAILED; } } } break; case SPM_POWER_PRIO_DISABLE: { if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); wSpmStatus = ESESTATUS_FAILED; } } break; } return wSpmStatus; } /****************************************************************************** * Function phNxpEse_SPM_EnablePwr * * Description This function request to the nfc i2c driver * to enable power to ese. This api should be called before * sending any apdu to ese. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_EnablePwr(void) { int32_t ret = -1; ESESTATUS wSpmStatus = ESESTATUS_SUCCESS; spm_state_t current_spm_state = SPM_STATE_INVALID; ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_EnablePwr is set to = 0x%d", __FUNCTION__, 0); ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 0); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); if (errno == -EBUSY) { wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state); if (wSpmStatus != ESESTATUS_SUCCESS) { ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__); return wSpmStatus; } else { if (current_spm_state == SPM_STATE_DWNLD) { wSpmStatus = ESESTATUS_DWNLD_BUSY; } else { wSpmStatus = ESESTATUS_BUSY; } } } else { wSpmStatus = ESESTATUS_FAILED; } } return wSpmStatus; } /****************************************************************************** * Function phNxpEse_SPM_DisablePwr * * Description This function request to the nfc i2c driver * to disable power to ese. This api should be called * once apdu exchange is done. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_DisablePwr(void) { int32_t ret = -1; ESESTATUS status = ESESTATUS_SUCCESS; ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_DisablePwr is set to = 0x%d", __FUNCTION__, 1); ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 1); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); status = ESESTATUS_FAILED; } return status; } /****************************************************************************** * Function phNxpEse_SPM_SetPwrScheme * * Description This function request to the nfc i2c driver * to set the chip type and power scheme. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_SetPwrScheme(long arg) { int32_t ret = -1; ESESTATUS status = ESESTATUS_SUCCESS; ALOGD_IF(ese_debug_enabled, "%s : Power scheme is set to = 0x%ld", __FUNCTION__, arg); ret = phPalEse_ioctl(phPalEse_e_SetPowerScheme, pEseDeviceHandle, arg); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); status = ESESTATUS_FAILED; } return status; } /****************************************************************************** * Function phNxpEseP61_SPM_EnableDisablePwrCntrl * * Description This function request to the nfc i2c driver * to set the chip type and power scheme. * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_DisablePwrControl(unsigned long arg) { int32_t ret = -1; ESESTATUS status = ESESTATUS_SUCCESS; ALOGD_IF(ese_debug_enabled, "%s : Inhibit power control is set to = 0x%ld", __FUNCTION__, arg); ret = phPalEse_ioctl(phPalEse_e_DisablePwrCntrl, pEseDeviceHandle, arg); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); status = ESESTATUS_FAILED; } return status; } /****************************************************************************** * Function phNxpEse_SPM_GetState * * Description This function gets the current power state of ESE * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_GetState(spm_state_t* current_state) { int32_t ret = -1; ESESTATUS status = ESESTATUS_SUCCESS; spm_state_t ese_current_state; if (current_state == NULL) { ALOGE("%s : failed Invalid argument", __FUNCTION__); return ESESTATUS_FAILED; } ret = phPalEse_ioctl(phPalEse_e_GetSPMStatus, pEseDeviceHandle, (unsigned long)&ese_current_state); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); status = ESESTATUS_FAILED; } else { *current_state = ese_current_state; /* Current ESE state */ } return status; } #ifdef NXP_ESE_JCOP_DWNLD_PROTECTION /****************************************************************************** * Function phNxpEse_SPM_SetJcopDwnldState * * Description This function is used to set the JCOP OS download state * * Returns On Success ESESTATUS_SUCCESS else proper error code * ******************************************************************************/ ESESTATUS phNxpEse_SPM_SetJcopDwnldState(long arg) { int ret = -1; ESESTATUS status = ESESTATUS_SUCCESS; ALOGD_IF(ese_debug_enabled, "%s :phNxpEse_SPM_SetJcopDwnldState = 0x%ld", __FUNCTION__, arg); ret = phPalEse_ioctl(phPalEse_e_SetJcopDwnldState, pEseDeviceHandle, arg); if (ret < 0) { ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); status = ESESTATUS_FAILED; } return status; } #endif