Add available RFKILL switches to list of technologies
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 26 Jan 2010 07:16:47 +0000 (08:16 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 26 Jan 2010 07:16:47 +0000 (08:16 +0100)
src/connman.h
src/rfkill.c
src/technology.c

index d399634..be160ab 100644 (file)
@@ -273,6 +273,14 @@ void __connman_technology_list(DBusMessageIter *iter, void *user_data);
 
 int __connman_technology_add_device(struct connman_device *device);
 int __connman_technology_remove_device(struct connman_device *device);
+int __connman_technology_add_rfkill(unsigned int index,
+                                       enum connman_service_type type,
+                                               connman_bool_t softblock,
+                                               connman_bool_t hardblock);
+int __connman_technology_update_rfkill(unsigned int index,
+                                               connman_bool_t softblock,
+                                               connman_bool_t hardblock);
+int __connman_technology_remove_rfkill(unsigned int index);
 
 int __connman_device_init(void);
 void __connman_device_cleanup(void);
index f68ee0e..3792305 100644 (file)
@@ -39,6 +39,8 @@ enum rfkill_type {
        RFKILL_TYPE_UWB,
        RFKILL_TYPE_WIMAX,
        RFKILL_TYPE_WWAN,
+       RFKILL_TYPE_GPS,
+       RFKILL_TYPE_FM,
 };
 
 enum rfkill_operation {
@@ -56,12 +58,29 @@ struct rfkill_event {
        uint8_t  hard;
 };
 
+static enum connman_service_type convert_type(uint8_t type)
+{
+       switch (type) {
+       case RFKILL_TYPE_WLAN:
+               return CONNMAN_SERVICE_TYPE_WIFI;
+       case RFKILL_TYPE_BLUETOOTH:
+               return CONNMAN_SERVICE_TYPE_BLUETOOTH;
+       case RFKILL_TYPE_WIMAX:
+               return CONNMAN_SERVICE_TYPE_WIMAX;
+       case RFKILL_TYPE_WWAN:
+               return CONNMAN_SERVICE_TYPE_CELLULAR;
+       }
+
+       return CONNMAN_SERVICE_TYPE_UNKNOWN;
+}
+
 static GIOStatus rfkill_process(GIOChannel *chan)
 {
        GIOStatus status = G_IO_STATUS_NORMAL;
        unsigned char buf[32];
        struct rfkill_event *event = (void *) buf;
        char sysname[32];
+       enum connman_service_type type;
        connman_bool_t blocked;
        gsize len;
 
@@ -78,9 +97,26 @@ static GIOStatus rfkill_process(GIOChannel *chan)
        if (len != sizeof(struct rfkill_event))
                return status;
 
-       DBG("idx %u type %u op %u soft %u hard %u",
-                               event->idx, event->type, event->op,
-                                       event->soft, event->hard);
+       DBG("idx %u type %u op %u soft %u hard %u", event->idx,
+                                               event->type, event->op,
+                                               event->soft, event->hard);
+
+       switch (event->op) {
+       case RFKILL_OP_ADD:
+               type = convert_type(event->type);
+               __connman_technology_add_rfkill(event->idx, type,
+                                               event->soft, event->hard);
+               break;
+       case RFKILL_OP_DEL:
+               __connman_technology_remove_rfkill(event->idx);
+               break;
+       case RFKILL_OP_CHANGE:
+               __connman_technology_update_rfkill(event->idx, event->soft,
+                                                               event->hard);
+               break;
+       default:
+               break;
+       }
 
        snprintf(sysname, sizeof(sysname) - 1, "rfkill%d", event->idx);
 
index 2f79281..fcfd9d8 100644 (file)
 
 static DBusConnection *connection;
 
+static GHashTable *rfkill_table;
 static GHashTable *device_table;
 static GSList *technology_list = NULL;
 
+struct connman_rfkill {
+       unsigned int index;
+       enum connman_service_type type;
+};
+
 enum connman_technology_state {
        CONNMAN_TECHNOLOGY_STATE_UNKNOWN   = 0,
        CONNMAN_TECHNOLOGY_STATE_OFFLINE   = 1,
@@ -45,9 +51,17 @@ struct connman_technology {
        enum connman_service_type type;
        enum connman_technology_state state;
        char *path;
+       GHashTable *rfkill_list;
        GSList *device_list;
 };
 
+static void free_rfkill(gpointer data)
+{
+       struct connman_rfkill *rfkill = data;
+
+       g_free(rfkill);
+}
+
 void __connman_technology_list(DBusMessageIter *iter, void *user_data)
 {
        GSList *list;
@@ -241,6 +255,12 @@ static struct connman_technology *technology_get(enum connman_service_type type)
        technology->path = g_strdup_printf("%s/technology/%s",
                                                        CONNMAN_PATH, str);
 
+       technology->rfkill_list = g_hash_table_new_full(g_int_hash, g_int_equal,
+                                                       NULL, free_rfkill);
+       technology->device_list = NULL;
+
+       technology->state = CONNMAN_TECHNOLOGY_STATE_OFFLINE;
+
        if (g_dbus_register_interface(connection, technology->path,
                                        CONNMAN_TECHNOLOGY_INTERFACE,
                                        technology_methods, technology_signals,
@@ -274,16 +294,17 @@ static void technology_put(struct connman_technology *technology)
        g_dbus_unregister_interface(connection, technology->path,
                                                CONNMAN_TECHNOLOGY_INTERFACE);
 
+       g_slist_free(technology->device_list);
+       g_hash_table_destroy(technology->rfkill_list);
+
        g_free(technology->path);
        g_free(technology);
 }
 
-static void unregister_device(gpointer data)
+static void unregister_technology(gpointer data)
 {
        struct connman_technology *technology = data;
 
-       DBG("technology %p", technology);
-
        technology_put(technology);
 }
 
@@ -338,14 +359,79 @@ int __connman_technology_remove_device(struct connman_device *device)
        return 0;
 }
 
+int __connman_technology_add_rfkill(unsigned int index,
+                                       enum connman_service_type type,
+                                               connman_bool_t softblock,
+                                               connman_bool_t hardblock)
+{
+       struct connman_technology *technology;
+       struct connman_rfkill *rfkill;
+
+       DBG("index %u type %d soft %u hard %u", index, type,
+                                                       softblock, hardblock);
+
+       rfkill = g_try_new0(struct connman_rfkill, 1);
+       if (rfkill == NULL)
+               return -ENOMEM;
+
+       rfkill->index = index;
+       rfkill->type = type;
+
+       technology = technology_get(type);
+       if (technology == NULL) {
+               g_free(rfkill);
+               return -ENXIO;
+       }
+
+       g_hash_table_replace(rfkill_table, &index, technology);
+
+       g_hash_table_replace(technology->rfkill_list, &index, rfkill);
+
+       return 0;
+}
+
+int __connman_technology_update_rfkill(unsigned int index,
+                                               connman_bool_t softblock,
+                                               connman_bool_t hardblock)
+{
+       struct connman_technology *technology;
+
+       DBG("index %u soft %u hard %u", index, softblock, hardblock);
+
+       technology = g_hash_table_lookup(rfkill_table, &index);
+       if (technology == NULL)
+               return -ENXIO;
+
+       return 0;
+}
+
+int __connman_technology_remove_rfkill(unsigned int index)
+{
+       struct connman_technology *technology;
+
+       DBG("index %u", index);
+
+       technology = g_hash_table_lookup(rfkill_table, &index);
+       if (technology == NULL)
+               return -ENXIO;
+
+       g_hash_table_remove(technology->rfkill_list, &index);
+
+       g_hash_table_remove(rfkill_table, &index);
+
+       return 0;
+}
+
 int __connman_technology_init(void)
 {
        DBG("");
 
        connection = connman_dbus_get_connection();
 
+       rfkill_table = g_hash_table_new_full(g_int_hash, g_int_equal,
+                                               NULL, unregister_technology);
        device_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-                                               NULL, unregister_device);
+                                               NULL, unregister_technology);
 
        return 0;
 }
@@ -355,6 +441,7 @@ void __connman_technology_cleanup(void)
        DBG("");
 
        g_hash_table_destroy(device_table);
+       g_hash_table_destroy(rfkill_table);
 
        dbus_connection_unref(connection);
 }