#include "hal/ffi/hidl.h" #include #include 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::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using android::hardware::nfc::V1_0::INfc; using INfcV1_1 = android::hardware::nfc::V1_1::INfc; using INfcV1_2 = android::hardware::nfc::V1_2::INfc; using android::hardware::nfc::V1_1::INfcClientCallback; namespace nfc { namespace hal { namespace { class NfcHalDeathRecipient : public hidl_death_recipient { public: virtual void serviceDied( uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) { LOG_FATAL("Nfc HAL service died!"); abort(); } }; class NfcCallbackTrampoline : public INfcClientCallback { public: NfcCallbackTrampoline() {} Return sendEvent_1_1( ::android::hardware::nfc::V1_1::NfcEvent event, ::android::hardware::nfc::V1_0::NfcStatus event_status) override { on_event(event, event_status); return Void(); } Return sendEvent( ::android::hardware::nfc::V1_0::NfcEvent event, ::android::hardware::nfc::V1_0::NfcStatus event_status) override { on_event((::android::hardware::nfc::V1_1::NfcEvent)event, event_status); return Void(); } Return sendData(const ::android::hardware::nfc::V1_0::NfcData& data) { on_data(rust::Slice(&data[0], data.size())); return Void(); } }; android::sp nfc_death_recipient_; android::sp nci_; android::sp nci_1_1_; android::sp nci_1_2_; android::sp trampoline_; } // namespace void start_hal() { ALOG_ASSERT(nci_ != nullptr, "Stale value of the NCI port"); nci_ = nci_1_1_ = nci_1_2_ = INfcV1_2::getService(); if (nci_1_2_ == nullptr) { nci_ = nci_1_1_ = INfcV1_1::getService(); if (nci_1_1_ == nullptr) { nci_ = INfc::getService(); } } LOG_FATAL_IF(nci_ == nullptr, "Failed to retrieve the NFC HAL!"); ALOGI("%s: INfc::getService() returned %p (%s)", __func__, nci_.get(), (nci_->isRemote() ? "remote" : "local")); if (nci_) { nfc_death_recipient_ = new NfcHalDeathRecipient(); auto death_link = nci_->linkToDeath(nfc_death_recipient_, 0); ALOG_ASSERT(death_link.isOk(), "Unable to set the death recipient for the Nfc HAL"); } trampoline_ = new NfcCallbackTrampoline(); if (nci_1_1_ != nullptr) { nci_1_1_->open_1_1(trampoline_); } else { nci_->open(trampoline_); } } void stop_hal() { ALOG_ASSERT(nci_ == nullptr, "The NCI communication was already closed"); auto death_unlink = nci_->unlinkToDeath(nfc_death_recipient_); if (!death_unlink.isOk()) { ALOGE("Error unlinking death recipient from the Bluetooth HAL"); } nci_->close(); nci_ = nullptr; nci_1_1_ = nullptr; nci_1_2_ = nullptr; trampoline_ = nullptr; } void send_command(rust::Slice data) { ALOG_ASSERT(nci_ == nullptr, "The NCI communication was already closed"); nci_->write(hidl_vec(data.data(), data.data() + data.length())); } } // namespace hal } // namespace nfc