Loading bluetooth/aidl/default/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ cc_library_static { defaults: ["android.hardware.bluetooth-service-build-defaults"], srcs: [ "BluetoothHci.cpp", "net_bluetooth_mgmt.cpp", ], } Loading @@ -37,7 +38,7 @@ cc_binary { name: "android.hardware.bluetooth-service.default", relative_install_path: "hw", init_rc: ["bluetooth-service-default.rc"], vintf_fragments: ["bluetooth-service-default.xml"], vintf_fragments: [":manifest_android.hardware.bluetooth-service.default.xml"], vendor: true, defaults: ["android.hardware.bluetooth-service-build-defaults"], srcs: [ Loading Loading @@ -77,3 +78,8 @@ cc_fuzz { ], }, } filegroup { name: "manifest_android.hardware.bluetooth-service.default.xml", srcs: ["bluetooth-service-default.xml"], } bluetooth/aidl/default/BluetoothHci.cpp +41 −16 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ int SetTerminalRaw(int fd) { using namespace ::android::hardware::bluetooth::hci; using namespace ::android::hardware::bluetooth::async; using aidl::android::hardware::bluetooth::Status; namespace aidl::android::hardware::bluetooth::impl { Loading Loading @@ -97,38 +98,46 @@ BluetoothHci::BluetoothHci(const std::string& dev_path) { mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this); } ndk::ScopedAStatus BluetoothHci::initialize( const std::shared_ptr<IBluetoothHciCallbacks>& cb) { ALOGI(__func__); mFd = open(mDevPath.c_str(), O_RDWR); if (mFd < 0) { int BluetoothHci::getFdFromDevPath() { int fd = open(mDevPath.c_str(), O_RDWR); if (fd < 0) { ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(), strerror(errno)); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); return fd; } if (int ret = SetTerminalRaw(mFd) < 0) { ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret, strerror(errno)); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); ::close(fd); return -1; } return fd; } ndk::ScopedAStatus BluetoothHci::initialize( const std::shared_ptr<IBluetoothHciCallbacks>& cb) { ALOGI(__func__); mCb = cb; if (mCb == nullptr) { ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)"); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); } mDeathRecipient->LinkToDeath(mCb); management_.reset(new NetBluetoothMgmt); mFd = management_->openHci(); if (mFd < 0) { management_.reset(); auto init_ret = cb->initializationComplete(Status::SUCCESS); if (!init_ret.isOk()) { if (!mDeathRecipient->getHasDied()) { ALOGE("Error sending init callback, but no death notification."); ALOGI("Unable to open Linux interface, trying default path."); mFd = getFdFromDevPath(); if (mFd < 0) { return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); } return ndk::ScopedAStatus::fromServiceSpecificError( STATUS_FAILED_TRANSACTION); } mDeathRecipient->LinkToDeath(mCb); mH4 = std::make_shared<H4Protocol>( mFd, [](const std::vector<uint8_t>& /* raw_command */) { Loading @@ -152,13 +161,29 @@ ndk::ScopedAStatus BluetoothHci::initialize( }); mFdWatcher.WatchFdForNonBlockingReads(mFd, [this](int) { mH4->OnDataReady(); }); ALOGI("initialization complete"); auto status = mCb->initializationComplete(Status::SUCCESS); if (!status.isOk()) { if (!mDeathRecipient->getHasDied()) { ALOGE("Error sending init callback, but no death notification"); } close(); return ndk::ScopedAStatus::fromServiceSpecificError( STATUS_FAILED_TRANSACTION); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothHci::close() { ALOGI(__func__); mFdWatcher.StopWatchingFileDescriptors(); if (management_) { management_->closeHci(); } else { ::close(mFd); } return ndk::ScopedAStatus::ok(); } Loading bluetooth/aidl/default/BluetoothHci.h +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "async_fd_watcher.h" #include "h4_protocol.h" #include "net_bluetooth_mgmt.h" namespace aidl::android::hardware::bluetooth::impl { Loading Loading @@ -64,8 +65,10 @@ class BluetoothHci : public BnBluetoothHci { ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher; int getFdFromDevPath(); void send(::android::hardware::bluetooth::hci::PacketType type, const std::vector<uint8_t>& packet); std::unique_ptr<NetBluetoothMgmt> management_{}; }; } // namespace aidl::android::hardware::bluetooth::impl bluetooth/aidl/default/bluetooth-service-default.rc +1 −1 Original line number Diff line number Diff line service bluetooth_hal_service /vendor/bin/hw/android.hardware.bluetooth-service.default service vendor.bluetooth-default /vendor/bin/hw/android.hardware.bluetooth-service.default class hal capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE user bluetooth Loading bluetooth/aidl/default/net_bluetooth_mgmt.cpp 0 → 100644 +296 −0 Original line number Diff line number Diff line /* * Copyright 2022 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.service.default" #include "net_bluetooth_mgmt.h" #include <fcntl.h> #include <log/log.h> #include <poll.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include <cstdint> #include <cstdlib> #include <cstring> // Definitions imported from <linux/net/bluetooth/bluetooth.h> #define BTPROTO_HCI 1 // Definitions imported from <linux/net/bluetooth/hci_sock.h> #define HCI_CHANNEL_USER 1 #define HCI_CHANNEL_CONTROL 3 #define HCI_DEV_NONE 0xffff struct sockaddr_hci { sa_family_t hci_family; unsigned short hci_dev; unsigned short hci_channel; }; // Definitions imported from <linux/net/bluetooth/mgmt.h> #define MGMT_OP_READ_INDEX_LIST 0x0003 #define MGMT_EV_INDEX_ADDED 0x0004 #define MGMT_EV_CMD_COMPLETE 0x0001 #define MGMT_PKT_SIZE_MAX 1024 #define MGMT_INDEX_NONE 0xFFFF struct mgmt_pkt { uint16_t opcode; uint16_t index; uint16_t len; uint8_t data[MGMT_PKT_SIZE_MAX]; } __attribute__((packed)); struct mgmt_ev_read_index_list { uint16_t opcode; uint8_t status; uint16_t num_controllers; uint16_t index[]; } __attribute__((packed)); // Definitions imported from <linux/rfkill.h> #define RFKILL_STATE_SOFT_BLOCKED 0 #define RFKILL_STATE_UNBLOCKED 1 #define RFKILL_STATE_HARD_BLOCKED 2 #define RFKILL_TYPE_BLUETOOTH 2 #define RFKILL_OP_ADD 0 #define RFKILL_OP_CHANGE 2 struct rfkill_event { uint32_t idx; uint8_t type; uint8_t op; uint8_t soft; uint8_t hard; } __attribute__((packed)); namespace aidl::android::hardware::bluetooth::impl { // Wait indefinitely for the selected HCI interface to be enabled in the // bluetooth driver. int NetBluetoothMgmt::waitHciDev(int hci_interface) { ALOGI("waiting for hci interface %d", hci_interface); int ret = -1; struct mgmt_pkt cmd; struct pollfd pollfd; struct sockaddr_hci hci_addr = { .hci_family = AF_BLUETOOTH, .hci_dev = HCI_DEV_NONE, .hci_channel = HCI_CHANNEL_CONTROL, }; // Open and bind a socket to the bluetooth control interface in the // kernel driver, used to send control commands and receive control // events. int fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (fd < 0) { ALOGE("unable to open raw bluetooth socket: %s", strerror(errno)); return -1; } if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) { ALOGE("unable to bind bluetooth control channel: %s", strerror(errno)); goto end; } // Send the control command [Read Index List]. cmd = { .opcode = MGMT_OP_READ_INDEX_LIST, .index = MGMT_INDEX_NONE, .len = 0, }; if (write(fd, &cmd, 6) != 6) { ALOGE("error writing mgmt command: %s", strerror(errno)); goto end; } // Poll the control socket waiting for the command response, // and subsequent [Index Added] events. The loops continue without // timeout until the selected hci interface is detected. pollfd = {.fd = fd, .events = POLLIN}; for (;;) { ret = poll(&pollfd, 1, -1); // Poll interrupted, try again. if (ret == -1 && (errno == EINTR || errno == EAGAIN)) { continue; } // Poll failure, abandon. if (ret == -1) { ALOGE("poll error: %s", strerror(errno)); break; } // Spurious wakeup, try again. if (ret == 0 || (pollfd.revents & POLLIN) == 0) { continue; } // Read the next control event. struct mgmt_pkt ev {}; ret = read(fd, &ev, sizeof(ev)); if (ret < 0) { ALOGE("error reading mgmt event: %s", strerror(errno)); goto end; } // Received [Read Index List] command response. if (ev.opcode == MGMT_EV_CMD_COMPLETE) { struct mgmt_ev_read_index_list* data = (struct mgmt_ev_read_index_list*)ev.data; for (int i = 0; i < data->num_controllers; i++) { if (data->index[i] == hci_interface) { ALOGI("hci interface %d found", hci_interface); ret = 0; goto end; } } } // Received [Index Added] event. if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) { ALOGI("hci interface %d added", hci_interface); ret = 0; goto end; } } end: ::close(fd); return ret; } int NetBluetoothMgmt::openRfkill() { int fd = open("/dev/rfkill", O_RDWR); if (fd < 0) { ALOGE("unable to open /dev/rfkill: %s", strerror(errno)); return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { ALOGE("unable to set rfkill control device to non-blocking: %s", strerror(errno)); ::close(fd); return -1; } for (;;) { struct rfkill_event event {}; ssize_t res = read(fd, &event, sizeof(event)); if (res < 0) { ALOGE("error reading rfkill events: %s", strerror(errno)); break; } ALOGI("index:%d type:%d op:%d", event.idx, event.type, event.op); if (event.op == RFKILL_OP_ADD && event.type == RFKILL_TYPE_BLUETOOTH) { rfkill_bt_index_ = event.idx; rfkill_fd_ = fd; return 0; } } ::close(fd); return -1; } // Block or unblock Bluetooth. int NetBluetoothMgmt::rfkill(int block) { if (rfkill_fd_ == -1) { openRfkill(); } if (rfkill_fd_ == -1) { ALOGE("rfkill unavailable"); return -1; } struct rfkill_event event = { .idx = static_cast<uint32_t>(rfkill_bt_index_), .type = RFKILL_TYPE_BLUETOOTH, .op = RFKILL_OP_CHANGE, .soft = static_cast<uint8_t>(block), .hard = 0, }; int res = write(rfkill_fd_, &event, sizeof(event)); if (res < 0) { ALOGE("error writing rfkill command: %s", strerror(errno)); return -1; } return 0; } int NetBluetoothMgmt::openHci(int hci_interface) { ALOGI("opening hci interface %d", hci_interface); // Block Bluetooth. rfkill(1); // Wait for the HCI interface to complete initialization or to come online. if (waitHciDev(hci_interface)) { ALOGE("hci interface %d not found", hci_interface); return -1; } // Open the raw HCI socket. int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (fd < 0) { ALOGE("unable to open raw bluetooth socket: %s", strerror(errno)); return -1; } struct sockaddr_hci hci_addr = { .hci_family = AF_BLUETOOTH, .hci_dev = static_cast<uint16_t>(hci_interface), .hci_channel = HCI_CHANNEL_USER, }; // Bind the socket to the selected interface. if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) { ALOGE("unable to bind bluetooth user channel: %s", strerror(errno)); ::close(fd); return -1; } ALOGI("hci interface %d ready", hci_interface); bt_fd_ = fd; return fd; } void NetBluetoothMgmt::closeHci() { if (bt_fd_ != -1) { ::close(bt_fd_); bt_fd_ = -1; } // Unblock Bluetooth. rfkill(0); } } // namespace aidl::android::hardware::bluetooth::impl Loading
bluetooth/aidl/default/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ cc_library_static { defaults: ["android.hardware.bluetooth-service-build-defaults"], srcs: [ "BluetoothHci.cpp", "net_bluetooth_mgmt.cpp", ], } Loading @@ -37,7 +38,7 @@ cc_binary { name: "android.hardware.bluetooth-service.default", relative_install_path: "hw", init_rc: ["bluetooth-service-default.rc"], vintf_fragments: ["bluetooth-service-default.xml"], vintf_fragments: [":manifest_android.hardware.bluetooth-service.default.xml"], vendor: true, defaults: ["android.hardware.bluetooth-service-build-defaults"], srcs: [ Loading Loading @@ -77,3 +78,8 @@ cc_fuzz { ], }, } filegroup { name: "manifest_android.hardware.bluetooth-service.default.xml", srcs: ["bluetooth-service-default.xml"], }
bluetooth/aidl/default/BluetoothHci.cpp +41 −16 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ int SetTerminalRaw(int fd) { using namespace ::android::hardware::bluetooth::hci; using namespace ::android::hardware::bluetooth::async; using aidl::android::hardware::bluetooth::Status; namespace aidl::android::hardware::bluetooth::impl { Loading Loading @@ -97,38 +98,46 @@ BluetoothHci::BluetoothHci(const std::string& dev_path) { mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this); } ndk::ScopedAStatus BluetoothHci::initialize( const std::shared_ptr<IBluetoothHciCallbacks>& cb) { ALOGI(__func__); mFd = open(mDevPath.c_str(), O_RDWR); if (mFd < 0) { int BluetoothHci::getFdFromDevPath() { int fd = open(mDevPath.c_str(), O_RDWR); if (fd < 0) { ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(), strerror(errno)); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); return fd; } if (int ret = SetTerminalRaw(mFd) < 0) { ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret, strerror(errno)); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); ::close(fd); return -1; } return fd; } ndk::ScopedAStatus BluetoothHci::initialize( const std::shared_ptr<IBluetoothHciCallbacks>& cb) { ALOGI(__func__); mCb = cb; if (mCb == nullptr) { ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)"); return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); } mDeathRecipient->LinkToDeath(mCb); management_.reset(new NetBluetoothMgmt); mFd = management_->openHci(); if (mFd < 0) { management_.reset(); auto init_ret = cb->initializationComplete(Status::SUCCESS); if (!init_ret.isOk()) { if (!mDeathRecipient->getHasDied()) { ALOGE("Error sending init callback, but no death notification."); ALOGI("Unable to open Linux interface, trying default path."); mFd = getFdFromDevPath(); if (mFd < 0) { return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE); } return ndk::ScopedAStatus::fromServiceSpecificError( STATUS_FAILED_TRANSACTION); } mDeathRecipient->LinkToDeath(mCb); mH4 = std::make_shared<H4Protocol>( mFd, [](const std::vector<uint8_t>& /* raw_command */) { Loading @@ -152,13 +161,29 @@ ndk::ScopedAStatus BluetoothHci::initialize( }); mFdWatcher.WatchFdForNonBlockingReads(mFd, [this](int) { mH4->OnDataReady(); }); ALOGI("initialization complete"); auto status = mCb->initializationComplete(Status::SUCCESS); if (!status.isOk()) { if (!mDeathRecipient->getHasDied()) { ALOGE("Error sending init callback, but no death notification"); } close(); return ndk::ScopedAStatus::fromServiceSpecificError( STATUS_FAILED_TRANSACTION); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus BluetoothHci::close() { ALOGI(__func__); mFdWatcher.StopWatchingFileDescriptors(); if (management_) { management_->closeHci(); } else { ::close(mFd); } return ndk::ScopedAStatus::ok(); } Loading
bluetooth/aidl/default/BluetoothHci.h +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "async_fd_watcher.h" #include "h4_protocol.h" #include "net_bluetooth_mgmt.h" namespace aidl::android::hardware::bluetooth::impl { Loading Loading @@ -64,8 +65,10 @@ class BluetoothHci : public BnBluetoothHci { ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher; int getFdFromDevPath(); void send(::android::hardware::bluetooth::hci::PacketType type, const std::vector<uint8_t>& packet); std::unique_ptr<NetBluetoothMgmt> management_{}; }; } // namespace aidl::android::hardware::bluetooth::impl
bluetooth/aidl/default/bluetooth-service-default.rc +1 −1 Original line number Diff line number Diff line service bluetooth_hal_service /vendor/bin/hw/android.hardware.bluetooth-service.default service vendor.bluetooth-default /vendor/bin/hw/android.hardware.bluetooth-service.default class hal capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE user bluetooth Loading
bluetooth/aidl/default/net_bluetooth_mgmt.cpp 0 → 100644 +296 −0 Original line number Diff line number Diff line /* * Copyright 2022 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.service.default" #include "net_bluetooth_mgmt.h" #include <fcntl.h> #include <log/log.h> #include <poll.h> #include <sys/socket.h> #include <unistd.h> #include <cerrno> #include <cstdint> #include <cstdlib> #include <cstring> // Definitions imported from <linux/net/bluetooth/bluetooth.h> #define BTPROTO_HCI 1 // Definitions imported from <linux/net/bluetooth/hci_sock.h> #define HCI_CHANNEL_USER 1 #define HCI_CHANNEL_CONTROL 3 #define HCI_DEV_NONE 0xffff struct sockaddr_hci { sa_family_t hci_family; unsigned short hci_dev; unsigned short hci_channel; }; // Definitions imported from <linux/net/bluetooth/mgmt.h> #define MGMT_OP_READ_INDEX_LIST 0x0003 #define MGMT_EV_INDEX_ADDED 0x0004 #define MGMT_EV_CMD_COMPLETE 0x0001 #define MGMT_PKT_SIZE_MAX 1024 #define MGMT_INDEX_NONE 0xFFFF struct mgmt_pkt { uint16_t opcode; uint16_t index; uint16_t len; uint8_t data[MGMT_PKT_SIZE_MAX]; } __attribute__((packed)); struct mgmt_ev_read_index_list { uint16_t opcode; uint8_t status; uint16_t num_controllers; uint16_t index[]; } __attribute__((packed)); // Definitions imported from <linux/rfkill.h> #define RFKILL_STATE_SOFT_BLOCKED 0 #define RFKILL_STATE_UNBLOCKED 1 #define RFKILL_STATE_HARD_BLOCKED 2 #define RFKILL_TYPE_BLUETOOTH 2 #define RFKILL_OP_ADD 0 #define RFKILL_OP_CHANGE 2 struct rfkill_event { uint32_t idx; uint8_t type; uint8_t op; uint8_t soft; uint8_t hard; } __attribute__((packed)); namespace aidl::android::hardware::bluetooth::impl { // Wait indefinitely for the selected HCI interface to be enabled in the // bluetooth driver. int NetBluetoothMgmt::waitHciDev(int hci_interface) { ALOGI("waiting for hci interface %d", hci_interface); int ret = -1; struct mgmt_pkt cmd; struct pollfd pollfd; struct sockaddr_hci hci_addr = { .hci_family = AF_BLUETOOTH, .hci_dev = HCI_DEV_NONE, .hci_channel = HCI_CHANNEL_CONTROL, }; // Open and bind a socket to the bluetooth control interface in the // kernel driver, used to send control commands and receive control // events. int fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (fd < 0) { ALOGE("unable to open raw bluetooth socket: %s", strerror(errno)); return -1; } if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) { ALOGE("unable to bind bluetooth control channel: %s", strerror(errno)); goto end; } // Send the control command [Read Index List]. cmd = { .opcode = MGMT_OP_READ_INDEX_LIST, .index = MGMT_INDEX_NONE, .len = 0, }; if (write(fd, &cmd, 6) != 6) { ALOGE("error writing mgmt command: %s", strerror(errno)); goto end; } // Poll the control socket waiting for the command response, // and subsequent [Index Added] events. The loops continue without // timeout until the selected hci interface is detected. pollfd = {.fd = fd, .events = POLLIN}; for (;;) { ret = poll(&pollfd, 1, -1); // Poll interrupted, try again. if (ret == -1 && (errno == EINTR || errno == EAGAIN)) { continue; } // Poll failure, abandon. if (ret == -1) { ALOGE("poll error: %s", strerror(errno)); break; } // Spurious wakeup, try again. if (ret == 0 || (pollfd.revents & POLLIN) == 0) { continue; } // Read the next control event. struct mgmt_pkt ev {}; ret = read(fd, &ev, sizeof(ev)); if (ret < 0) { ALOGE("error reading mgmt event: %s", strerror(errno)); goto end; } // Received [Read Index List] command response. if (ev.opcode == MGMT_EV_CMD_COMPLETE) { struct mgmt_ev_read_index_list* data = (struct mgmt_ev_read_index_list*)ev.data; for (int i = 0; i < data->num_controllers; i++) { if (data->index[i] == hci_interface) { ALOGI("hci interface %d found", hci_interface); ret = 0; goto end; } } } // Received [Index Added] event. if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) { ALOGI("hci interface %d added", hci_interface); ret = 0; goto end; } } end: ::close(fd); return ret; } int NetBluetoothMgmt::openRfkill() { int fd = open("/dev/rfkill", O_RDWR); if (fd < 0) { ALOGE("unable to open /dev/rfkill: %s", strerror(errno)); return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { ALOGE("unable to set rfkill control device to non-blocking: %s", strerror(errno)); ::close(fd); return -1; } for (;;) { struct rfkill_event event {}; ssize_t res = read(fd, &event, sizeof(event)); if (res < 0) { ALOGE("error reading rfkill events: %s", strerror(errno)); break; } ALOGI("index:%d type:%d op:%d", event.idx, event.type, event.op); if (event.op == RFKILL_OP_ADD && event.type == RFKILL_TYPE_BLUETOOTH) { rfkill_bt_index_ = event.idx; rfkill_fd_ = fd; return 0; } } ::close(fd); return -1; } // Block or unblock Bluetooth. int NetBluetoothMgmt::rfkill(int block) { if (rfkill_fd_ == -1) { openRfkill(); } if (rfkill_fd_ == -1) { ALOGE("rfkill unavailable"); return -1; } struct rfkill_event event = { .idx = static_cast<uint32_t>(rfkill_bt_index_), .type = RFKILL_TYPE_BLUETOOTH, .op = RFKILL_OP_CHANGE, .soft = static_cast<uint8_t>(block), .hard = 0, }; int res = write(rfkill_fd_, &event, sizeof(event)); if (res < 0) { ALOGE("error writing rfkill command: %s", strerror(errno)); return -1; } return 0; } int NetBluetoothMgmt::openHci(int hci_interface) { ALOGI("opening hci interface %d", hci_interface); // Block Bluetooth. rfkill(1); // Wait for the HCI interface to complete initialization or to come online. if (waitHciDev(hci_interface)) { ALOGE("hci interface %d not found", hci_interface); return -1; } // Open the raw HCI socket. int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (fd < 0) { ALOGE("unable to open raw bluetooth socket: %s", strerror(errno)); return -1; } struct sockaddr_hci hci_addr = { .hci_family = AF_BLUETOOTH, .hci_dev = static_cast<uint16_t>(hci_interface), .hci_channel = HCI_CHANNEL_USER, }; // Bind the socket to the selected interface. if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) { ALOGE("unable to bind bluetooth user channel: %s", strerror(errno)); ::close(fd); return -1; } ALOGI("hci interface %d ready", hci_interface); bt_fd_ = fd; return fd; } void NetBluetoothMgmt::closeHci() { if (bt_fd_ != -1) { ::close(bt_fd_); bt_fd_ = -1; } // Unblock Bluetooth. rfkill(0); } } // namespace aidl::android::hardware::bluetooth::impl