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