blob: fb3b5b38c9932de33968af96d2ef1870935bab82 [file] [log] [blame]
#include "hal/ffi/hidl.h"
#include <log/log.h>
#include <stdlib.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::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<void> 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<void> 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<void> sendData(const ::android::hardware::nfc::V1_0::NfcData& data) {
on_data(rust::Slice(&data[0], data.size()));
return Void();
}
};
android::sp<NfcHalDeathRecipient> nfc_death_recipient_;
android::sp<INfc> nci_;
android::sp<INfcV1_1> nci_1_1_;
android::sp<INfcV1_2> nci_1_2_;
android::sp<NfcCallbackTrampoline> 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<const uint8_t> data) {
ALOG_ASSERT(nci_ == nullptr, "The NCI communication was already closed");
nci_->write(hidl_vec<uint8_t>(data.data(), data.data() + data.length()));
}
} // namespace hal
} // namespace nfc