1 #include "hal/ffi/hidl.h"
2
3 #include <log/log.h>
4 #include <stdlib.h>
5
6 using ::android::wp;
7 using ::android::hardware::hidl_death_recipient;
8 using ::android::hidl::base::V1_0::IBase;
9
10 using android::OK;
11 using android::sp;
12 using android::status_t;
13
14 using ::android::hardware::hidl_vec;
15 using ::android::hardware::Return;
16 using ::android::hardware::Void;
17 using android::hardware::nfc::V1_0::INfc;
18 using INfcV1_1 = android::hardware::nfc::V1_1::INfc;
19 using INfcV1_2 = android::hardware::nfc::V1_2::INfc;
20 using android::hardware::nfc::V1_1::INfcClientCallback;
21
22 namespace nfc {
23 namespace hal {
24 namespace {
25
26 class NfcHalDeathRecipient : public hidl_death_recipient {
27 public:
serviceDied(uint64_t,const android::wp<::android::hidl::base::V1_0::IBase> &)28 virtual void serviceDied(
29 uint64_t /*cookie*/,
30 const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
31 LOG_FATAL("Nfc HAL service died!");
32 abort();
33 }
34 };
35
36 class NfcCallbackTrampoline : public INfcClientCallback {
37 public:
NfcCallbackTrampoline()38 NfcCallbackTrampoline() {}
39
sendEvent_1_1(::android::hardware::nfc::V1_1::NfcEvent event,::android::hardware::nfc::V1_0::NfcStatus event_status)40 Return<void> sendEvent_1_1(
41 ::android::hardware::nfc::V1_1::NfcEvent event,
42 ::android::hardware::nfc::V1_0::NfcStatus event_status) override {
43 on_event(event, event_status);
44 return Void();
45 }
sendEvent(::android::hardware::nfc::V1_0::NfcEvent event,::android::hardware::nfc::V1_0::NfcStatus event_status)46 Return<void> sendEvent(
47 ::android::hardware::nfc::V1_0::NfcEvent event,
48 ::android::hardware::nfc::V1_0::NfcStatus event_status) override {
49 on_event((::android::hardware::nfc::V1_1::NfcEvent)event, event_status);
50 return Void();
51 }
52
sendData(const::android::hardware::nfc::V1_0::NfcData & data)53 Return<void> sendData(const ::android::hardware::nfc::V1_0::NfcData& data) {
54 on_data(rust::Slice(&data[0], data.size()));
55 return Void();
56 }
57 };
58
59 android::sp<NfcHalDeathRecipient> nfc_death_recipient_;
60 android::sp<INfc> nci_;
61 android::sp<INfcV1_1> nci_1_1_;
62 android::sp<INfcV1_2> nci_1_2_;
63 android::sp<NfcCallbackTrampoline> trampoline_;
64
65 } // namespace
66
start_hal()67 void start_hal() {
68 ALOG_ASSERT(nci_ != nullptr, "Stale value of the NCI port");
69
70 nci_ = nci_1_1_ = nci_1_2_ = INfcV1_2::getService();
71 if (nci_1_2_ == nullptr) {
72 nci_ = nci_1_1_ = INfcV1_1::getService();
73 if (nci_1_1_ == nullptr) {
74 nci_ = INfc::getService();
75 }
76 }
77 LOG_FATAL_IF(nci_ == nullptr, "Failed to retrieve the NFC HAL!");
78 ALOGI("%s: INfc::getService() returned %p (%s)", __func__, nci_.get(),
79 (nci_->isRemote() ? "remote" : "local"));
80 if (nci_) {
81 nfc_death_recipient_ = new NfcHalDeathRecipient();
82 auto death_link = nci_->linkToDeath(nfc_death_recipient_, 0);
83 ALOG_ASSERT(death_link.isOk(),
84 "Unable to set the death recipient for the Nfc HAL");
85 }
86
87 trampoline_ = new NfcCallbackTrampoline();
88 if (nci_1_1_ != nullptr) {
89 nci_1_1_->open_1_1(trampoline_);
90 } else {
91 nci_->open(trampoline_);
92 }
93 }
94
stop_hal()95 void stop_hal() {
96 ALOG_ASSERT(nci_ == nullptr, "The NCI communication was already closed");
97
98 auto death_unlink = nci_->unlinkToDeath(nfc_death_recipient_);
99 if (!death_unlink.isOk()) {
100 ALOGE("Error unlinking death recipient from the Bluetooth HAL");
101 }
102 nci_->close();
103 nci_ = nullptr;
104 nci_1_1_ = nullptr;
105 nci_1_2_ = nullptr;
106 trampoline_ = nullptr;
107 }
108
send_command(rust::Slice<const uint8_t> data)109 void send_command(rust::Slice<const uint8_t> data) {
110 ALOG_ASSERT(nci_ == nullptr, "The NCI communication was already closed");
111 nci_->write(hidl_vec<uint8_t>(data.data(), data.data() + data.length()));
112 }
113
114 } // namespace hal
115 } // namespace nfc
116