/****************************************************************************** * * 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 "NfcAdaptation.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug_nfcsnoop.h" #include "nfa_api.h" #include "nfa_rw_api.h" #include "nfc_config.h" #include "nfc_int.h" using ::android::wp; using ::android::hardware::hidl_death_recipient; using ::android::hidl::base::V1_0::IBase; 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; using INfcAidl = ::aidl::android::hardware::nfc::INfc; using NfcAidlConfig = ::aidl::android::hardware::nfc::NfcConfig; using AidlPresenceCheckAlgorithm = ::aidl::android::hardware::nfc::PresenceCheckAlgorithm; using INfcAidlClientCallback = ::aidl::android::hardware::nfc::INfcClientCallback; using NfcAidlEvent = ::aidl::android::hardware::nfc::NfcEvent; using NfcAidlStatus = ::aidl::android::hardware::nfc::NfcStatus; using ::aidl::android::hardware::nfc::NfcCloseType; using Status = ::ndk::ScopedAStatus; #define VERBOSE_VENDOR_LOG_PROPERTY "persist.nfc.vendor_debug_enabled" std::string NFC_AIDL_HAL_SERVICE_NAME = "android.hardware.nfc.INfc/default"; 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; ThreadCondVar NfcAdaptation::mHalOpenCompletedEvent; ThreadCondVar NfcAdaptation::mHalCloseCompletedEvent; sp NfcAdaptation::mHal; sp NfcAdaptation::mHal_1_1; sp NfcAdaptation::mHal_1_2; INfcClientCallback* NfcAdaptation::mCallback; std::shared_ptr mAidlCallback; ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; std::shared_ptr mAidlHal; int32_t mAidlHalVer; bool nfc_nci_reset_keep_cfg_enabled = false; uint8_t nfc_nci_reset_type = 0x00; std::string nfc_storage_path; uint8_t appl_dta_mode_flag = 0x00; bool isDownloadFirmwareCompleted = false; bool use_aidl = false; uint8_t mute_tech_route_option = 0x00; unsigned int t5t_mute_legacy = 0; 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 host_allowlist; namespace { void initializeGlobalDebugEnabledFlag() { bool nfc_debug_enabled = (NfcConfig::getUnsigned(NAME_NFC_DEBUG_ENABLED, 0) != 0) || property_get_bool("persist.nfc.debug_enabled", true); android::base::SetMinimumLogSeverity(nfc_debug_enabled ? android::base::DEBUG : android::base::INFO); LOG(VERBOSE) << StringPrintf("%s: level=%u", __func__, nfc_debug_enabled); } // initialize NciResetType Flag // NCI_RESET_TYPE // 0x00 default, reset configurations every time. // 0x01, reset configurations only once every boot. // 0x02, keep configurations. void initializeNciResetTypeFlag() { nfc_nci_reset_type = NfcConfig::getUnsigned(NAME_NCI_RESET_TYPE, 0); LOG(VERBOSE) << StringPrintf("%s: nfc_nci_reset_type=%u", __func__, nfc_nci_reset_type); } // initialize MuteTechRouteOption Flag // MUTE_TECH_ROUTE_OPTION // 0x00: Default. Route mute techs to DH, enable block bit and set power state // to 0x00 0x01: Remove mute techs from rf discover cmd void initializeNfcMuteTechRouteOptionFlag() { mute_tech_route_option = NfcConfig::getUnsigned(NAME_MUTE_TECH_ROUTE_OPTION, 0); LOG(VERBOSE) << StringPrintf("%s: mute_tech_route_option=%u", __func__, mute_tech_route_option); } // Abort nfc service when AIDL process died. void HalAidlBinderDied(void* /* cookie */) { LOG(ERROR) << __func__ << "INfc aidl hal died, exiting procces to restart"; exit(0); } } // namespace class NfcClientCallback : public INfcClientCallback { public: NfcClientCallback(tHAL_NFC_CBACK* eventCallback, tHAL_NFC_DATA_CBACK dataCallback) { mEventCallback = eventCallback; mDataCallback = dataCallback; }; virtual ~NfcClientCallback() = default; Return 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 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 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; }; class NfcHalDeathRecipient : public hidl_death_recipient { public: android::sp mNfcDeathHal; NfcHalDeathRecipient(android::sp& mHal) { mNfcDeathHal = mHal; } virtual void serviceDied( uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* who */) { ALOGE( "NfcHalDeathRecipient::serviceDied - Nfc-Hal service died. Killing " "NfcService"); if (mNfcDeathHal) { mNfcDeathHal->unlinkToDeath(this); } mNfcDeathHal = NULL; exit(0); } void finalize() { if (mNfcDeathHal) { mNfcDeathHal->unlinkToDeath(this); } else { LOG(VERBOSE) << StringPrintf("%s: mNfcDeathHal is not set", __func__); } ALOGI("NfcHalDeathRecipient::destructor - NfcService"); mNfcDeathHal = NULL; } }; class NfcAidlClientCallback : public ::aidl::android::hardware::nfc::BnNfcClientCallback { public: NfcAidlClientCallback(tHAL_NFC_CBACK* eventCallback, tHAL_NFC_DATA_CBACK dataCallback) { mEventCallback = eventCallback; mDataCallback = dataCallback; }; virtual ~NfcAidlClientCallback() = default; ::ndk::ScopedAStatus sendEvent(NfcAidlEvent event, NfcAidlStatus event_status) override { uint8_t e_num; uint8_t s_num; switch (event) { case NfcAidlEvent::OPEN_CPLT: e_num = HAL_NFC_OPEN_CPLT_EVT; break; case NfcAidlEvent::CLOSE_CPLT: e_num = HAL_NFC_CLOSE_CPLT_EVT; break; case NfcAidlEvent::POST_INIT_CPLT: e_num = HAL_NFC_POST_INIT_CPLT_EVT; break; case NfcAidlEvent::PRE_DISCOVER_CPLT: e_num = HAL_NFC_PRE_DISCOVER_CPLT_EVT; break; case NfcAidlEvent::HCI_NETWORK_RESET: e_num = HAL_HCI_NETWORK_RESET; break; case NfcAidlEvent::REQUEST_CONTROL: e_num = HAL_NFC_REQUEST_CONTROL_EVT; break; case NfcAidlEvent::RELEASE_CONTROL: e_num = HAL_NFC_RELEASE_CONTROL_EVT; break; case NfcAidlEvent::ERROR: default: e_num = HAL_NFC_ERROR_EVT; } switch (event_status) { case NfcAidlStatus::OK: s_num = HAL_NFC_STATUS_OK; break; case NfcAidlStatus::FAILED: s_num = HAL_NFC_STATUS_FAILED; break; case NfcAidlStatus::ERR_TRANSPORT: s_num = HAL_NFC_STATUS_ERR_TRANSPORT; break; case NfcAidlStatus::ERR_CMD_TIMEOUT: s_num = HAL_NFC_STATUS_ERR_CMD_TIMEOUT; break; case NfcAidlStatus::REFUSED: s_num = HAL_NFC_STATUS_REFUSED; break; default: s_num = HAL_NFC_STATUS_FAILED; } mEventCallback(e_num, (tHAL_NFC_STATUS)s_num); return ::ndk::ScopedAStatus::ok(); }; ::ndk::ScopedAStatus sendData(const std::vector& data) override { std::vector copy = data; mDataCallback(copy.size(), ©[0]); return ::ndk::ScopedAStatus::ok(); }; 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)); mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(HalAidlBinderDied)); } /******************************************************************************* ** ** 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& configMap) { NfcVendorConfigV1_2 configValue; NfcAidlConfig aidlConfigValue; if (mAidlHal) { mAidlHal->getConfig(&aidlConfigValue); } else 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 (mAidlHal) { std::vector nfaPropCfg = { aidlConfigValue.nfaProprietaryCfg.protocol18092Active, aidlConfigValue.nfaProprietaryCfg.protocolBPrime, aidlConfigValue.nfaProprietaryCfg.protocolDual, aidlConfigValue.nfaProprietaryCfg.protocol15693, aidlConfigValue.nfaProprietaryCfg.protocolKovio, aidlConfigValue.nfaProprietaryCfg.protocolMifare, aidlConfigValue.nfaProprietaryCfg.discoveryPollKovio, aidlConfigValue.nfaProprietaryCfg.discoveryPollBPrime, aidlConfigValue.nfaProprietaryCfg.discoveryListenBPrime, aidlConfigValue.nfaProprietaryCfg.protocolChineseId}; configMap.emplace(NAME_NFA_PROPRIETARY_CFG, ConfigValue(nfaPropCfg)); configMap.emplace(NAME_NFA_POLL_BAIL_OUT_MODE, ConfigValue(aidlConfigValue.nfaPollBailOutMode ? 1 : 0)); if (aidlConfigValue.offHostRouteUicc.size() != 0) { configMap.emplace(NAME_OFFHOST_ROUTE_UICC, ConfigValue(aidlConfigValue.offHostRouteUicc)); } if (aidlConfigValue.offHostRouteEse.size() != 0) { configMap.emplace(NAME_OFFHOST_ROUTE_ESE, ConfigValue(aidlConfigValue.offHostRouteEse)); } // AIDL byte would be int8_t in C++. // Here we force cast int8_t to uint8_t for ConfigValue configMap.emplace( NAME_DEFAULT_OFFHOST_ROUTE, ConfigValue((uint8_t)aidlConfigValue.defaultOffHostRoute)); configMap.emplace(NAME_DEFAULT_ROUTE, ConfigValue((uint8_t)aidlConfigValue.defaultRoute)); configMap.emplace( NAME_DEFAULT_NFCF_ROUTE, ConfigValue((uint8_t)aidlConfigValue.defaultOffHostRouteFelica)); configMap.emplace(NAME_DEFAULT_ISODEP_ROUTE, ConfigValue((uint8_t)aidlConfigValue.defaultIsoDepRoute)); configMap.emplace( NAME_DEFAULT_SYS_CODE_ROUTE, ConfigValue((uint8_t)aidlConfigValue.defaultSystemCodeRoute)); configMap.emplace( NAME_DEFAULT_SYS_CODE_PWR_STATE, ConfigValue((uint8_t)aidlConfigValue.defaultSystemCodePowerState)); configMap.emplace(NAME_OFF_HOST_SIM_PIPE_ID, ConfigValue((uint8_t)aidlConfigValue.offHostSIMPipeId)); configMap.emplace(NAME_OFF_HOST_ESE_PIPE_ID, ConfigValue((uint8_t)aidlConfigValue.offHostESEPipeId)); configMap.emplace(NAME_T4T_NFCEE_ENABLE, ConfigValue(aidlConfigValue.t4tNfceeEnable ? 1 : 0)); if (aidlConfigValue.offHostSimPipeIds.size() != 0) { configMap.emplace(NAME_OFF_HOST_SIM_PIPE_IDS, ConfigValue(aidlConfigValue.offHostSimPipeIds)); } configMap.emplace(NAME_ISO_DEP_MAX_TRANSCEIVE, ConfigValue(aidlConfigValue.maxIsoDepTransceiveLength)); if (aidlConfigValue.hostAllowlist.size() != 0) { configMap.emplace(NAME_DEVICE_HOST_ALLOW_LIST, ConfigValue(aidlConfigValue.hostAllowlist)); } /* For Backwards compatibility */ if (aidlConfigValue.presenceCheckAlgorithm == AidlPresenceCheckAlgorithm::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)aidlConfigValue.presenceCheckAlgorithm)); } } else if (mHal_1_1 || mHal_1_2) { std::vector 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_ALLOW_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"; // Init log tag android::base::InitLogging(nullptr); android::base::SetDefaultTag("libnfc_nci"); initializeGlobalDebugEnabledFlag(); initializeNciResetTypeFlag(); initializeNfcMuteTechRouteOptionFlag(); LOG(VERBOSE) << StringPrintf("%s: enter", func); nfc_storage_path = NfcConfig::getString(NAME_NFA_STORAGE, "/data/nfc"); if (NfcConfig::hasKey(NAME_NFA_DM_CFG)) { std::vector 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 endianness // of a byte array is ambiguous and needlessly difficult to configure. // If this value needs to be configurable, 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); LOG(VERBOSE) << 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); LOG(VERBOSE) << 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 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]; if (p_config.size() > 9) nfa_proprietary_cfg.pro_protocol_chinese_id = p_config[9]; } // Configure allowlist of HCI host ID's // See specification: ETSI TS 102 622, section 6.1.3.1 if (NfcConfig::hasKey(NAME_DEVICE_HOST_ALLOW_LIST)) { host_allowlist = NfcConfig::getBytes(NAME_DEVICE_HOST_ALLOW_LIST); nfa_hci_cfg.num_allowlist_host = host_allowlist.size(); nfa_hci_cfg.p_allowlist = &host_allowlist[0]; } if (NfcConfig::hasKey(NAME_ISO15693_SKIP_GET_SYS_INFO_CMD)) { t5t_mute_legacy = NfcConfig::getUnsigned(NAME_ISO15693_SKIP_GET_SYS_INFO_CMD); } if (NfcConfig::hasKey(NAME_NFA_DM_LISTEN_ACTIVE_DEACT_NTF_TIMEOUT)) { unsigned int value = NfcConfig::getUnsigned(NAME_NFA_DM_LISTEN_ACTIVE_DEACT_NTF_TIMEOUT); if (value > 0) { nfa_dm_cfg.deact_ntf_listen_active_timeout = value * 1000; } } verify_stack_non_volatile_store(); if (NfcConfig::hasKey(NAME_PRESERVE_STORAGE) && NfcConfig::getUnsigned(NAME_PRESERVE_STORAGE) == 1) { LOG(VERBOSE) << 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(); LOG(VERBOSE) << StringPrintf("%s: exit", func); } /******************************************************************************* ** ** Function: NfcAdaptation::Finalize() ** ** Description: class finalizer ** ** Returns: none ** *******************************************************************************/ void NfcAdaptation::Finalize() { const char* func = "NfcAdaptation::Finalize"; AutoThreadMutex a(sLock); LOG(VERBOSE) << StringPrintf("%s: enter", func); GKI_shutdown(); NfcConfig::clear(); if (mAidlHal != nullptr) { AIBinder_unlinkToDeath(mAidlHal->asBinder().get(), mDeathRecipient.get(), nullptr); } else if (mHal != nullptr) { mNfcHalDeathRecipient->finalize(); } LOG(VERBOSE) << StringPrintf("%s: exit", func); delete this; } void NfcAdaptation::FactoryReset() { if (mAidlHal != nullptr) { mAidlHal->factoryReset(); } else if (mHal_1_2 != nullptr) { mHal_1_2->factoryReset(); } else if (mHal_1_1 != nullptr) { mHal_1_1->factoryReset(); } } void NfcAdaptation::DeviceShutdown() { if (mAidlHal != nullptr) { mAidlHal->close(NfcCloseType::HOST_SWITCHED_OFF); AIBinder_unlinkToDeath(mAidlHal->asBinder().get(), mDeathRecipient.get(), nullptr); mAidlHal = nullptr; } else { if (mHal_1_2 != nullptr) { mHal_1_2->closeForPowerOffCase(); } else if (mHal_1_1 != nullptr) { mHal_1_1->closeForPowerOffCase(); } if (mHal != nullptr) { mHal->unlinkToDeath(mNfcHalDeathRecipient); } } } /******************************************************************************* ** ** 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"; LOG(VERBOSE) << StringPrintf("%s: enter", func); GKI_run(nullptr); LOG(VERBOSE) << 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"; LOG(VERBOSE) << 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()); LOG(VERBOSE) << 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: Check validity of current handle to the nfc HAL service ** ** 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); mAidlHal = nullptr; mHal = mHal_1_1 = mHal_1_2 = nullptr; if (!use_aidl) { mHal = mHal_1_1 = mHal_1_2 = INfcV1_2::getService(); } if (!use_aidl && mHal_1_2 == nullptr) { mHal = mHal_1_1 = INfcV1_1::getService(); if (mHal_1_1 == nullptr) { mHal = INfc::getService(); } } if (mHal == nullptr) { // Try get AIDL ::ndk::SpAIBinder binder( AServiceManager_waitForService(NFC_AIDL_HAL_SERVICE_NAME.c_str())); mAidlHal = INfcAidl::fromBinder(binder); if (mAidlHal != nullptr) { use_aidl = true; AIBinder_linkToDeath(mAidlHal->asBinder().get(), mDeathRecipient.get(), nullptr /* cookie */); mHal = mHal_1_1 = mHal_1_2 = nullptr; mAidlHal->getInterfaceVersion(&mAidlHalVer); LOG(INFO) << StringPrintf("%s: INfcAidl::fromBinder returned ver(%d)", func, mAidlHalVer); } LOG_ALWAYS_FATAL_IF(mAidlHal == nullptr, "Failed to retrieve the NFC AIDL!"); } else { LOG(INFO) << StringPrintf("%s: INfc::getService() returned %p (%s)", func, mHal.get(), (mHal->isRemote() ? "remote" : "local")); mNfcHalDeathRecipient = new NfcHalDeathRecipient(mHal); mHal->linkToDeath(mNfcHalDeathRecipient, 0); } } /******************************************************************************* ** ** 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"; LOG(VERBOSE) << 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"; LOG(VERBOSE) << 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"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { mAidlCallback = ::ndk::SharedRefBase::make( p_hal_cback, p_data_cback); Status status = mAidlHal->open(mAidlCallback); if (!status.isOk()) { LOG(ERROR) << "Open Error: " << ::aidl::android::hardware::nfc::toString( static_cast( status.getServiceSpecificError())); } else { bool verbose_vendor_log = android::base::GetBoolProperty(VERBOSE_VENDOR_LOG_PROPERTY, false); mAidlHal->setEnableVerboseLogging(verbose_vendor_log); LOG(VERBOSE) << StringPrintf("%s: verbose_vendor_log=%u", __func__, verbose_vendor_log); } } else if (mHal_1_1 != nullptr) { mCallback = new NfcClientCallback(p_hal_cback, p_data_cback); mHal_1_1->open_1_1(mCallback); } else if (mHal != nullptr) { mCallback = new NfcClientCallback(p_hal_cback, p_data_cback); mHal->open(mCallback); } } /******************************************************************************* ** ** Function: NfcAdaptation::HalClose ** ** Description: Turn off controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalClose() { const char* func = "NfcAdaptation::HalClose"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { mAidlHal->close(NfcCloseType::DISABLE); } else if (mHal != nullptr) { mHal->close(); } } /******************************************************************************* ** ** 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"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { int ret; std::vector aidl_data(p_data, p_data + data_len); mAidlHal->write(aidl_data, &ret); } else if (mHal != nullptr) { ::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"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { // AIDL coreInitialized doesn't send data to HAL. mAidlHal->coreInitialized(); } else if (mHal != nullptr) { hidl_vec 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"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { Status status = mAidlHal->preDiscover(); if (status.isOk()) { LOG(VERBOSE) << StringPrintf("%s wait for NFC_PRE_DISCOVER_CPLT_EVT", func); return true; } } else if (mHal != nullptr) { mHal->prediscover(); } return false; } /******************************************************************************* ** ** 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"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { if (mAidlHalVer > 1) { NfcAidlStatus aidl_status; mAidlHal->controlGranted(&aidl_status); } else { LOG(ERROR) << StringPrintf("Unsupported function %s", func); } } else if (mHal != nullptr) { mHal->controlGranted(); } } /******************************************************************************* ** ** Function: NfcAdaptation::HalPowerCycle ** ** Description: Turn off and turn on the controller. ** ** Returns: None. ** *******************************************************************************/ void NfcAdaptation::HalPowerCycle() { const char* func = "NfcAdaptation::HalPowerCycle"; LOG(VERBOSE) << StringPrintf("%s", func); if (mAidlHal != nullptr) { mAidlHal->powerCycle(); } else if (mHal != nullptr) { mHal->powerCycle(); } } /******************************************************************************* ** ** Function: NfcAdaptation::HalGetMaxNfcee ** ** Description: Turn off and turn on the controller. ** ** Returns: None. ** *******************************************************************************/ uint8_t NfcAdaptation::HalGetMaxNfcee() { const char* func = "NfcAdaptation::HalGetMaxNfcee"; LOG(VERBOSE) << 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; LOG(VERBOSE) << StringPrintf("%s: enter", func); HalInitialize(); mHalOpenCompletedEvent.lock(); LOG(VERBOSE) << StringPrintf("%s: try open HAL", func); HalOpen(HalDownloadFirmwareCallback, HalDownloadFirmwareDataCallback); mHalOpenCompletedEvent.wait(); LOG(VERBOSE) << StringPrintf("%s: try close HAL", func); HalClose(); HalTerminate(); LOG(VERBOSE) << 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"; LOG(VERBOSE) << StringPrintf("%s: event=0x%X", func, event); switch (event) { case HAL_NFC_OPEN_CPLT_EVT: { LOG(VERBOSE) << 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: { LOG(VERBOSE) << 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(); }