| /* |
| * Copyright 2021-2023 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. |
| */ |
| |
| #if (NXP_NFC_RECOVERY == TRUE) |
| |
| #include "phNxpNciHal_Recovery.h" |
| |
| #include <phDnldNfc.h> |
| #include <phNfcStatus.h> |
| #include <phNfcTypes.h> |
| #include <phNxpLog.h> |
| #include <phNxpNciHal.h> |
| #include <phNxpNciHal_Dnld.h> |
| #include <phNxpNciHal_ext.h> |
| #include <phOsalNfc_Timer.h> |
| #include <phTmlNfc.h> |
| #undef property_set |
| #undef PROPERTY_VALUE_MAX |
| #undef property_get |
| #include <cutils/properties.h> |
| #define MAX_CORE_RESET 3 |
| |
| extern phNxpNciProfile_Control_t nxpprofile_ctrl; |
| extern phNxpNciHal_Control_t nxpncihal_ctrl; |
| extern phTmlNfc_Context_t* gpphTmlNfc_Context; |
| extern void* phNxpNciHal_client_thread(void* arg); |
| |
| static void phnxpNciHal_partialClose(); |
| static NFCSTATUS phnxpNciHal_partialOpen(); |
| |
| // property name for storing boot time init status |
| const char* halInitProperty = "vendor.nfc.min_firmware"; |
| |
| /****************************************************************************** |
| * Function getHalInitStatus |
| * |
| * Description Get property whether it is boot init/not |
| * |
| * Parameters Parameter to return the hal status is boot init/not. |
| * |
| * Returns None |
| * |
| ******************************************************************************/ |
| static void getHalInitStatus(char* halInitStatus) { |
| NXPLOG_NCIHAL_D("Enter : %s", __func__); |
| if (property_get(halInitProperty, halInitStatus, "Boot-time") != 0) { |
| NXPLOG_NCIHAL_E("Error in property_get : %s", __func__); |
| } |
| } |
| |
| /****************************************************************************** |
| * Function setHalInitStatus |
| * |
| * Description To set property as per input whether it is boot init/not |
| * |
| * Parameters status to be updated in property |
| * |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void setHalInitStatus(const char* status) { |
| NXPLOG_NCIHAL_E("Enter : %s", __func__); |
| if (property_set(halInitProperty, status) != 0) { |
| NXPLOG_NCIHAL_E("Error in property_set : %s", __func__); |
| } |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_read_callback |
| * |
| * Description Callback function for read request to tml reader thread |
| * |
| * Parameters pContext - context value passed while callback register |
| * pInfo - Information which contains status and response |
| * buffers. |
| * |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpNciHal_read_callback(void* pContext, |
| phTmlNfc_TransactInfo_t* pInfo) { |
| UNUSED_PROP(pContext); |
| if (pInfo != NULL) { |
| NXPLOG_NCIHAL_E("%s Status %d", __func__, pInfo->wStatus); |
| if (pInfo->wStatus == NFCSTATUS_SUCCESS) { |
| nxpncihal_ctrl.p_rx_data = pInfo->pBuff; |
| nxpncihal_ctrl.rx_data_len = pInfo->wLength; |
| } |
| nxpncihal_ctrl.ext_cb_data.status = pInfo->wStatus; |
| } else { |
| nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_FAILED; |
| } |
| SEM_POST(&(nxpncihal_ctrl.ext_cb_data)); |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_write_callback |
| * |
| * Description Callback function for write request to tml writer thread |
| * |
| * Parameters pContext - context value passed while callback register |
| * pInfo - Information which contains status and response |
| * buffers. |
| * |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpNciHal_write_callback(void* pContext, |
| phTmlNfc_TransactInfo_t* pInfo) { |
| UNUSED_PROP(pContext); |
| if (pInfo != NULL) { |
| if (pInfo->wStatus != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("write error status = 0x%x", pInfo->wStatus); |
| } |
| nxpncihal_ctrl.ext_cb_data.status = pInfo->wStatus; |
| } else { |
| nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_FAILED; |
| } |
| SEM_POST(&(nxpncihal_ctrl.ext_cb_data)); |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_semWaitTimeout |
| * |
| * Description Helper function for global sem wait with timeout value |
| * |
| * Parameters timeout - wait timeout in nanoseconds |
| * |
| * Returns NFCSTATUS |
| * |
| ******************************************************************************/ |
| static NFCSTATUS phNxpNciHal_semWaitTimeout(long timeout) { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| int retVal = 0; |
| struct timespec ts; |
| clock_gettime(CLOCK_MONOTONIC, &ts); |
| ts.tv_nsec += timeout; |
| ts.tv_sec += ts.tv_nsec / 1000000000; |
| ts.tv_nsec %= 1000000000; |
| while ((retVal = sem_timedwait_monotonic_np(&nxpncihal_ctrl.ext_cb_data.sem, &ts)) == -1 && |
| errno == EINTR) { |
| continue; /* Restart if interrupted by handler */ |
| } |
| if (retVal == -1 && errno != ETIMEDOUT) { |
| NXPLOG_NCIHAL_E("%s : sem_timedwait failed : errno = 0x%x", __func__, |
| errno); |
| } |
| if (retVal != -1) { |
| status = nxpncihal_ctrl.ext_cb_data.status; |
| } else if (errno == ETIMEDOUT && retVal == -1) { |
| NXPLOG_NCIHAL_E("%s :timed out errno = 0x%x", __func__, errno); |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_writeCmd |
| * |
| * Description Helper function to write command to NFCC |
| * |
| * Parameters timeout - wait timeout in nanoseconds |
| * |
| * Returns NFCSTATUS |
| * |
| ******************************************************************************/ |
| static NFCSTATUS phNxpNciHal_writeCmd(uint16_t data_len, const uint8_t* p_data, |
| long timeout) { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| const char context[] = "RecoveryWrite"; |
| |
| if (p_data == NULL) { |
| NXPLOG_NCIHAL_E("Invalid Command Buffer"); |
| return NFCSTATUS_INVALID_PARAMETER; |
| } |
| /* Create local copy of cmd_data */ |
| memcpy(nxpncihal_ctrl.p_cmd_data, p_data, data_len); |
| nxpncihal_ctrl.cmd_len = data_len; |
| status = phTmlNfc_Write( |
| (uint8_t*)nxpncihal_ctrl.p_cmd_data, (uint16_t)nxpncihal_ctrl.cmd_len, |
| (pphTmlNfc_TransactCompletionCb_t)&phNxpNciHal_write_callback, |
| (void*)context); |
| if (status == NFCSTATUS_PENDING) { |
| return phNxpNciHal_semWaitTimeout(timeout); |
| } |
| NXPLOG_NCIHAL_E("tml write request failed"); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_ReadResponse |
| * |
| * Description Helper function to read response from NFCC |
| * |
| * Parameters len - response buffer len |
| * rsp_buffer - Ptr to the response buffer |
| * timeout - wait timeout in nanoseconds |
| * |
| * Returns NFCSTATUS |
| * |
| ******************************************************************************/ |
| static NFCSTATUS phNxpNciHal_ReadResponse(uint16_t* len, uint8_t** rsp_buffer, |
| long timeout) { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| const char context[] = "RecoveryRead"; |
| |
| if (len == NULL) { |
| NXPLOG_NCIHAL_E("%s Invalid Parameters", __func__); |
| return NFCSTATUS_INVALID_PARAMETER; |
| } |
| status = phTmlNfc_Read( |
| nxpncihal_ctrl.p_rsp_data, NCI_MAX_DATA_LEN, |
| (pphTmlNfc_TransactCompletionCb_t)&phNxpNciHal_read_callback, |
| (void*)context); |
| if (phNxpNciHal_semWaitTimeout(timeout) == NFCSTATUS_SUCCESS) { |
| if (nxpncihal_ctrl.p_rx_data != NULL && nxpncihal_ctrl.rx_data_len > 0) { |
| *rsp_buffer = nxpncihal_ctrl.p_rx_data; |
| *len = nxpncihal_ctrl.rx_data_len; |
| status = NFCSTATUS_SUCCESS; |
| } else |
| status = NFCSTATUS_FAILED; |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_readNFCCClockCfgValues |
| * |
| * Description Helper function to read clock configuration from |
| * nfcc configuration file and stores value in global strcture |
| * |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpNciHal_readNFCCClockCfgValues(void) { |
| unsigned long num = 0; |
| int isfound = 0; |
| |
| isfound = GetNxpNumValue(NAME_NXP_SYS_CLK_SRC_SEL, &num, sizeof(num)); |
| if (isfound > 0) nxpprofile_ctrl.bClkSrcVal = num; |
| num = 0; |
| isfound = 0; |
| isfound = GetNxpNumValue(NAME_NXP_SYS_CLK_FREQ_SEL, &num, sizeof(num)); |
| if (isfound > 0) nxpprofile_ctrl.bClkFreqVal = num; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_determineChipType |
| * |
| * Description Helper function to determine the chip info in nci mode |
| * from NCI command and stores value in global strcture |
| * |
| * Returns bool |
| * |
| ******************************************************************************/ |
| static bool phNxpNciHal_determineChipType(void) { |
| const uint8_t cmd_reset_nci[] = {0x20, 0x00, 0x01, 0x00}; |
| uint8_t* rsp_buffer = NULL; |
| uint16_t rsp_len = 0; |
| uint8_t retry = 0; |
| bool status = false; |
| |
| do { |
| if ((phNxpNciHal_writeCmd(sizeof(cmd_reset_nci), cmd_reset_nci, |
| WRITE_TIMEOUT_NS) != NFCSTATUS_SUCCESS)) { |
| NXPLOG_NCIHAL_E("NCI_CORE_RESET Write Failure "); |
| break; |
| } |
| // 10ms delay for first core reset response to avoid nfcc standby |
| usleep(NCI_RESET_RESP_READ_DELAY_US); |
| if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer, |
| RESPONSE_READ_TIMEOUT_NS) != |
| NFCSTATUS_SUCCESS) || |
| (rsp_buffer == NULL)) { |
| NXPLOG_NCIHAL_E("NCI_CORE_RESET read response failed"); |
| break; |
| } |
| if (rsp_buffer[NCI_RSP_IDX] == NCI_MSG_RSP) { |
| if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer, |
| RESPONSE_READ_TIMEOUT_NS) != |
| NFCSTATUS_SUCCESS) || |
| (rsp_buffer == NULL)) { |
| NXPLOG_NCIHAL_E("NCI_CORE_RESET NTF read failed"); |
| break; |
| } |
| if (rsp_buffer[NCI_RSP_IDX] == NCI_MSG_NTF) { |
| phNxpNciHal_configFeatureList(rsp_buffer, rsp_len); |
| status = true; |
| break; |
| } |
| } else { |
| NXPLOG_NCIHAL_E("NCI_CORE_RESPONSE Wrong Status"); |
| } |
| } while (retry++ < MAX_CORE_RESET); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_isSessionClosed |
| * |
| * Description Helper function to determine download session state |
| * |
| * Returns true means session closed |
| * |
| ******************************************************************************/ |
| bool phNxpNciHal_isSessionClosed(void) { |
| const uint8_t get_session_cmd[] = {0x00, 0x04, 0xF2, 0x00, |
| 0x00, 0x00, 0xF5, 0x33}; |
| uint8_t* rsp_buffer = NULL; |
| uint16_t rsp_len = 0; |
| |
| if ((phNxpNciHal_writeCmd(sizeof(get_session_cmd), get_session_cmd, |
| WRITE_TIMEOUT_NS) == NFCSTATUS_SUCCESS)) { |
| if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer, |
| RESPONSE_READ_TIMEOUT_NS) != |
| NFCSTATUS_SUCCESS) || |
| (rsp_buffer == NULL)) { |
| NXPLOG_NCIHAL_E("Get Session read response failed"); |
| } else if (rsp_buffer[DL_RSP_STAT_IDX] == DL_MSG_STAT_RSP && |
| rsp_buffer[DL_RSP_IDX] == DL_MSG_RSP) { |
| if (rsp_buffer[DL_RSP_SESS_IDX] == DL_SESSION_CLOSE_TAG) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_determineChipTypeDlMode |
| * |
| * Description Helper function to determine the chip info in download mode |
| * from get version command and stores value in global strcture |
| * |
| * Returns bool |
| * |
| ******************************************************************************/ |
| static bool phNxpNciHal_determineChipTypeDlMode(void) { |
| const uint8_t get_version_cmd[] = {0x00, 0x04, 0xF1, 0x00, |
| 0x00, 0x00, 0x6E, 0xEF}; |
| uint8_t* rsp_buffer = NULL; |
| uint16_t rsp_len = 0; |
| |
| if ((phNxpNciHal_writeCmd(sizeof(get_version_cmd), get_version_cmd, |
| WRITE_TIMEOUT_NS) == NFCSTATUS_SUCCESS)) { |
| if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer, |
| RESPONSE_READ_TIMEOUT_NS) != |
| NFCSTATUS_SUCCESS) || |
| (rsp_buffer == NULL)) { |
| NXPLOG_NCIHAL_E("Get Version read response failed"); |
| } else if (rsp_buffer[DL_RSP_STAT_IDX] == DL_MSG_STAT_RSP && |
| rsp_buffer[DL_RSP_IDX] == DL_MSG_RSP) { |
| phNxpNciHal_configFeatureList(rsp_buffer, rsp_len); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpNciHal_RecoverFWTearDown |
| * |
| * Description Function to determine the NFCC state and recovery using |
| * minimal fw download. |
| * |
| * Parameters None |
| * |
| * Returns SUCCESS if recovery is successful else FAIL. |
| * |
| ******************************************************************************/ |
| void phNxpNciHal_RecoverFWTearDown(void) { |
| uint8_t nfcc_recovery_support = 0x00; |
| // status post boot completed |
| const char* status = "Boot-completed"; |
| char halInitStatus[PROPERTY_VALUE_MAX] = {0}; |
| |
| NXPLOG_NCIHAL_D("phNxpNciHal_RecoverFWTearDown(): enter \n"); |
| if (!GetNxpNumValue(NAME_NXP_NFCC_RECOVERY_SUPPORT, &nfcc_recovery_support, |
| sizeof(nfcc_recovery_support))) { |
| NXPLOG_NCIHAL_E("Failed to read NXP_NFC_RECOVERY_SUPPORT config :"); |
| } |
| if (nfcc_recovery_support == 0x00) { |
| NXPLOG_NCIHAL_D("NFCC Recovery not supported"); |
| return; |
| } |
| |
| // If this is not boot time invocation return |
| getHalInitStatus(halInitStatus); |
| if (strncmp(halInitStatus, status, PROPERTY_VALUE_MAX) == 0) { |
| NXPLOG_NCIHAL_D("Not boot time, skip minimal FW download"); |
| return; |
| } else { |
| NXPLOG_NCIHAL_D("boot time, check minimal FW download required"); |
| } |
| |
| if (phnxpNciHal_partialOpen() != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("Failed to Initialize Partial HAL for NFCC recovery \n"); |
| return; |
| } |
| if (phTmlNfc_IoCtl(phTmlNfc_e_PowerReset) != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("Failed to Perform VEN RESET \n"); |
| phnxpNciHal_partialClose(); |
| return; |
| } |
| if (phNxpNciHal_determineChipType()) { |
| NXPLOG_NCIHAL_D("Recovery not required \n"); |
| phnxpNciHal_partialClose(); |
| setHalInitStatus(status); |
| return; |
| } |
| if (phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadModeWithVenRst) != |
| NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("Enable Download mode failed"); |
| phnxpNciHal_partialClose(); |
| setHalInitStatus(status); |
| return; |
| } |
| |
| phTmlNfc_EnableFwDnldMode(true); |
| bool bEnableNormalMode = true; |
| if (!phNxpNciHal_determineChipTypeDlMode()) { |
| NXPLOG_NCIHAL_E("Not able to determine chiptype"); |
| } else if (IS_CHIP_TYPE_NE(sn100u)) { |
| NXPLOG_NCIHAL_E("Recovery not supported for chiptype (%d)", nfcFL.chipType); |
| } else if (phNxpNciHal_isSessionClosed()) { |
| NXPLOG_NCIHAL_D("FW Dnld session is closed"); |
| } else if (phNxpNciHal_fw_download_seq(nxpprofile_ctrl.bClkSrcVal, |
| nxpprofile_ctrl.bClkFreqVal, 0, |
| true) != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("Minimal FW Update failed \n"); |
| } else { |
| /* In the success case, the phNxpNciHal_fw_download_seq() will enable normal |
| * mode */ |
| bEnableNormalMode = false; |
| } |
| if (bEnableNormalMode) { |
| phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode); |
| } |
| phTmlNfc_IoCtl(phTmlNfc_e_PowerReset); |
| phnxpNciHal_partialClose(); |
| // Minimal FW not required in this boot session |
| setHalInitStatus(status); |
| } |
| |
| /******************************************************************************* |
| * |
| * Function phnxpNciHal_partialOpenCleanUp |
| * |
| * Description Helper function to cleanUp the Memory and flags from |
| * phnxpNciHal_partialOpen |
| * |
| * Parameters nfc_dev_node - dev node to be freed |
| * |
| * Returns NFCSTATUS |
| *******************************************************************************/ |
| static int phnxpNciHal_partialOpenCleanUp(char* nfc_dev_node) { |
| if (nfc_dev_node != NULL) { |
| free(nfc_dev_node); |
| nfc_dev_node = NULL; |
| } |
| /* Report error status */ |
| phNxpNciHal_cleanup_monitor(); |
| nxpncihal_ctrl.halStatus = HAL_STATUS_CLOSE; |
| return NFCSTATUS_FAILED; |
| } |
| |
| /******************************************************************************* |
| * |
| * Function phnxpNciHal_partialOpen |
| * |
| * Description Initialize the Minimal HAL |
| * |
| * Parameters none |
| * |
| * Returns NFCSTATUS |
| *******************************************************************************/ |
| static NFCSTATUS phnxpNciHal_partialOpen(void) { |
| phOsalNfc_Config_t tOsalConfig; |
| phTmlNfc_Config_t tTmlConfig; |
| char* nfc_dev_node = NULL; |
| |
| NXPLOG_NCIHAL_D("phnxpNciHal_partialOpen(): enter"); |
| if (nxpncihal_ctrl.halStatus == HAL_STATUS_MIN_OPEN) { |
| NXPLOG_NCIHAL_D("phNxpNciHal: already open"); |
| return NFCSTATUS_SUCCESS; |
| } |
| /* initialize trace level */ |
| phNxpLog_InitializeLogLevel(); |
| if (phNxpNciHal_init_monitor() == NULL) { |
| NXPLOG_NCIHAL_E("Init monitor failed"); |
| return NFCSTATUS_FAILED; |
| } |
| /* Create the local semaphore */ |
| if (phNxpNciHal_init_cb_data(&nxpncihal_ctrl.ext_cb_data, NULL) != |
| NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_D("Create ext_cb_data failed"); |
| return NFCSTATUS_FAILED; |
| } |
| CONCURRENCY_LOCK(); |
| memset(&tOsalConfig, 0x00, sizeof(tOsalConfig)); |
| memset(&tTmlConfig, 0x00, sizeof(tTmlConfig)); |
| memset(&nxpprofile_ctrl, 0, sizeof(phNxpNciProfile_Control_t)); |
| |
| /* By default HAL status is HAL_STATUS_OPEN */ |
| nxpncihal_ctrl.halStatus = HAL_STATUS_OPEN; |
| |
| /*nci version NCI_VERSION_2_0 version by default for SN100 chip type*/ |
| nxpncihal_ctrl.nci_info.nci_version = NCI_VERSION_2_0; |
| /* Read the nfc device node name */ |
| nfc_dev_node = (char*)malloc(NXP_MAX_CONFIG_STRING_LEN * sizeof(char)); |
| if (nfc_dev_node == NULL) { |
| NXPLOG_NCIHAL_D("malloc of nfc_dev_node failed "); |
| CONCURRENCY_UNLOCK(); |
| return phnxpNciHal_partialOpenCleanUp(nfc_dev_node); |
| } else if (!GetNxpStrValue(NAME_NXP_NFC_DEV_NODE, nfc_dev_node, |
| NXP_MAX_CONFIG_STRING_LEN)) { |
| NXPLOG_NCIHAL_D( |
| "Invalid nfc device node name keeping the default device node " |
| "/dev/pn54x"); |
| strlcpy(nfc_dev_node, "/dev/pn54x", |
| (NXP_MAX_CONFIG_STRING_LEN * sizeof(char))); |
| } |
| /* Configure hardware link */ |
| nxpncihal_ctrl.gDrvCfg.nClientId = phDal4Nfc_msgget(0, 0600); |
| nxpncihal_ctrl.gDrvCfg.nLinkType = ENUM_LINK_TYPE_I2C; /* For PN54X */ |
| tTmlConfig.pDevName = (int8_t*)nfc_dev_node; |
| tOsalConfig.dwCallbackThreadId = (uintptr_t)nxpncihal_ctrl.gDrvCfg.nClientId; |
| tOsalConfig.pLogFile = NULL; |
| tTmlConfig.dwGetMsgThreadId = (uintptr_t)nxpncihal_ctrl.gDrvCfg.nClientId; |
| |
| /* Initialize TML layer */ |
| if (phTmlNfc_Init(&tTmlConfig) != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("phTmlNfc_Init Failed"); |
| CONCURRENCY_UNLOCK(); |
| return phnxpNciHal_partialOpenCleanUp(nfc_dev_node); |
| } else { |
| if (nfc_dev_node != NULL) { |
| free(nfc_dev_node); |
| nfc_dev_node = NULL; |
| } |
| } |
| /* Create the client thread */ |
| if (pthread_create(&nxpncihal_ctrl.client_thread, NULL, |
| phNxpNciHal_client_thread, &nxpncihal_ctrl) != 0) { |
| NXPLOG_NCIHAL_E("pthread_create failed"); |
| if (phTmlNfc_Shutdown_CleanUp() != NFCSTATUS_SUCCESS) { |
| NXPLOG_NCIHAL_E("phTmlNfc_Shutdown_CleanUp: Failed"); |
| } |
| CONCURRENCY_UNLOCK(); |
| return phnxpNciHal_partialOpenCleanUp(nfc_dev_node); |
| } |
| phNxpNciHal_readNFCCClockCfgValues(); |
| CONCURRENCY_UNLOCK(); |
| return NFCSTATUS_SUCCESS; |
| } |
| |
| /******************************************************************************* |
| * |
| * Function phnxpNciHal_partialClose |
| * |
| * Description close the Minimal HAL |
| * |
| * Parameters none |
| * |
| * Returns void |
| *******************************************************************************/ |
| static void phnxpNciHal_partialClose(void) { |
| phLibNfc_Message_t msg; |
| nxpncihal_ctrl.halStatus = HAL_STATUS_CLOSE; |
| |
| if (NULL != gpphTmlNfc_Context->pDevHandle) { |
| msg.eMsgType = NCI_HAL_CLOSE_CPLT_MSG; |
| msg.pMsgData = NULL; |
| msg.Size = 0; |
| phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &msg); |
| /* Abort any pending read and write */ |
| phTmlNfc_ReadAbort(); |
| phTmlNfc_WriteAbort(); |
| phTmlNfc_Shutdown(); |
| if (0 != pthread_join(nxpncihal_ctrl.client_thread, (void**)NULL)) { |
| NXPLOG_TML_E("Fail to kill client thread!"); |
| } |
| phTmlNfc_CleanUp(); |
| phDal4Nfc_msgrelease(nxpncihal_ctrl.gDrvCfg.nClientId); |
| phNxpNciHal_cleanup_cb_data(&nxpncihal_ctrl.ext_cb_data); |
| memset(&nxpncihal_ctrl, 0x00, sizeof(nxpncihal_ctrl)); |
| NXPLOG_NCIHAL_D("phnxpNciHal_partialClose - phOsalNfc_DeInit completed"); |
| } |
| CONCURRENCY_UNLOCK(); |
| phNxpNciHal_cleanup_monitor(); |
| } |
| |
| #endif |