| /****************************************************************************** |
| * |
| * Copyright 2018-2019 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 *************************************/ |
| |
| 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; |
| if (GET_CHIP_OS_VERSION() > OS_VERSION_4_0) { |
| /*None of the IOCTLs valid except SPM_RECOVERY_RESET*/ |
| if (arg != SPM_RECOVERY_RESET) { |
| return ESESTATUS_SUCCESS; |
| } |
| } |
| 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; |
| } else { |
| if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) { |
| ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__); |
| } |
| } |
| } 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__); |
| if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) { |
| ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__); |
| } |
| return wSpmStatus; |
| } else { |
| if (current_spm_state & SPM_STATE_DWNLD) { |
| wSpmStatus = ESESTATUS_DWNLD_BUSY; |
| } else { |
| wSpmStatus = ESESTATUS_BUSY; |
| } |
| } |
| } else { |
| wSpmStatus = ESESTATUS_FAILED; |
| } |
| if (wSpmStatus != ESESTATUS_SUCCESS) { |
| if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) { |
| ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__); |
| } |
| } |
| } |
| } 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; |
| case SPM_RECOVERY_RESET: { |
| } 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 = SPM_STATE_INVALID; |
| |
| 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; |
| } |
| |
| /****************************************************************************** |
| * 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; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEse_SPM_SetEseClientUpdateState |
| * |
| * Description This function is used to set the ese Update state |
| * |
| * Returns On Success ESESTATUS_SUCCESS else proper error code |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEse_SPM_SetEseClientUpdateState(long arg) { |
| int ret = -1; |
| ESESTATUS status = ESESTATUS_SUCCESS; |
| |
| ALOGD_IF(ese_debug_enabled, |
| "%s :phNxpEse_SPM_SetEseClientUpdateState = 0x%ld", __FUNCTION__, |
| arg); |
| ret = phPalEse_ioctl(phPalEse_e_SetClientUpdateState, pEseDeviceHandle, arg); |
| if (ret < 0) { |
| ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); |
| status = ESESTATUS_FAILED; |
| } |
| |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEse_SPM_ResetPwr |
| * |
| * Description This function request to the nfc i2c driver |
| * to reset ese. |
| * |
| * Returns On Success ESESTATUS_SUCCESS else proper error code |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEse_SPM_ResetPwr(void) { |
| int32_t ret = -1; |
| ESESTATUS wSpmStatus = ESESTATUS_SUCCESS; |
| spm_state_t current_spm_state = SPM_STATE_INVALID; |
| |
| /* reset the ese */ |
| ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 2); |
| if (ret < 0) { |
| ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno); |
| if (errno == -EBUSY || 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 phTmlEse_get_ese_access |
| ** |
| ** Description |
| ** |
| ** Parameters timeout - timeout to wait for ese access |
| ** |
| ** Returns success or failure |
| ** |
| *******************************************************************************/ |
| ESESTATUS phNxpEse_SPM_GetAccess(long timeout) { |
| ESESTATUS status = ESESTATUS_SUCCESS; |
| ALOGD_IF(ese_debug_enabled, "phTmlEse_get_ese_access(), timeout %ld", |
| timeout); |
| #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2)) |
| int ret = -1; |
| |
| ret = phPalEse_ioctl(phPalEse_e_GetEseAccess, pEseDeviceHandle, timeout); |
| if (ret < 0) { |
| if (ret == -EBUSY) |
| status = ESESTATUS_BUSY; |
| else |
| status = ESESTATUS_FAILED; |
| } |
| ALOGD_IF(ese_debug_enabled, "phTmlEse_get_ese_access(), exit %d", status); |
| #endif |
| return status; |
| } |
| /******************************************************************************* |
| ** |
| ** Function phNxpEse_SPM_RelAccess |
| ** |
| ** Description |
| ** |
| ** Parameters timeout - Releases the ese access |
| ** |
| ** Returns success or failure |
| ** |
| *******************************************************************************/ |
| ESESTATUS phNxpEse_SPM_RelAccess(void) { |
| ESESTATUS status = ESESTATUS_SUCCESS; |
| #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2)) |
| int ret = -1; |
| ALOGD_IF(ese_debug_enabled, "phNxpEse_SPM_RelAccess(): enter"); |
| |
| ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 5); |
| if (ret < 0) { |
| status = ESESTATUS_FAILED; |
| } |
| ALOGD_IF(ese_debug_enabled, "phNxpEse_SPM_RelAccess(): exit %d", status); |
| #endif |
| return status; |
| } |
| /** @} */ |