summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Xu <martin.xu@intel.com>2010-01-18 15:27:17 +0800
committerMarcel Holtmann <marcel@holtmann.org>2010-01-18 00:48:29 -0800
commit0935c628cf83b096d72ffba5e53a6d6e8029e7ef (patch)
tree32e3402035f4ed83e7682615a27696c6fdab74d6
parent5fbfa700fb4b3ccdafd16343d02462f7ba408cee (diff)
downloadconnman-0935c628cf83b096d72ffba5e53a6d6e8029e7ef.tar.gz
connman-0935c628cf83b096d72ffba5e53a6d6e8029e7ef.tar.bz2
connman-0935c628cf83b096d72ffba5e53a6d6e8029e7ef.zip
Check RFKILL block state before enable the device
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.
-rw-r--r--src/connman.h1
-rw-r--r--src/device.c3
-rw-r--r--src/udev-compat.c5
-rw-r--r--src/udev.c60
4 files changed, 69 insertions, 0 deletions
diff --git a/src/connman.h b/src/connman.h
index a6619df6..a7040270 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -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>
diff --git a/src/device.c b/src/device.c
index 0d418639..875b1972 100644
--- a/src/device.c
+++ b/src/device.c
@@ -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);
diff --git a/src/udev-compat.c b/src/udev-compat.c
index 70cc3bba..11567050 100644
--- a/src/udev-compat.c
+++ b/src/udev-compat.c
@@ -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("");
diff --git a/src/udev.c b/src/udev.c
index 59f36eaf..676fe6fc 100644
--- a/src/udev.c
+++ b/src/udev.c
@@ -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;