Check RFKILL block state before enable the device
authorMartin Xu <martin.xu@intel.com>
Mon, 18 Jan 2010 07:27:17 +0000 (15:27 +0800)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 18 Jan 2010 08:48:29 +0000 (00:48 -0800)
When starting, the device RFKILL block state will be recorded using
update_rfkill_state(). And at following device detection stage,
before enable the device, __connman_udev_get_blocked() should be
used to check the block state. If the device is blocked, it should
not be enabled. This avoids unnecessary enable and disable operation
and a race condition.

src/connman.h
src/device.c
src/udev-compat.c
src/udev.c

index a6619df..a704027 100644 (file)
@@ -265,6 +265,7 @@ char *__connman_udev_get_devtype(const char *ifname);
 char *__connman_udev_get_mbm_devnode(const char *ifname);
 void __connman_udev_rfkill(const char *sysname, connman_bool_t blocked);
 void __connman_udev_enable_rfkill_processing(void);
+connman_bool_t __connman_udev_get_blocked(int phyindex);
 
 #include <connman/device.h>
 
index 0d41863..875b197 100644 (file)
@@ -545,6 +545,9 @@ static int setup_device(struct connman_device *device)
                break;
        }
 
+       if (__connman_udev_get_blocked(device->phyindex) == TRUE)
+               return 0;
+
        if (device->offlinemode == FALSE &&
                                device->powered_persistent == TRUE)
                __connman_device_enable(device);
index 70cc3bb..1156705 100644 (file)
@@ -127,6 +127,11 @@ void __connman_udev_rfkill(const char *sysname, connman_bool_t blocked)
        DBG("sysname %s blocked %d", sysname, blocked);
 }
 
+connman_bool_t __connman_udev_get_blocked(int phyindex)
+{
+       return FALSE;
+}
+
 int __connman_udev_init(void)
 {
        DBG("");
index 59f36ea..676fe6f 100644 (file)
@@ -155,6 +155,56 @@ static void remove_net_device(struct udev_device *udev_device)
        connman_device_unref(device);
 }
 
+static GSList *rfkill_list = NULL;
+
+struct rfkill_data {
+       int phyindex;
+       connman_bool_t blocked;
+};
+
+connman_bool_t __connman_udev_get_blocked(int phyindex)
+{
+       GSList *list;
+
+       if (phyindex < 0)
+               return FALSE;
+
+       for (list = rfkill_list; list; list = rfkill_list->next) {
+               struct rfkill_data *block = list->data;
+
+               if (block->phyindex == phyindex)
+                       return block->blocked;
+       }
+
+       return FALSE;
+}
+
+static void update_rfkill_state(int phyindex, connman_bool_t blocked)
+{
+       GSList *list;
+       struct rfkill_data *block;
+
+       DBG("index %d blocked %d", phyindex, blocked);
+
+       for (list = rfkill_list; list; list = rfkill_list->next) {
+               block = list->data;
+
+               if (block->phyindex == phyindex) {
+                       block->blocked = blocked;
+                       return;
+               }
+       }
+
+       block = g_try_new0(struct rfkill_data, 1);
+       if (block == NULL)
+               return;
+
+       block->phyindex = phyindex;
+       block->blocked = blocked;
+
+       rfkill_list = g_slist_prepend(rfkill_list, block);
+}
+
 static void phyindex_rfkill(int phyindex, connman_bool_t blocked)
 {
        GSList *list;
@@ -162,6 +212,8 @@ static void phyindex_rfkill(int phyindex, connman_bool_t blocked)
        if (phyindex < 0)
                return;
 
+       update_rfkill_state(phyindex, blocked);
+
        for (list = device_list; list; list = list->next) {
                struct connman_device *device = list->data;
 
@@ -543,6 +595,14 @@ void __connman_udev_cleanup(void)
        g_slist_free(device_list);
        device_list = NULL;
 
+       for (list = rfkill_list; list; list = list->next) {
+               struct rfkill_data *block = list->data;
+               g_free(block);
+       }
+
+       g_slist_free(rfkill_list);
+       rfkill_list = NULL;
+
        if (udev_ctx == NULL)
                return;