/****************************************************************************** * * Copyright (C) 1999-2012 Broadcom Corporation * * 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. * ******************************************************************************/ #include <android-base/stringprintf.h> #include <android/hardware/nfc/1.1/INfc.h> #include <android/hardware/nfc/1.2/INfc.h> #include <base/command_line.h> #include <base/logging.h> #include <cutils/properties.h> #include <hwbinder/ProcessState.h> #include "NfcAdaptation.h" #include "debug_nfcsnoop.h" #include "nfa_api.h" #include "nfa_rw_api.h" #include "nfc_config.h" #include "nfc_int.h" using android::OK; using android::sp; using android::status_t; using android::base::StringPrintf; using android::hardware::ProcessState; using android::hardware::Return; using android::hardware::Void; using android::hardware::nfc::V1_0::INfc; using android::hardware::nfc::V1_1::PresenceCheckAlgorithm; using INfcV1_1 = android::hardware::nfc::V1_1::INfc; using INfcV1_2 = android::hardware::nfc::V1_2::INfc; using NfcVendorConfigV1_1 = android::hardware::nfc::V1_1::NfcConfig; using NfcVendorConfigV1_2 = android::hardware::nfc::V1_2::NfcConfig; using android::hardware::nfc::V1_1::INfcClientCallback; using android::hardware::hidl_vec; extern bool nfc_debug_enabled; extern void GKI_shutdown(); extern void verify_stack_non_volatile_store(); extern void delete_stack_non_volatile_store(bool forceDelete); NfcAdaptation* NfcAdaptation::mpInstance = nullptr; ThreadMutex NfcAdaptation::sLock; tHAL_NFC_CBACK* NfcAdaptation::mHalCallback = nullptr; tHAL_NFC_DATA_CBACK* NfcAdaptation::mHalDataCallback = nullptr; ThreadCondVar NfcAdaptation::mHalOpenCompletedEvent; ThreadCondVar NfcAdaptation::mHalCloseCompletedEvent; sp<INfc> NfcAdaptation::mHal; sp<INfcV1_1> NfcAdaptation::mHal_1_1; sp<INfcV1_2> NfcAdaptation::mHal_1_2; INfcClientCallback* NfcAdaptation::mCallback; bool nfc_debug_enabled = false; std::string nfc_storage_path; uint8_t appl_dta_mode_flag = 0x00; bool isDownloadFirmwareCompleted = false; extern tNFA_DM_CFG nfa_dm_cfg; extern tNFA_PROPRIETARY_CFG nfa_proprietary_cfg; extern tNFA_HCI_CFG nfa_hci_cfg; extern uint8_t nfa_ee_max_ee_cfg; extern bool nfa_poll_bail_out_mode; // Whitelist for hosts allowed to create a pipe // See ADM_CREATE_PIPE command in the ETSI test specification // ETSI TS 102 622, section 6.1.3.1 static std::vector<uint8_t> host_whitelist; namespace { void initializeGlobalDebugEnabledFlag() { nfc_debug_enabled = (NfcConfig::getUnsigned(NAME_NFC_DEBUG_ENABLED, 0) != 0) ? true : false; char valueStr[PROPERTY_VALUE_MAX] = {0}; int len = property_get("nfc.debug_enabled", valueStr, ""); if (len > 0) { // let Android property override .conf variable unsigned debug_enabled = 0; sscanf(valueStr, "%u", &debug_enabled); nfc_debug_enabled = (debug_enabled == 0) ? false : true; } DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: level=%u", __func__, nfc_debug_enabled); } } // namespace class NfcClientCallback : public INfcClientCallback { public: NfcClientCallback(tHAL_NFC_CBACK* eventCallback, tHAL_NFC_DATA_CBACK dataCallback) { mEventCallback = eventCallback; mDataCallback = dataCallback; }; virtual ~NfcClientCallback() = default; Return<void> sendEvent_1_1( ::android::hardware::nfc::V1_1::NfcEvent event, ::android::hardware::nfc::V1_0::NfcStatus event_status) override { mEventCallback((uint8_t)event, (tHAL_NFC_STATUS)event_status); return Void(); }; Return<void> sendEvent( ::android::hardware::nfc::V1_0::NfcEvent event, ::android::hardware::nfc::V1_0::NfcStatus event_status) override { mEventCallback((uint8_t)event, (tHAL_NFC_STATUS)event_status); return Void(); }; Return<void> sendData( const ::android::hardware::nfc::V1_0::NfcData& data) override { ::android::hardware::nfc::V1_0::NfcData copy = data; mDataCallback(copy.size(), ©[0]); return Void(); }; private: tHAL_NFC_CBACK* mEventCallback; tHAL_NFC_DATA_CBACK* mDataCallback; }; /******************************************************************************* ** ** Function: NfcAdaptation::NfcAdaptation() ** ** Description: class constructor ** ** Returns: none ** *******************************************************************************/ NfcAdaptation::NfcAdaptation() { memset(&mHalEntryFuncs, 0, sizeof(mHalEntryFuncs)); } /******************************************************************************* ** ** Function: NfcAdaptation::~NfcAdaptation() ** ** Description: class destructor ** ** Returns: none ** *******************************************************************************/ NfcAdaptation::~NfcAdaptation() { mpInstance = nullptr; } /******************************************************************************* ** ** Function: NfcAdaptation::GetInstance() ** ** Description: access class singleton ** ** Returns: pointer to the singleton object ** *******************************************************************************/ NfcAdaptation& NfcAdaptation::GetInstance() { AutoThreadMutex a(sLock); if (!mpInstance) { mpInstance = new NfcAdaptation; mpInstance->InitializeHalDeviceContext(); } return *mpInstance; } void NfcAdaptation::GetVendorConfigs( std::map<std::string, ConfigValue>& configMap) { NfcVendorConfigV1_2 configValue; if (mHal_1_2) { mHal_1_2->getConfig_1_2( [&configValue](NfcVendorConfigV1_2 config) { configValue = config; }); } else if (mHal_1_1) { mHal_1_1->getConfig([&configValue](NfcVendorConfigV1_1 config) { configValue.v1_1 = config; configValue.defaultIsoDepRoute = 0x00; }); } if (mHal_1_1 || mHal_1_2) { std::vector<uint8_t> nfaPropCfg = { configValue.v1_1.nfaProprietaryCfg.protocol18092Active, configValue.v1_1.nfaProprietaryCfg.protocolBPrime, configValue.v1_1.nfaProprietaryCfg.protocolDual, configValue.v1_1.nfaProprietaryCfg.protocol15693, configValue.v1_1.nfaProprietaryCfg.protocolKovio, configValue.v1_1.nfaProprietaryCfg.protocolMifare, configValue.v1_1.nfaProprietaryCfg.discoveryPollKovio, configValue.v1_1.nfaProprietaryCfg.discoveryPollBPrime, configValue.v1_1.nfaProprietaryCfg.discoveryListenBPrime}; configMap.emplace(NAME_NFA_PROPRIETARY_CFG, ConfigValue(nfaPropCfg)); configMap.emplace(NAME_NFA_POLL_BAIL_OUT_MODE, ConfigValue(configValue.v1_1.nfaPollBailOutMode ? 1 : 0)); configMap.emplace(NAME_DEFAULT_OFFHOST_ROUTE, ConfigValue(configValue.v1_1.defaultOffHostRoute)); if (configValue.offHostRouteUicc.size() != 0) { configMap.emplace(NAME_OFFHOST_ROUTE_UICC, ConfigValue(configValue.offHostRouteUicc)); } if (configValue.offHostRouteEse.size() != 0) { configMap.emplace(NAME_OFFHOST_ROUTE_ESE, ConfigValue(configValue.offHostRouteEse)); } configMap.emplace(NAME_DEFAULT_ROUTE, ConfigValue(configValue.v1_1.defaultRoute)); configMap.emplace(NAME_DEFAULT_NFCF_ROUTE, ConfigValue(configValue.v1_1.defaultOffHostRouteFelica)); configMap.emplace(NAME_DEFAULT_ISODEP_ROUTE, ConfigValue(configValue.defaultIsoDepRoute)); configMap.emplace(NAME_DEFAULT_SYS_CODE_ROUTE, ConfigValue(configValue.v1_1.defaultSystemCodeRoute)); configMap.emplace( NAME_DEFAULT_SYS_CODE_PWR_STATE, ConfigValue(configValue.v1_1.defaultSystemCodePowerState)); configMap.emplace(NAME_OFF_HOST_SIM_PIPE_ID, ConfigValue(configValue.v1_1.offHostSIMPipeId)); configMap.emplace(NAME_OFF_HOST_ESE_PIPE_ID, ConfigValue(configValue.v1_1.offHostESEPipeId)); configMap.emplace(NAME_ISO_DEP_MAX_TRANSCEIVE, ConfigValue(configValue.v1_1.maxIsoDepTransceiveLength)); if (configValue.v1_1.hostWhitelist.size() != 0) { configMap.emplace(NAME_DEVICE_HOST_WHITE_LIST, ConfigValue(configValue.v1_1.hostWhitelist)); } /* For Backwards compatibility */ if (configValue.v1_1.presenceCheckAlgorithm == PresenceCheckAlgorithm::ISO_DEP_NAK) { configMap.emplace(NAME_PRESENCE_CHECK_ALGORITHM, ConfigValue((uint32_t)NFA_RW_PRES_CHK_ISO_DEP_NAK)); } else { configMap.emplace( NAME_PRESENCE_CHECK_ALGORITHM, ConfigValue((uint32_t)configValue.v1_1.presenceCheckAlgorithm)); } } } /******************************************************************************* ** ** Function: NfcAdaptation::Initialize() ** ** Description: class initializer ** ** Returns: none ** *******************************************************************************/ void NfcAdaptation::Initialize() { const char* func = "NfcAdaptation::Initialize"; const char* argv[] = {"libnfc_nci"}; // Init log tag base::CommandLine::Init(1, argv); // Android already logs thread_id, proc_id, timestamp, so disable those. logging::SetLogItems(false, false, false, false); initializeGlobalDebugEnabledFlag(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", func); nfc_storage_path = NfcConfig::getString(NAME_NFA_STORAGE, "/data/nfc"); if (NfcConfig::hasKey(NAME_NFA_DM_CFG)) { std::vector<uint8_t> dm_config = NfcConfig::getBytes(NAME_NFA_DM_CFG); if (dm_config.size() > 0) nfa_dm_cfg.auto_detect_ndef = dm_config[0]; if (dm_config.size() > 1) nfa_dm_cfg.auto_read_ndef = dm_config[1]; if (dm_config.size() > 2) nfa_dm_cfg.auto_presence_check = dm_config[2]; if (dm_config.size() > 3) nfa_dm_cfg.presence_check_option = dm_config[3]; // NOTE: The timeout value is not configurable here because the endianess // of a byte array is ambiguous and needlessly difficult to configure. // If this value needs to be configgurable, a numeric config option should // be used. } if (NfcConfig::hasKey(NAME_NFA_MAX_EE_SUPPORTED)) { nfa_ee_max_ee_cfg = NfcConfig::getUnsigned(NAME_NFA_MAX_EE_SUPPORTED); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Overriding NFA_EE_MAX_EE_SUPPORTED to use %d", func, nfa_ee_max_ee_cfg); } if (NfcConfig::hasKey(NAME_NFA_POLL_BAIL_OUT_MODE)) { nfa_poll_bail_out_mode = NfcConfig::getUnsigned(NAME_NFA_POLL_BAIL_OUT_MODE); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Overriding NFA_POLL_BAIL_OUT_MODE to use %d", func, nfa_poll_bail_out_mode); } if (NfcConfig::hasKey(NAME_NFA_PROPRIETARY_CFG)) { std::vector<uint8_t> p_config = NfcConfig::getBytes(NAME_NFA_PROPRIETARY_CFG); if (p_config.size() > 0) nfa_proprietary_cfg.pro_protocol_18092_active = p_config[0]; if (p_config.size() > 1) nfa_proprietary_cfg.pro_protocol_b_prime = p_config[1]; if (p_config.size() > 2) nfa_proprietary_cfg.pro_protocol_dual = p_config[2]; if (p_config.size() > 3) nfa_proprietary_cfg.pro_protocol_15693 = p_config[3]; if (p_config.size() > 4) nfa_proprietary_cfg.pro_protocol_kovio = p_config[4]; if (p_config.size() > 5) nfa_proprietary_cfg.pro_protocol_mfc = p_config[5]; if (p_config.size() > 6) nfa_proprietary_cfg.pro_discovery_kovio_poll = p_config[6]; if (p_config.size() > 7) nfa_proprietary_cfg.pro_discovery_b_prime_poll = p_config[7]; if (p_config.size() > 8) nfa_proprietary_cfg.pro_discovery_b_prime_listen = p_config[8]; } // Configure whitelist of HCI host ID's // See specification: ETSI TS 102 622, section 6.1.3.1 if (NfcConfig::hasKey(NAME_DEVICE_HOST_WHITE_LIST)) { host_whitelist = NfcConfig::getBytes(NAME_DEVICE_HOST_WHITE_LIST); nfa_hci_cfg.num_whitelist_host = host_whitelist.size(); nfa_hci_cfg.p_whitelist = &host_whitelist[0]; } verify_stack_non_volatile_store(); if (NfcConfig::hasKey(NAME_PRESERVE_STORAGE) && NfcConfig::getUnsigned(NAME_PRESERVE_STORAGE) == 1) { DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: preserve stack NV store", __func__); } else { delete_stack_non_volatile_store(FALSE); } GKI_init(); GKI_enable(); GKI_create_task((TASKPTR)NFCA_TASK, BTU_TASK, (int8_t*)"NFCA_TASK", nullptr, 0, (pthread_cond_t*)nullptr, nullptr); { AutoThreadMutex guard(mCondVar); GKI_create_task((TASKPTR)Thread, MMI_TASK, (int8_t*)"NFCA_THREAD", nullptr, 0, (pthread_cond_t*)nullptr, nullptr); mCondVar.wait(); } debug_nfcsnoop_init(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", func); } /******************************************************************************* ** ** Function: NfcAdaptation::Finalize() ** ** Description: class finalizer ** ** Returns: none ** *******************************************************************************/ void NfcAdaptation::Finalize() { const char* func = "NfcAdaptation::Finalize"; AutoThreadMutex a(sLock); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", func); GKI_shutdown(); NfcConfig::clear(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", func); delete this; } void NfcAdaptation::FactoryReset() { if (mHal_1_2 != nullptr) { mHal_1_2->factoryReset(); } else if (mHal_1_1 != nullptr) { mHal_1_1->factoryReset(); } } void NfcAdaptation::DeviceShutdown() { if (mHal_1_2 != nullptr) { mHal_1_2->closeForPowerOffCase(); } else if (mHal_1_1 != nullptr) { mHal_1_1->closeForPowerOffCase(); } } /******************************************************************************* ** ** Function: NfcAdaptation::Dump ** ** Description: Native support for dumpsys function. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::Dump(int fd) { debug_nfcsnoop_dump(fd); } /******************************************************************************* ** ** Function: NfcAdaptation::signal() ** ** Description: signal the CondVar to release the thread that is waiting ** ** Returns: none ** *******************************************************************************/ void NfcAdaptation::signal() { mCondVar.signal(); } /******************************************************************************* ** ** Function: NfcAdaptation::NFCA_TASK() ** ** Description: NFCA_TASK runs the GKI main task ** ** Returns: none ** *******************************************************************************/ uint32_t NfcAdaptation::NFCA_TASK(__attribute__((unused)) uint32_t arg) { const char* func = "NfcAdaptation::NFCA_TASK"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", func); GKI_run(nullptr); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", func); return 0; } /******************************************************************************* ** ** Function: NfcAdaptation::Thread() ** ** Description: Creates work threads ** ** Returns: none ** *******************************************************************************/ uint32_t NfcAdaptation::Thread(__attribute__((unused)) uint32_t arg) { const char* func = "NfcAdaptation::Thread"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", func); { ThreadCondVar CondVar; AutoThreadMutex guard(CondVar); GKI_create_task((TASKPTR)nfc_task, NFC_TASK, (int8_t*)"NFC_TASK", nullptr, 0, (pthread_cond_t*)CondVar, (pthread_mutex_t*)CondVar); CondVar.wait(); } NfcAdaptation::GetInstance().signal(); GKI_exit_task(GKI_get_taskid()); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", func); return 0; } /******************************************************************************* ** ** Function: NfcAdaptation::GetHalEntryFuncs() ** ** Description: Get the set of HAL entry points. ** ** Returns: Functions pointers for HAL entry points. ** *******************************************************************************/ tHAL_NFC_ENTRY* NfcAdaptation::GetHalEntryFuncs() { return &mHalEntryFuncs; } /******************************************************************************* ** ** Function: NfcAdaptation::InitializeHalDeviceContext ** ** Description: Ask the generic Android HAL to find the Broadcom-specific HAL. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::InitializeHalDeviceContext() { const char* func = "NfcAdaptation::InitializeHalDeviceContext"; mHalEntryFuncs.initialize = HalInitialize; mHalEntryFuncs.terminate = HalTerminate; mHalEntryFuncs.open = HalOpen; mHalEntryFuncs.close = HalClose; mHalEntryFuncs.core_initialized = HalCoreInitialized; mHalEntryFuncs.write = HalWrite; mHalEntryFuncs.prediscover = HalPrediscover; mHalEntryFuncs.control_granted = HalControlGranted; mHalEntryFuncs.power_cycle = HalPowerCycle; mHalEntryFuncs.get_max_ee = HalGetMaxNfcee; LOG(INFO) << StringPrintf("%s: INfc::getService()", func); mHal = mHal_1_1 = mHal_1_2 = INfcV1_2::getService(); if (mHal_1_2 == nullptr) { mHal = mHal_1_1 = INfcV1_1::getService(); if (mHal_1_1 == nullptr) { mHal = INfc::getService(); } } LOG_FATAL_IF(mHal == nullptr, "Failed to retrieve the NFC HAL!"); LOG(INFO) << StringPrintf("%s: INfc::getService() returned %p (%s)", func, mHal.get(), (mHal->isRemote() ? "remote" : "local")); } /******************************************************************************* ** ** Function: NfcAdaptation::HalInitialize ** ** Description: Not implemented because this function is only needed ** within the HAL. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalInitialize() { const char* func = "NfcAdaptation::HalInitialize"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); } /******************************************************************************* ** ** Function: NfcAdaptation::HalTerminate ** ** Description: Not implemented because this function is only needed ** within the HAL. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalTerminate() { const char* func = "NfcAdaptation::HalTerminate"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); } /******************************************************************************* ** ** Function: NfcAdaptation::HalOpen ** ** Description: Turn on controller, download firmware. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalOpen(tHAL_NFC_CBACK* p_hal_cback, tHAL_NFC_DATA_CBACK* p_data_cback) { const char* func = "NfcAdaptation::HalOpen"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); mCallback = new NfcClientCallback(p_hal_cback, p_data_cback); if (mHal_1_1 != nullptr) { mHal_1_1->open_1_1(mCallback); } else { mHal->open(mCallback); } } /******************************************************************************* ** ** Function: NfcAdaptation::HalClose ** ** Description: Turn off controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalClose() { const char* func = "NfcAdaptation::HalClose"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); mHal->close(); } /******************************************************************************* ** ** Function: NfcAdaptation::HalDeviceContextCallback ** ** Description: Translate generic Android HAL's callback into Broadcom-specific ** callback function. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalDeviceContextCallback(nfc_event_t event, nfc_status_t event_status) { const char* func = "NfcAdaptation::HalDeviceContextCallback"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: event=%u", func, event); if (mHalCallback) mHalCallback(event, (tHAL_NFC_STATUS)event_status); } /******************************************************************************* ** ** Function: NfcAdaptation::HalDeviceContextDataCallback ** ** Description: Translate generic Android HAL's callback into Broadcom-specific ** callback function. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalDeviceContextDataCallback(uint16_t data_len, uint8_t* p_data) { const char* func = "NfcAdaptation::HalDeviceContextDataCallback"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: len=%u", func, data_len); if (mHalDataCallback) mHalDataCallback(data_len, p_data); } /******************************************************************************* ** ** Function: NfcAdaptation::HalWrite ** ** Description: Write NCI message to the controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalWrite(uint16_t data_len, uint8_t* p_data) { const char* func = "NfcAdaptation::HalWrite"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); ::android::hardware::nfc::V1_0::NfcData data; data.setToExternal(p_data, data_len); mHal->write(data); } /******************************************************************************* ** ** Function: NfcAdaptation::HalCoreInitialized ** ** Description: Adjust the configurable parameters in the controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalCoreInitialized(uint16_t data_len, uint8_t* p_core_init_rsp_params) { const char* func = "NfcAdaptation::HalCoreInitialized"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); hidl_vec<uint8_t> data; data.setToExternal(p_core_init_rsp_params, data_len); mHal->coreInitialized(data); } /******************************************************************************* ** ** Function: NfcAdaptation::HalPrediscover ** ** Description: Perform any vendor-specific pre-discovery actions (if ** needed) If any actions were performed TRUE will be returned, ** and HAL_PRE_DISCOVER_CPLT_EVT will notify when actions are ** completed. ** ** Returns: TRUE if vendor-specific pre-discovery actions initialized ** FALSE if no vendor-specific pre-discovery actions are ** needed. ** *******************************************************************************/ bool NfcAdaptation::HalPrediscover() { const char* func = "NfcAdaptation::HalPrediscover"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); bool retval = FALSE; mHal->prediscover(); return retval; } /******************************************************************************* ** ** Function: HAL_NfcControlGranted ** ** Description: Grant control to HAL control for sending NCI commands. ** Call in response to HAL_REQUEST_CONTROL_EVT. ** Must only be called when there are no NCI commands pending. ** HAL_RELEASE_CONTROL_EVT will notify when HAL no longer ** needs control of NCI. ** ** Returns: void ** *******************************************************************************/ void NfcAdaptation::HalControlGranted() { const char* func = "NfcAdaptation::HalControlGranted"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); mHal->controlGranted(); } /******************************************************************************* ** ** Function: NfcAdaptation::HalPowerCycle ** ** Description: Turn off and turn on the controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalPowerCycle() { const char* func = "NfcAdaptation::HalPowerCycle"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); mHal->powerCycle(); } /******************************************************************************* ** ** Function: NfcAdaptation::HalGetMaxNfcee ** ** Description: Turn off and turn on the controller. ** ** Returns: None. ** *******************************************************************************/ uint8_t NfcAdaptation::HalGetMaxNfcee() { const char* func = "NfcAdaptation::HalPowerCycle"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func); return nfa_ee_max_ee_cfg; } /******************************************************************************* ** ** Function: NfcAdaptation::DownloadFirmware ** ** Description: Download firmware patch files. ** ** Returns: None. ** *******************************************************************************/ bool NfcAdaptation::DownloadFirmware() { const char* func = "NfcAdaptation::DownloadFirmware"; isDownloadFirmwareCompleted = false; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", func); HalInitialize(); mHalOpenCompletedEvent.lock(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: try open HAL", func); HalOpen(HalDownloadFirmwareCallback, HalDownloadFirmwareDataCallback); mHalOpenCompletedEvent.wait(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: try close HAL", func); HalClose(); HalTerminate(); DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", func); return isDownloadFirmwareCompleted; } /******************************************************************************* ** ** Function: NfcAdaptation::HalDownloadFirmwareCallback ** ** Description: Receive events from the HAL. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalDownloadFirmwareCallback(nfc_event_t event, __attribute__((unused)) nfc_status_t event_status) { const char* func = "NfcAdaptation::HalDownloadFirmwareCallback"; DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: event=0x%X", func, event); switch (event) { case HAL_NFC_OPEN_CPLT_EVT: { DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: HAL_NFC_OPEN_CPLT_EVT", func); if (event_status == HAL_NFC_STATUS_OK) isDownloadFirmwareCompleted = true; mHalOpenCompletedEvent.signal(); break; } case HAL_NFC_CLOSE_CPLT_EVT: { DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: HAL_NFC_CLOSE_CPLT_EVT", func); break; } } } /******************************************************************************* ** ** Function: NfcAdaptation::HalDownloadFirmwareDataCallback ** ** Description: Receive data events from the HAL. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalDownloadFirmwareDataCallback(__attribute__((unused)) uint16_t data_len, __attribute__((unused)) uint8_t* p_data) {} /******************************************************************************* ** ** Function: ThreadMutex::ThreadMutex() ** ** Description: class constructor ** ** Returns: none ** *******************************************************************************/ ThreadMutex::ThreadMutex() { pthread_mutexattr_t mutexAttr; pthread_mutexattr_init(&mutexAttr); pthread_mutex_init(&mMutex, &mutexAttr); pthread_mutexattr_destroy(&mutexAttr); } /******************************************************************************* ** ** Function: ThreadMutex::~ThreadMutex() ** ** Description: class destructor ** ** Returns: none ** *******************************************************************************/ ThreadMutex::~ThreadMutex() { pthread_mutex_destroy(&mMutex); } /******************************************************************************* ** ** Function: ThreadMutex::lock() ** ** Description: lock kthe mutex ** ** Returns: none ** *******************************************************************************/ void ThreadMutex::lock() { pthread_mutex_lock(&mMutex); } /******************************************************************************* ** ** Function: ThreadMutex::unblock() ** ** Description: unlock the mutex ** ** Returns: none ** *******************************************************************************/ void ThreadMutex::unlock() { pthread_mutex_unlock(&mMutex); } /******************************************************************************* ** ** Function: ThreadCondVar::ThreadCondVar() ** ** Description: class constructor ** ** Returns: none ** *******************************************************************************/ ThreadCondVar::ThreadCondVar() { pthread_condattr_t CondAttr; pthread_condattr_init(&CondAttr); pthread_cond_init(&mCondVar, &CondAttr); pthread_condattr_destroy(&CondAttr); } /******************************************************************************* ** ** Function: ThreadCondVar::~ThreadCondVar() ** ** Description: class destructor ** ** Returns: none ** *******************************************************************************/ ThreadCondVar::~ThreadCondVar() { pthread_cond_destroy(&mCondVar); } /******************************************************************************* ** ** Function: ThreadCondVar::wait() ** ** Description: wait on the mCondVar ** ** Returns: none ** *******************************************************************************/ void ThreadCondVar::wait() { pthread_cond_wait(&mCondVar, *this); pthread_mutex_unlock(*this); } /******************************************************************************* ** ** Function: ThreadCondVar::signal() ** ** Description: signal the mCondVar ** ** Returns: none ** *******************************************************************************/ void ThreadCondVar::signal() { AutoThreadMutex a(*this); pthread_cond_signal(&mCondVar); } /******************************************************************************* ** ** Function: AutoThreadMutex::AutoThreadMutex() ** ** Description: class constructor, automatically lock the mutex ** ** Returns: none ** *******************************************************************************/ AutoThreadMutex::AutoThreadMutex(ThreadMutex& m) : mm(m) { mm.lock(); } /******************************************************************************* ** ** Function: AutoThreadMutex::~AutoThreadMutex() ** ** Description: class destructor, automatically unlock the mutex ** ** Returns: none ** *******************************************************************************/ AutoThreadMutex::~AutoThreadMutex() { mm.unlock(); }