From: Alok Barsode <[email protected]>
If we get a rfkill switch before the technology driver was registered we
would lose track of it as we currently ignoed it. Adding a global rfkill
hash table which can keep a track of technologyless switches untill the
driver for them is loaded. If the driver is not compiled in the switches
will remain in the hash but will not be handled by connman.
---
src/technology.c | 66 +++++++++++++++++++++++++++++++++++++----------------
1 files changed, 46 insertions(+), 20 deletions(-)
diff --git a/src/technology.c b/src/technology.c
index ef8efb2..4a85c35 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -39,6 +39,7 @@ static GSList *technology_list = NULL;
* no compiled in support or the driver is not yet loaded.
*/
static GSList *techless_device_list = NULL;
+static GHashTable *rfkill_list;
static connman_bool_t global_offlinemode;
@@ -53,7 +54,6 @@ struct connman_technology {
int refcount;
enum connman_service_type type;
char *path;
- GHashTable *rfkill_list;
GSList *device_list;
int enabled;
char *regdom;
@@ -82,6 +82,18 @@ static gint compare_priority(gconstpointer a, gconstpointer
b)
return driver2->priority - driver1->priority;
}
+static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
+{
+ int index = (int)key;
+ struct connman_rfkill *rfkill = value;
+ enum connman_service_type type = (enum connman_service_type)user_data;
+
+ /* Calling _technology_rfkill_add will update the tech. */
+ if (rfkill->type == type)
+ __connman_technology_add_rfkill(index, type,
+ rfkill->softblock, rfkill->hardblock);
+}
+
/**
* connman_technology_driver_register:
* @driver: Technology driver definition
@@ -102,7 +114,7 @@ int connman_technology_driver_register(struct
connman_technology_driver *driver)
compare_priority);
if (g_slist_length(techless_device_list) == 0)
- return 0;
+ goto check_rfkill;
/*
* Check for technology less devices if this driver
@@ -121,6 +133,11 @@ int connman_technology_driver_register(struct
connman_technology_driver *driver)
__connman_technology_add_device(device);
}
+check_rfkill:
+ /* Check for orphaned rfkill switches. */
+ g_hash_table_foreach(rfkill_list, (GHFunc)rfkill_check,
+ (gpointer)driver->type);
+
return 0;
}
@@ -799,8 +816,6 @@ 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->pending_reply = NULL;
@@ -850,7 +865,6 @@ static void technology_put(struct connman_technology
*technology)
CONNMAN_TECHNOLOGY_INTERFACE);
g_slist_free(technology->device_list);
- g_hash_table_destroy(technology->rfkill_list);
g_free(technology->path);
g_free(technology->regdom);
@@ -1105,9 +1119,9 @@ int __connman_technology_add_rfkill(unsigned int index,
DBG("index %u type %d soft %u hard %u", index, type,
softblock, hardblock);
- technology = technology_get(type);
- if (technology == NULL)
- return -ENXIO;
+ rfkill = g_hash_table_lookup(rfkill_list, &index);
+ if (rfkill != NULL)
+ goto done;
rfkill = g_try_new0(struct connman_rfkill, 1);
if (rfkill == NULL)
@@ -1118,7 +1132,13 @@ int __connman_technology_add_rfkill(unsigned int index,
rfkill->softblock = softblock;
rfkill->hardblock = hardblock;
- g_hash_table_replace(technology->rfkill_list, &rfkill->index, rfkill);
+ g_hash_table_insert(rfkill_list, &rfkill->index, rfkill);
+
+done:
+ technology = technology_get(type);
+ /* If there is no driver for this type, ignore it. */
+ if (technology == NULL)
+ return -ENXIO;
if (hardblock) {
DBG("%s is switched off.", get_name(type));
@@ -1153,11 +1173,7 @@ int __connman_technology_update_rfkill(unsigned int
index,
DBG("index %u soft %u hard %u", index, softblock, hardblock);
- technology = technology_find(type);
- if (technology == NULL)
- return -ENXIO;
-
- rfkill = g_hash_table_lookup(technology->rfkill_list, &index);
+ rfkill = g_hash_table_lookup(rfkill_list, &index);
if (rfkill == NULL)
return -ENXIO;
@@ -1173,6 +1189,11 @@ int __connman_technology_update_rfkill(unsigned int
index,
return 0;
}
+ technology = technology_get(type);
+ /* If there is no driver for this type, ignore it. */
+ if (technology == NULL)
+ return -ENXIO;
+
if (!global_offlinemode) {
if (technology->enable_persistent && softblock)
return __connman_rfkill_block(type, FALSE);
@@ -1191,15 +1212,15 @@ int __connman_technology_remove_rfkill(unsigned int
index,
DBG("index %u", index);
- technology = technology_find(type);
- if (technology == NULL)
- return -ENXIO;
-
- rfkill = g_hash_table_lookup(technology->rfkill_list, &index);
+ rfkill = g_hash_table_lookup(rfkill_list, &index);
if (rfkill == NULL)
return -ENXIO;
- g_hash_table_remove(technology->rfkill_list, &index);
+ g_hash_table_remove(rfkill_list, &index);
+
+ technology = technology_find(type);
+ if (technology == NULL)
+ return -ENXIO;
technology_put(technology);
@@ -1212,6 +1233,9 @@ int __connman_technology_init(void)
connection = connman_dbus_get_connection();
+ rfkill_list = g_hash_table_new_full(g_int_hash, g_int_equal,
+ NULL, free_rfkill);
+
global_offlinemode = connman_technology_load_offlinemode();
return 0;
@@ -1221,5 +1245,7 @@ void __connman_technology_cleanup(void)
{
DBG("");
+ g_hash_table_destroy(rfkill_list);
+
dbus_connection_unref(connection);
}
--
1.7.5.4
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman