From 03cd2c324472088e5dbd2d7e7998cefabe15335a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 26 Jan 2010 08:16:47 +0100 Subject: [PATCH] Add available RFKILL switches to list of technologies --- src/connman.h | 8 +++++ src/rfkill.c | 42 +++++++++++++++++++++++-- src/technology.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/connman.h b/src/connman.h index d399634..be160ab 100644 --- a/src/connman.h +++ b/src/connman.h @@ -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); diff --git a/src/rfkill.c b/src/rfkill.c index f68ee0e..3792305 100644 --- a/src/rfkill.c +++ b/src/rfkill.c @@ -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); diff --git a/src/technology.c b/src/technology.c index 2f79281..fcfd9d8 100644 --- a/src/technology.c +++ b/src/technology.c @@ -29,9 +29,15 @@ 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); } -- 2.7.4