#include #include #include #include #include "../../os/log.h" #include "src/ffi/hidl.h" using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::bluetooth::V1_1::IBluetoothHci; using ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks; using HidlStatus = ::android::hardware::bluetooth::V1_0::Status; using IBluetoothHci_1_0 = ::android::hardware::bluetooth::V1_0::IBluetoothHci; namespace bluetooth { namespace hal { namespace { class HciDeathRecipient : public ::android::hardware::hidl_death_recipient { public: virtual void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) { LOG_ERROR("Bluetooth HAL service died!"); abort(); } }; class HciCallbackTrampoline : public IBluetoothHciCallbacks { public: HciCallbackTrampoline() {} Return initializationComplete(HidlStatus status) { ASSERT(status == HidlStatus::SUCCESS); on_init_complete(); return Void(); } Return hciEventReceived(const hidl_vec& event) { on_event(rust::Slice(&event[0], event.size())); return Void(); } Return aclDataReceived(const hidl_vec& data) { on_acl(rust::Slice(&data[0], data.size())); return Void(); } Return scoDataReceived(const hidl_vec& data) { on_sco(rust::Slice(&data[0], data.size())); return Void(); } Return isoDataReceived(const hidl_vec& data) { on_iso(rust::Slice(&data[0], data.size())); return Void(); } }; android::sp hci_death_recipient_ = new HciDeathRecipient(); android::sp bt_hci_; android::sp bt_hci_1_1_; android::sp trampoline_; } // namespace void start_hal() { ASSERT(bt_hci_ == nullptr); bt_hci_1_1_ = IBluetoothHci::getService(); if (bt_hci_1_1_ != nullptr) { bt_hci_ = bt_hci_1_1_; } else { bt_hci_ = IBluetoothHci_1_0::getService(); } ASSERT(bt_hci_ != nullptr); auto death_link = bt_hci_->linkToDeath(hci_death_recipient_, 0); ASSERT_LOG(death_link.isOk(), "Unable to set the death recipient for the Bluetooth HAL"); trampoline_ = new HciCallbackTrampoline(); if (bt_hci_1_1_ != nullptr) { bt_hci_1_1_->initialize_1_1(trampoline_); } else { bt_hci_->initialize(trampoline_); } } void stop_hal() { ASSERT(bt_hci_ != nullptr); auto death_unlink = bt_hci_->unlinkToDeath(hci_death_recipient_); if (!death_unlink.isOk()) { LOG_ERROR("Error unlinking death recipient from the Bluetooth HAL"); } bt_hci_->close(); bt_hci_ = nullptr; bt_hci_1_1_ = nullptr; trampoline_ = nullptr; } void send_command(rust::Slice data) { ASSERT(bt_hci_ != nullptr); bt_hci_->sendHciCommand(hidl_vec(data.data(), data.data() + data.length())); } void send_acl(rust::Slice data) { ASSERT(bt_hci_ != nullptr); bt_hci_->sendAclData(hidl_vec(data.data(), data.data() + data.length())); } void send_sco(rust::Slice data) { ASSERT(bt_hci_ != nullptr); bt_hci_->sendScoData(hidl_vec(data.data(), data.data() + data.length())); } void send_iso(rust::Slice data) { if (bt_hci_1_1_ == nullptr) { LOG_ERROR("ISO is not supported in HAL v1.0"); return; } ASSERT(bt_hci_ != nullptr); bt_hci_1_1_->sendIsoData(hidl_vec(data.data(), data.data() + data.length())); } } // namespace hal } // namespace bluetooth