bluetooth: adjust rfkill

* Switch to android.hardware.bluetooth@1.1-service.btlinux rfkill
  implementation that uses /sys/class/rfkill/rfkill*/state.
This commit is contained in:
Konsta
2024-11-16 22:23:55 +02:00
parent 412e289949
commit 89eb1f3253
2 changed files with 46 additions and 80 deletions

View File

@@ -50,6 +50,9 @@ struct sockaddr_hci {
#define MGMT_EV_CMD_COMPLETE 0x0001 #define MGMT_EV_CMD_COMPLETE 0x0001
#define MGMT_PKT_SIZE_MAX 1024 #define MGMT_PKT_SIZE_MAX 1024
#define MGMT_INDEX_NONE 0xFFFF #define MGMT_INDEX_NONE 0xFFFF
#define WRITE_NO_INTR(fn) \
do { \
} while ((fn) == -1 && errno == EINTR)
struct mgmt_pkt { struct mgmt_pkt {
uint16_t opcode; uint16_t opcode;
@@ -65,24 +68,6 @@ struct mgmt_ev_read_index_list {
uint16_t index[]; uint16_t index[];
} __attribute__((packed)); } __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 { namespace aidl::android::hardware::bluetooth::impl {
// Wait indefinitely for the selected HCI interface to be enabled in the // Wait indefinitely for the selected HCI interface to be enabled in the
@@ -194,66 +179,49 @@ end:
return ret; return ret;
} }
int NetBluetoothMgmt::openRfkill() { int NetBluetoothMgmt::findRfKill() {
int fd = open("/dev/rfkill", O_RDWR); char rfkill_type[64];
char type[16];
int fd, size, i;
for(i = 0; rfkill_state_ == NULL; i++)
{
snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
if ((fd = open(rfkill_type, O_RDONLY)) < 0)
{
ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
return -1;
}
size = read(fd, &type, sizeof(type));
::close(fd);
if ((size >= 9) && !memcmp(type, "bluetooth", 9))
{
::asprintf(&rfkill_state_, "/sys/class/rfkill/rfkill%d/state", i);
break;
}
}
return 0;
}
int NetBluetoothMgmt::rfKill(int block) {
int fd;
char on = (block)?'1':'0';
if (findRfKill() != 0) return 0;
fd = open(rfkill_state_, O_WRONLY);
if (fd < 0) { if (fd < 0) {
ALOGE("unable to open /dev/rfkill: %s", strerror(errno)); ALOGE( "Unable to open /dev/rfkill");
return -1; return -1;
} }
ssize_t len;
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { WRITE_NO_INTR(len = write(fd, &on, 1));
ALOGE("unable to set rfkill control device to non-blocking: %s", if (len < 0) {
strerror(errno)); ALOGE( "Failed to change rfkill state");
::close(fd); ::close(fd);
return -1; 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); ::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; return 0;
} }
@@ -261,7 +229,8 @@ int NetBluetoothMgmt::openHci(int hci_interface) {
ALOGI("opening hci interface %d", hci_interface); ALOGI("opening hci interface %d", hci_interface);
// Block Bluetooth. // Block Bluetooth.
rfkill(1); rfkill_state_ = NULL;
rfKill(1);
// Wait for the HCI interface to complete initialization or to come online. // Wait for the HCI interface to complete initialization or to come online.
int hci = waitHciDev(hci_interface); int hci = waitHciDev(hci_interface);
@@ -302,7 +271,8 @@ void NetBluetoothMgmt::closeHci() {
} }
// Unblock Bluetooth. // Unblock Bluetooth.
rfkill(0); rfKill(0);
free(rfkill_state_);
} }
} // namespace aidl::android::hardware::bluetooth::impl } // namespace aidl::android::hardware::bluetooth::impl

View File

@@ -25,7 +25,6 @@ class NetBluetoothMgmt {
public: public:
NetBluetoothMgmt() {} NetBluetoothMgmt() {}
~NetBluetoothMgmt() { ~NetBluetoothMgmt() {
::close(rfkill_fd_);
::close(bt_fd_); ::close(bt_fd_);
} }
@@ -34,13 +33,10 @@ class NetBluetoothMgmt {
private: private:
int waitHciDev(int hci_interface); int waitHciDev(int hci_interface);
int openRfkill(); int findRfKill();
int rfkill(int block); int rfKill(int block);
char *rfkill_state_;
// Index of the first rfkill device of type bluetooth.
int rfkill_bt_index_{-1};
// File descriptor opened to /dev/rfkill.
int rfkill_fd_{-1};
// File descriptor opened to the bluetooth user channel. // File descriptor opened to the bluetooth user channel.
int bt_fd_{-1}; int bt_fd_{-1};
}; };