Handle the RFKILL change events from udev
authorMarcel Holtmann <marcel@holtmann.org>
Wed, 22 Jul 2009 18:52:53 +0000 (20:52 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 22 Jul 2009 18:52:53 +0000 (20:52 +0200)
src/udev.c

index a1b9223..b14b625 100644 (file)
@@ -71,7 +71,7 @@ static struct connman_device *find_device(int index)
        return NULL;
 }
 
-static void add_device(struct udev_device *udev_device)
+static void add_net_device(struct udev_device *udev_device)
 {
        struct udev_list_entry *entry;
        struct connman_device *device;
@@ -140,7 +140,7 @@ static void add_device(struct udev_device *udev_device)
        device_list = g_slist_append(device_list, device);
 }
 
-static void remove_device(struct udev_device *udev_device)
+static void remove_net_device(struct udev_device *udev_device)
 {
        struct udev_list_entry *entry;
        struct connman_device *device;
@@ -174,6 +174,67 @@ static void remove_device(struct udev_device *udev_device)
        connman_device_unref(device);
 }
 
+static void phyindex_rfkill(int phyindex, connman_bool_t blocked)
+{
+       GSList *list;
+
+       if (phyindex < 0)
+               return;
+
+       for (list = device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+
+               if (__connman_device_get_phyindex(device) == phyindex)
+                       __connman_device_set_blocked(device, blocked);
+       }
+}
+
+static void change_rfkill_device(struct udev_device *device)
+{
+       struct udev_device *parent;
+       struct udev_list_entry *entry;
+       connman_bool_t blocked;
+       const char *value, *type = NULL;
+       int state = -1;
+
+       entry = udev_device_get_properties_list_entry(device);
+       while (entry) {
+               const char *name = udev_list_entry_get_name(entry);
+
+               if (g_str_has_prefix(name, "RFKILL_STATE") == TRUE) {
+                       value = udev_list_entry_get_value(entry);
+                       if (value != NULL)
+                               state = atoi(value);
+               } else if (g_str_has_prefix(name, "RFKILL_TYPE") == TRUE)
+                       type = udev_list_entry_get_value(entry);
+
+               entry = udev_list_entry_get_next(entry);
+       }
+
+       if (type == NULL || state < 0)
+               return;
+
+       if (g_str_equal(type, "wlan") == FALSE)
+               return;
+
+       parent = udev_device_get_parent(device);
+       if (parent == NULL)
+               return;
+
+       value = udev_device_get_sysattr_value(parent, "index");
+       if (value == NULL)
+               return;
+
+       blocked = (state != 1) ? TRUE : FALSE;
+
+       phyindex_rfkill(atoi(value), blocked);
+}
+
+static void add_rfkill_device(struct udev_device *device)
+{
+       change_rfkill_device(device);
+}
+
 static void print_properties(struct udev_device *device, const char *prefix)
 {
        struct udev_list_entry *entry;
@@ -245,6 +306,7 @@ static void enumerate_devices(struct udev *context)
                return;
 
        udev_enumerate_add_match_subsystem(enumerate, "net");
+       udev_enumerate_add_match_subsystem(enumerate, "rfkill");
 
        udev_enumerate_scan_devices(enumerate);
 
@@ -254,12 +316,20 @@ static void enumerate_devices(struct udev *context)
                struct udev_device *device;
 
                device = udev_device_new_from_syspath(context, syspath);
+               if (device != NULL) {
+                       const char *subsystem;
 
-               print_device(device, "coldplug");
+                       print_device(device, "coldplug");
 
-               add_device(device);
+                       subsystem = udev_device_get_subsystem(device);
 
-               udev_device_unref(device);
+                       if (g_strcmp0(subsystem, "net") == 0)
+                               add_net_device(device);
+                       else if (g_strcmp0(subsystem, "rfkill") == 0)
+                               add_rfkill_device(device);
+
+                       udev_device_unref(device);
+               }
 
                entry = udev_list_entry_get_next(entry);
        }
@@ -282,19 +352,24 @@ static gboolean udev_event(GIOChannel *channel,
        if (subsystem == NULL)
                goto done;
 
-       if (g_str_equal(subsystem, "net") == FALSE)
-               goto done;
-
        action = udev_device_get_action(device);
        if (action == NULL)
                goto done;
 
        print_device(device, action);
 
-       if (g_str_equal(action, "add") == TRUE)
-               add_device(device);
-       else if (g_str_equal(action, "remove") == TRUE)
-               remove_device(device);
+       if (g_str_equal(action, "add") == TRUE) {
+               if (g_str_equal(subsystem, "net") == TRUE)
+                       add_net_device(device);
+               else if (g_str_equal(subsystem, "rfkill") == TRUE)
+                       add_rfkill_device(device);
+       } else if (g_str_equal(action, "remove") == TRUE) {
+               if (g_str_equal(subsystem, "net") == TRUE)
+                       remove_net_device(device);
+       } else if (g_str_equal(action, "change") == TRUE) {
+               if (g_str_equal(subsystem, "rfkill") == TRUE)
+                       change_rfkill_device(device);
+       }
 
 done:
        udev_device_unref(device);
@@ -382,21 +457,6 @@ done:
        return devnode;
 }
 
-static void phyindex_rfkill(int phyindex, connman_bool_t blocked)
-{
-       GSList *list;
-
-       if (phyindex < 0)
-               return;
-
-       for (list = device_list; list; list = list->next) {
-               struct connman_device *device = list->data;
-
-               if (__connman_device_get_phyindex(device) == phyindex)
-                       __connman_device_set_blocked(device, blocked);
-       }
-}
-
 void __connman_udev_rfkill(const char *sysname, connman_bool_t blocked)
 {
        struct udev_device *device, *parent;