adapter: Keep track of whether the adapter is rfkill'ed
authorBastien Nocera <hadess@hadess.net>
Thu, 1 Sep 2022 11:07:14 +0000 (13:07 +0200)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 15 May 2023 09:25:54 +0000 (14:55 +0530)
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.

Signed-off-by: Manika Shrivastava <manika.sh@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/adapter.c
src/adapter.h
src/btd.h
src/rfkill.c

index daac434..e9e8661 100644 (file)
@@ -304,6 +304,7 @@ struct btd_adapter {
        uint32_t dev_class;             /* controller class of device */
        char *name;                     /* controller device name */
        char *short_name;               /* controller short name */
+       bool blocked;                   /* whether rfkill is enabled */
        uint32_t supported_settings;    /* controller supported settings */
        uint32_t pending_settings;      /* pending controller settings */
        uint32_t current_settings;      /* current controller settings */
@@ -1089,6 +1090,8 @@ static void set_mode_complete(uint8_t status, uint16_t length,
        if (status != MGMT_STATUS_SUCCESS) {
                btd_error(adapter->dev_id, "Failed to set mode: %s (0x%02x)",
                                                mgmt_errstr(status), status);
+               if (status == MGMT_STATUS_RFKILLED)
+                       adapter->blocked = true;
                adapter->pending_settings &= ~data->setting;
                return;
        }
@@ -7123,10 +7126,12 @@ static void property_set_mode_complete(uint8_t status, uint16_t length,
                btd_error(adapter->dev_id, "Failed to set mode: %s (0x%02x)",
                                                mgmt_errstr(status), status);
 
-               if (status == MGMT_STATUS_RFKILLED)
+               if (status == MGMT_STATUS_RFKILLED) {
                        dbus_err = ERROR_INTERFACE ".Blocked";
-               else
+                       adapter->blocked = true;
+               } else {
                        dbus_err = ERROR_INTERFACE ".Failed";
+               }
 
                g_dbus_pending_property_error(data->id, dbus_err,
                                                        mgmt_errstr(status));
@@ -11750,6 +11755,8 @@ static void load_config(struct btd_adapter *adapter)
 static struct btd_adapter *btd_adapter_new(uint16_t index)
 {
        struct btd_adapter *adapter;
+       int blocked;
+
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 #ifdef TIZEN_FEATURE_BLUEZ_BATTERY_WATCH
        DBusConnection *conn = btd_get_dbus_connection();
@@ -11766,6 +11773,9 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
        adapter->dev_id = index;
        adapter->mgmt = mgmt_ref(mgmt_primary);
        adapter->pincode_requested = false;
+       blocked = rfkill_get_blocked(index);
+       if (blocked > 0)
+               adapter->blocked = true;
 
        /*
         * Setup default configuration values. These are either adapter
@@ -11794,6 +11804,9 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
        DBG("Modalias: %s", adapter->modalias);
        DBG("Discoverable timeout: %u seconds", adapter->discoverable_timeout);
        DBG("Pairable timeout: %u seconds", adapter->pairable_timeout);
+       if (blocked > 0)
+               DBG("Blocked: yes");
+
        adapter->auths = g_queue_new();
        adapter->exps = queue_new();
 
@@ -12980,6 +12993,9 @@ int btd_cancel_authorization(guint id)
 
 int btd_adapter_restore_powered(struct btd_adapter *adapter)
 {
+       if (adapter->blocked)
+               adapter->blocked = false;
+
        if (btd_adapter_get_powered(adapter))
                return 0;
 
@@ -12988,6 +13004,13 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter)
        return 0;
 }
 
+int btd_adapter_set_blocked(struct btd_adapter *adapter)
+{
+       if (!adapter->blocked)
+               adapter->blocked = true;
+       return 0;
+}
+
 void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
                                                        btd_adapter_pin_cb_t cb)
 {
index 635632d..70375c1 100644 (file)
@@ -233,6 +233,7 @@ guint btd_request_authorization_cable_configured(const bdaddr_t *src, const bdad
 int btd_cancel_authorization(guint id);
 
 int btd_adapter_restore_powered(struct btd_adapter *adapter);
+int btd_adapter_set_blocked(struct btd_adapter *adapter);
 
 typedef ssize_t (*btd_adapter_pin_cb_t) (struct btd_adapter *adapter,
                        struct btd_device *dev, char *out, bool *display,
index 14b8e1a..782cbdc 100755 (executable)
--- a/src/btd.h
+++ b/src/btd.h
@@ -149,6 +149,7 @@ void plugin_cleanup(void);
 
 void rfkill_init(void);
 void rfkill_exit(void);
+int rfkill_get_blocked(uint16_t index);
 
 GKeyFile *btd_get_main_conf(void);
 bool btd_kernel_experimental_enabled(const char *uuid);
index 8a66a00..044b1da 100755 (executable)
@@ -54,12 +54,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;
 
@@ -83,7 +142,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;
@@ -92,26 +151,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;
 
@@ -121,7 +161,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;
 }