aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-06-29 16:51:25 -0400
committerDan Williams <dcbw@redhat.com>2009-06-29 16:51:25 -0400
commit7b7df91eb879b1070ed7fe99b5e201835eff53f6 (patch)
tree3e9c3d9d6122845bac808e9c63947810c52c97c8
parente3eef316a570e36d45ca582bf54aef4db9c2eb8d (diff)
manager: do modem creation from an idle handler
It helps make the supports/grab callchain less crappy to look at in gdb by ensuring that the supports chain unwinds before the grab happens, and also ensures that we use the right subsys/name variables rather than depending on ones the plugin provided to supports_callback, that may go be freed by the plugin somewhere in grab_port().
-rw-r--r--src/mm-manager.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/src/mm-manager.c b/src/mm-manager.c
index c6445cf6..aa109a99 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -271,6 +271,7 @@ typedef struct {
GSList *plugins;
GSList *cur_plugin;
guint defer_id;
+ guint done_id;
guint32 best_level;
MMPlugin *best_plugin;
@@ -301,6 +302,9 @@ supports_info_free (SupportsInfo *info)
if (info->defer_id)
g_source_remove (info->defer_id);
+ if (info->done_id)
+ g_source_remove (info->done_id);
+
g_free (info->subsys);
g_free (info->name);
g_slist_free (info->plugins);
@@ -373,12 +377,8 @@ try_supports_port (MMManager *manager,
}
}
-static void
-supports_callback (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- guint32 level,
- gpointer user_data)
+static gboolean
+do_grab_port (gpointer user_data)
{
SupportsInfo *info = user_data;
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (info->manager);
@@ -386,32 +386,6 @@ supports_callback (MMPlugin *plugin,
GError *error = NULL;
char *key;
GSList *iter;
- MMPlugin *next_plugin = NULL;
-
- info->cur_plugin = info->cur_plugin->next;
- if (info->cur_plugin)
- next_plugin = MM_PLUGIN (info->cur_plugin->data);
-
- /* Is this plugin's result better than any one we've tried before? */
- if (level > info->best_level) {
- info->best_level = level;
- info->best_plugin = plugin;
- }
-
- /* Prevent the generic plugin from probing devices that are already supported
- * by other plugins. For Huawei for example, secondary ports shouldn't
- * be probed, but the generic plugin would happily do so if allowed to.
- */
- if ( next_plugin
- && !strcmp (mm_plugin_get_name (next_plugin), MM_PLUGIN_GENERIC_NAME)
- && info->best_plugin)
- next_plugin = NULL;
-
- /* Try the next plugin */
- if (next_plugin) {
- try_supports_port (info->manager, next_plugin, info->subsys, info->name, info);
- return;
- }
/* No more plugins to try */
if (info->best_plugin) {
@@ -431,15 +405,15 @@ supports_callback (MMPlugin *plugin,
mm_plugin_get_name (info->best_plugin),
type_name,
mm_modem_get_device (modem),
- name);
+ info->name);
add_modem (info->manager, modem);
} else {
g_warning ("%s: plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
__func__,
mm_plugin_get_name (info->best_plugin),
- subsys,
- name,
+ info->subsys,
+ info->name,
error ? error->code : -1,
(error && error->message) ? error->message : "(unknown)");
}
@@ -447,13 +421,53 @@ supports_callback (MMPlugin *plugin,
/* Tell each plugin to clean up any outstanding supports task */
for (iter = info->plugins; iter; iter = g_slist_next (iter))
- mm_plugin_cancel_supports_port (MM_PLUGIN (iter->data), subsys, name);
+ mm_plugin_cancel_supports_port (MM_PLUGIN (iter->data), info->subsys, info->name);
g_slist_free (info->plugins);
info->cur_plugin = info->plugins = NULL;
key = get_key (info->subsys, info->name);
g_hash_table_remove (priv->supports, key);
g_free (key);
+
+ return FALSE;
+}
+
+static void
+supports_callback (MMPlugin *plugin,
+ const char *subsys,
+ const char *name,
+ guint32 level,
+ gpointer user_data)
+{
+ SupportsInfo *info = user_data;
+ MMPlugin *next_plugin = NULL;
+
+ info->cur_plugin = info->cur_plugin->next;
+ if (info->cur_plugin)
+ next_plugin = MM_PLUGIN (info->cur_plugin->data);
+
+ /* Is this plugin's result better than any one we've tried before? */
+ if (level > info->best_level) {
+ info->best_level = level;
+ info->best_plugin = plugin;
+ }
+
+ /* Prevent the generic plugin from probing devices that are already supported
+ * by other plugins. For Huawei for example, secondary ports shouldn't
+ * be probed, but the generic plugin would happily do so if allowed to.
+ */
+ if ( next_plugin
+ && !strcmp (mm_plugin_get_name (next_plugin), MM_PLUGIN_GENERIC_NAME)
+ && info->best_plugin)
+ next_plugin = NULL;
+
+ if (next_plugin) {
+ /* Try the next plugin */
+ try_supports_port (info->manager, next_plugin, info->subsys, info->name, info);
+ } else {
+ /* All done; let the best modem grab the port */
+ info->done_id = g_idle_add (do_grab_port, info);
+ }
}
static void