// // Copyright 2021 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define LOG_TAG "android.hardware.bluetooth@1.1.remote" #include "remote_bluetooth.h" #include #include #include #include #include #include #include #include #include #include "log/log.h" namespace { int SetTerminalRaw(int fd) { termios terminal_settings; int rval = tcgetattr(fd, &terminal_settings); if (rval < 0) { return rval; } cfmakeraw(&terminal_settings); rval = tcsetattr(fd, TCSANOW, &terminal_settings); return rval; } } // namespace namespace android { namespace hardware { namespace bluetooth { namespace V1_1 { namespace remote { using ::android::hardware::hidl_vec; class BluetoothDeathRecipient : public hidl_death_recipient { public: BluetoothDeathRecipient(const sp hci) : mHci(hci) {} void serviceDied( uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* who */) override { LOG(ERROR) << "BluetoothDeathRecipient::serviceDied - Bluetooth service died"; has_died_ = true; mHci->close(); } sp mHci; bool getHasDied() const { return has_died_; } void setHasDied(bool has_died) { has_died_ = has_died; } private: bool has_died_; }; BluetoothHci::BluetoothHci(const std::string& dev_path) : death_recipient_(new BluetoothDeathRecipient(this)), dev_path_(dev_path) {} Return BluetoothHci::initialize( const sp& cb) { return initialize_impl(cb, nullptr); } Return BluetoothHci::initialize_1_1( const sp& cb) { return initialize_impl(cb, cb); } Return BluetoothHci::initialize_impl( const sp& cb, const sp& cb_1_1) { LOG(INFO) << __func__; cb_ = cb; cb_1_1_ = cb_1_1; fd_ = open(dev_path_.c_str(), O_RDWR); if (fd_ < 0) { LOG(FATAL) << "Could not connect to bt: " << fd_; } if (int ret = SetTerminalRaw(fd_) < 0) { LOG(FATAL) << "Could not make " << fd_ << " a raw terminal: " << ret; } if (cb == nullptr) { LOG(ERROR) << "cb == nullptr! -> Unable to call initializationComplete(ERR)"; return Void(); } death_recipient_->setHasDied(false); auto link_ret = cb->linkToDeath(death_recipient_, 0); unlink_cb_ = [this, cb](sp& death_recipient) { if (death_recipient->getHasDied()) LOG(INFO) << "Skipping unlink call, service died."; else { auto ret = cb->unlinkToDeath(death_recipient); if (!ret.isOk()) { CHECK(death_recipient_->getHasDied()) << "Error calling unlink, but no death notification."; } } }; auto init_ret = cb->initializationComplete(V1_0::Status::SUCCESS); if (!init_ret.isOk()) { CHECK(death_recipient_->getHasDied()) << "Error sending init callback, but no death notification."; } h4_ = rootcanal::H4Packetizer( fd_, [](const std::vector& /* raw_command */) { LOG_ALWAYS_FATAL("Unexpected command!"); }, [this](const std::vector& raw_event) { cb_->hciEventReceived(hidl_vec(raw_event)); }, [this](const std::vector& raw_acl) { cb_->hciEventReceived(hidl_vec(raw_acl)); }, [this](const std::vector& raw_sco) { cb_->hciEventReceived(hidl_vec(raw_sco)); }, [this](const std::vector& raw_iso) { if (cb_1_1_) { cb_1_1_->hciEventReceived(hidl_vec(raw_iso)); } }, []() { LOG(INFO) << "HCI socket device disconnected"; }); fd_watcher_.WatchFdForNonBlockingReads( fd_, [this](int fd) { h4_.OnDataReady(fd); }); return Void(); } Return BluetoothHci::close() { LOG(INFO) << __func__; fd_watcher_.StopWatchingFileDescriptors(); ::close(fd_); return Void(); } Return BluetoothHci::sendHciCommand(const hidl_vec& packet) { send(rootcanal::PacketType::COMMAND, packet); return Void(); } Return BluetoothHci::sendAclData(const hidl_vec& packet) { send(rootcanal::PacketType::ACL, packet); return Void(); } Return BluetoothHci::sendScoData(const hidl_vec& packet) { send(rootcanal::PacketType::SCO, packet); return Void(); } Return BluetoothHci::sendIsoData(const hidl_vec& packet) { send(rootcanal::PacketType::ISO, packet); return Void(); } void BluetoothHci::send(rootcanal::PacketType type, const ::android::hardware::hidl_vec& v) { h4_.Send(static_cast(type), v.data(), v.size()); } /* Fallback to shared library if there is no service. */ IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) { return new BluetoothHci(); } } // namespace remote } // namespace V1_1 } // namespace bluetooth } // namespace hardware } // namespace android