summaryrefslogtreecommitdiff
path: root/src/rfkill.c
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2022-09-01 13:07:14 +0200
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2022-09-01 11:43:35 -0700
commitabf5ba6b80add53a4617ffdd06ac2102095347c2 (patch)
tree2a673e17e51a980b451c24d95d3d7f36ee85f0d5 /src/rfkill.c
parent49b8c5901584eab77af40f8ad19779747b4506d6 (diff)
downloadbluez-abf5ba6b80add53a4617ffdd06ac2102095347c2.tar.gz
adapter: Keep track of whether the adapter is rfkill'ed
Instead of only replying to D-Bus requests with an error saying the adapter is blocked, keep track of the rfkill being enabled or disabled so we know the rfkill state of the adapter at all times.
Diffstat (limited to 'src/rfkill.c')
-rw-r--r--src/rfkill.c89
1 files changed, 66 insertions, 23 deletions
diff --git a/src/rfkill.c b/src/rfkill.c
index 2099c5ac5..a0a50d9e4 100644
--- a/src/rfkill.c
+++ b/src/rfkill.c
@@ -55,12 +55,71 @@ struct rfkill_event {
};
#define RFKILL_EVENT_SIZE_V1 8
+static int get_adapter_id_for_rfkill(int rfkill_id)
+{
+ char sysname[PATH_MAX];
+ int namefd;
+
+ snprintf(sysname, sizeof(sysname) - 1,
+ "/sys/class/rfkill/rfkill%u/name", rfkill_id);
+
+ namefd = open(sysname, O_RDONLY);
+ if (namefd < 0)
+ return -1;
+
+ memset(sysname, 0, sizeof(sysname));
+
+ if (read(namefd, sysname, sizeof(sysname) - 1) < 4) {
+ close(namefd);
+ return -1;
+ }
+
+ close(namefd);
+
+ if (g_str_has_prefix(sysname, "hci") == FALSE)
+ return -1;
+
+ return atoi(sysname + 3);
+}
+
+int rfkill_get_blocked(uint16_t index)
+{
+ int fd;
+ int blocked = -1;
+
+ fd = open("/dev/rfkill", O_RDWR);
+ if (fd < 0) {
+ DBG("Failed to open RFKILL control device");
+ return -1;
+ }
+
+ while (1) {
+ struct rfkill_event event = { 0 };
+ int id;
+ ssize_t len;
+
+ len = read(fd, &event, sizeof(event));
+ if (len < RFKILL_EVENT_SIZE_V1)
+ break;
+
+ id = get_adapter_id_for_rfkill(event.idx);
+
+ if (index == id) {
+ blocked = event.soft || event.hard;
+ break;
+ }
+ }
+ close(fd);
+
+ return blocked;
+}
+
static gboolean rfkill_event(GIOChannel *chan,
GIOCondition cond, gpointer data)
{
struct rfkill_event event = { 0 };
struct btd_adapter *adapter;
- char sysname[PATH_MAX];
+ bool blocked = false;
ssize_t len;
int fd, id;
@@ -84,7 +143,7 @@ static gboolean rfkill_event(GIOChannel *chan,
event.soft, event.hard);
if (event.soft || event.hard)
- return TRUE;
+ blocked = true;
if (event.op != RFKILL_OP_CHANGE)
return TRUE;
@@ -93,26 +152,7 @@ static gboolean rfkill_event(GIOChannel *chan,
event.type != RFKILL_TYPE_ALL)
return TRUE;
- snprintf(sysname, sizeof(sysname) - 1,
- "/sys/class/rfkill/rfkill%u/name", event.idx);
-
- fd = open(sysname, O_RDONLY);
- if (fd < 0)
- return TRUE;
-
- memset(sysname, 0, sizeof(sysname));
-
- if (read(fd, sysname, sizeof(sysname) - 1) < 4) {
- close(fd);
- return TRUE;
- }
-
- close(fd);
-
- if (g_str_has_prefix(sysname, "hci") == FALSE)
- return TRUE;
-
- id = atoi(sysname + 3);
+ id = get_adapter_id_for_rfkill(event.idx);
if (id < 0)
return TRUE;
@@ -122,7 +162,10 @@ static gboolean rfkill_event(GIOChannel *chan,
DBG("RFKILL unblock for hci%d", id);
- btd_adapter_restore_powered(adapter);
+ if (blocked)
+ btd_adapter_set_blocked(adapter);
+ else
+ btd_adapter_restore_powered(adapter);
return TRUE;
}