diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-10-26 13:41:27 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-10-30 15:35:58 +0100 |
commit | 0ca6ae1b4b142dfa947bec45c833388f86cc9709 (patch) | |
tree | babbea5b0360bb252154903ee9487589d2a5e789 /src | |
parent | e5b4b4d0e5ab11a581504ce88be2a1aa317524e8 (diff) |
plugin-manager,plugin: run pre-probing filters early
For each port, we will construct the list of plugins to test with. In that list
we will include those plugins which are likely to handle a given port, so we
will skip all those which aren't.
To see if a plugin is likely or not, we will run the pre-probing filters before
adding them to the list, with the new `mm_plugin_discard_port_early()'. This
method will return one of these hints:
* UNSUPPORTED: The plugin will not be able to handle this port.
* MAYBE: The plugin may handle this port.
* LIKELY: The plugin may (very likely) handle this port.
* SUPPORTED: If any plugin should support the port, this is it.
Plugins reported to be 'likely' supporting the port will be probed before the
ones reported just as 'maybe'.
If a plugin reports 'supported' only that one and the fallback generic ones will
be tried.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-plugin-manager.c | 119 | ||||
-rw-r--r-- | src/mm-plugin.c | 82 | ||||
-rw-r--r-- | src/mm-plugin.h | 15 |
3 files changed, 152 insertions, 64 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index d5759b65..56290e19 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -42,9 +42,12 @@ G_DEFINE_TYPE_EXTENDED (MMPluginManager, mm_plugin_manager, G_TYPE_OBJECT, 0, initable_iface_init)); struct _MMPluginManagerPrivate { - /* The list of plugins. It is loaded once when the program starts, and the - * list is NOT expected to change after that. */ + /* This list contains all plugins except for the generic one, order is not + * important. It is loaded once when the program starts, and the list is NOT + * expected to change after that.*/ GList *plugins; + /* Last, the generic plugin. */ + MMPlugin *generic; }; /*****************************************************************************/ @@ -65,6 +68,7 @@ typedef struct { FindDeviceSupportContext *parent_ctx; GUdevDevice *port; + GList *plugins; GList *current; MMPlugin *best_plugin; MMPlugin *suggested_plugin; @@ -86,6 +90,8 @@ port_probe_context_free (PortProbeContext *ctx) g_object_unref (ctx->best_plugin); if (ctx->suggested_plugin) g_object_unref (ctx->suggested_plugin); + if (ctx->plugins) + g_list_free_full (ctx->plugins, (GDestroyNotify)g_object_unref); g_object_unref (ctx->port); g_slice_free (PortProbeContext, ctx); } @@ -426,6 +432,62 @@ port_probe_context_step (PortProbeContext *port_probe_ctx) port_probe_ctx); } +static GList * +build_plugins_list (MMPluginManager *self, + MMDevice *device, + GUdevDevice *port) +{ + GList *list = NULL; + GList *l; + gboolean supported_found = FALSE; + + for (l = self->priv->plugins; l && !supported_found; l = g_list_next (l)) { + MMPluginSupportsHint hint; + + hint = mm_plugin_discard_port_early (MM_PLUGIN (l->data), device, port); + switch (hint) { + case MM_PLUGIN_SUPPORTS_HINT_UNSUPPORTED: + /* Fully discard */ + break; + case MM_PLUGIN_SUPPORTS_HINT_MAYBE: + /* Maybe supported, add to tail of list */ + list = g_list_append (list, g_object_ref (l->data)); + break; + case MM_PLUGIN_SUPPORTS_HINT_LIKELY: + /* Likely supported, add to head of list */ + list = g_list_prepend (list, g_object_ref (l->data)); + break; + case MM_PLUGIN_SUPPORTS_HINT_SUPPORTED: + /* Really supported, clean existing list and add it alone */ + if (list) { + g_list_free_full (list, (GDestroyNotify)g_object_unref); + list = NULL; + } + list = g_list_prepend (list, g_object_ref (l->data)); + /* This will end the loop as well */ + supported_found = TRUE; + break; + default: + g_assert_not_reached(); + } + } + + /* Add the generic plugin at the end of the list */ + if (self->priv->generic) + list = g_list_append (list, g_object_ref (self->priv->generic)); + + mm_info ("(Plugin Manager) [%s] Found '%u' plugins to try...", + g_udev_device_get_name (port), + g_list_length (list)); + for (l = list; l; l = g_list_next (l)) { + mm_info ("(Plugin Manager) [%s] Will try with plugin '%s'", + g_udev_device_get_name (port), + mm_plugin_get_name (MM_PLUGIN (l->data))); + } + + return list; +} + static void device_port_grabbed_cb (MMDevice *device, GUdevDevice *port, @@ -433,17 +495,15 @@ device_port_grabbed_cb (MMDevice *device, { PortProbeContext *port_probe_ctx; - mm_dbg ("(%s/%s) Launching port support check", - g_udev_device_get_subsystem (port), - g_udev_device_get_name (port)); /* Launch probing task on this port with the first plugin of the list */ port_probe_ctx = g_slice_new0 (PortProbeContext); port_probe_ctx->parent_ctx = ctx; port_probe_ctx->port = g_object_ref (port); - /* Set first plugin to check */ - port_probe_ctx->current = ctx->self->priv->plugins; + /* Setup plugins to probe and first one to check */ + port_probe_ctx->plugins = build_plugins_list (ctx->self, device, port); + port_probe_ctx->current = port_probe_ctx->plugins; /* If we got one suggested, it will be the first one */ port_probe_ctx->suggested_plugin = (!!mm_device_peek_plugin (device) ? @@ -585,9 +645,7 @@ load_plugins (MMPluginManager *self, { GDir *dir = NULL; const gchar *fname; - MMPlugin *generic_plugin = NULL; gchar *plugindir_display = NULL; - GList *l; if (!g_module_supported ()) { g_set_error (error, @@ -622,27 +680,25 @@ load_plugins (MMPluginManager *self, plugin = load_plugin (path); g_free (path); - if (plugin) { - if (g_str_equal (mm_plugin_get_name (plugin), - MM_PLUGIN_GENERIC_NAME)) - generic_plugin = plugin; - else - self->priv->plugins = g_list_append (self->priv->plugins, - plugin); - } - } + if (!plugin) + continue; + + mm_info ("Loaded plugin '%s'", mm_plugin_get_name (plugin)); - /* Sort last plugins that request it */ - self->priv->plugins = g_list_sort (self->priv->plugins, - (GCompareFunc)mm_plugin_cmp); + if (g_str_equal (mm_plugin_get_name (plugin), MM_PLUGIN_GENERIC_NAME)) + /* Generic plugin */ + self->priv->generic = plugin; + else + /* Vendor specific plugin */ + self->priv->plugins = g_list_append (self->priv->plugins, plugin); + } - /* Make sure the generic plugin is last */ - if (generic_plugin) - self->priv->plugins = g_list_append (self->priv->plugins, - generic_plugin); + /* Check the generic plugin once all looped */ + if (!self->priv->generic) + mm_warn ("Generic plugin not loaded"); /* Treat as error if we don't find any plugin */ - if (!self->priv->plugins) { + if (!self->priv->plugins && !self->priv->generic) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS, @@ -651,20 +707,16 @@ load_plugins (MMPluginManager *self, goto out; } - /* Now report about all the found plugins, in the same order they will be - * used while checking support */ - for (l = self->priv->plugins; l; l = g_list_next (l)) - mm_info ("Loaded plugin '%s'", mm_plugin_get_name (MM_PLUGIN (l->data))); - mm_info ("Successfully loaded %u plugins", - g_list_length (self->priv->plugins)); + g_list_length (self->priv->plugins) + !!self->priv->generic); out: if (dir) g_dir_close (dir); g_free (plugindir_display); - return !!self->priv->plugins; + /* Return TRUE if at least one plugin found */ + return (self->priv->plugins || self->priv->generic); } MMPluginManager * @@ -704,6 +756,7 @@ dispose (GObject *object) g_list_free_full (self->priv->plugins, (GDestroyNotify)g_object_unref); self->priv->plugins = NULL; } + g_clear_object (&self->priv->generic); G_OBJECT_CLASS (mm_plugin_manager_parent_class)->dispose (object); } diff --git a/src/mm-plugin.c b/src/mm-plugin.c index fff6f0a8..5069f0ee 100644 --- a/src/mm-plugin.c +++ b/src/mm-plugin.c @@ -43,31 +43,48 @@ G_DEFINE_TYPE (MMPlugin, mm_plugin, G_TYPE_OBJECT) /* Virtual port corresponding to the embeded modem */ static gchar *virtual_port[] = {"smd0", NULL}; +#define HAS_POST_PROBING_FILTERS(self) \ + (self->priv->vendor_strings || \ + self->priv->product_strings || \ + self->priv->forbidden_product_strings || \ + self->priv->allowed_icera || \ + self->priv->forbidden_icera || \ + self->priv->custom_init) + + struct _MMPluginPrivate { gchar *name; GHashTable *tasks; - /* Plugin-specific setups */ + /* Pre-probing filters */ gchar **subsystems; gchar **drivers; gchar **forbidden_drivers; guint16 *vendor_ids; mm_uint16_pair *product_ids; mm_uint16_pair *forbidden_product_ids; + gchar **udev_tags; + + /* Post probing filters */ gchar **vendor_strings; mm_str_pair *product_strings; mm_str_pair *forbidden_product_strings; - gchar **udev_tags; + gboolean allowed_icera; + gboolean forbidden_icera; + + /* Probing setup */ gboolean at; gboolean single_at; gboolean qcdm; gboolean icera_probe; - gboolean allowed_icera; - gboolean forbidden_icera; MMPortProbeAtCommand *custom_at_probe; - MMAsyncMethod *custom_init; guint64 send_delay; gboolean remove_echo; + + /* Probing setup and/or post-probing filter. + * Plugins may use this method to decide whether they support a given + * port or not, so should also be considered kind of post-probing filter. */ + MMAsyncMethod *custom_init; }; enum { @@ -106,30 +123,6 @@ mm_plugin_get_name (MMPlugin *self) /*****************************************************************************/ -gint -mm_plugin_cmp (const MMPlugin *plugin_a, - const MMPlugin *plugin_b) -{ - /* If we have any post-probing filter, we need to sort the plugin last */ -#define SORT_LAST(self) (self->priv->vendor_strings || \ - self->priv->product_strings || \ - self->priv->forbidden_product_strings) - - /* The order of the plugins in the list is the same order used to check - * whether the plugin can manage a given modem: - * - First, modems that will check vendor ID from udev. - * - Then, modems that report to be sorted last (those which will check - * vendor ID also from the probed ones.. - */ - if (SORT_LAST (plugin_a) && !SORT_LAST (plugin_b)) - return 1; - if (!SORT_LAST (plugin_a) && SORT_LAST (plugin_b)) - return -1; - return 0; -} - -/*****************************************************************************/ - static gboolean device_file_exists (const char *name) { @@ -747,6 +740,37 @@ out: /*****************************************************************************/ +MMPluginSupportsHint +mm_plugin_discard_port_early (MMPlugin *self, + MMDevice *device, + GUdevDevice *port) +{ + gboolean need_vendor_probing = FALSE; + gboolean need_product_probing = FALSE; + + /* If fully filtered by pre-probing filters, port unsupported */ + if (apply_pre_probing_filters (self, + device, + port, + &need_vendor_probing, + &need_product_probing)) + return MM_PLUGIN_SUPPORTS_HINT_UNSUPPORTED; + + /* If there are no post-probing filters, this plugin is the only one (except + * for the generic one) which will grab the port */ + if (!HAS_POST_PROBING_FILTERS (self)) + return MM_PLUGIN_SUPPORTS_HINT_SUPPORTED; + + /* If no vendor/product probing needed, plugin is likely supported */ + if (!need_vendor_probing && !need_product_probing) + return MM_PLUGIN_SUPPORTS_HINT_LIKELY; + + /* If vendor/product probing is needed, plugin may be supported */ + return MM_PLUGIN_SUPPORTS_HINT_MAYBE; +} + +/*****************************************************************************/ + MMBaseModem * mm_plugin_create_modem (MMPlugin *self, MMDevice *device, diff --git a/src/mm-plugin.h b/src/mm-plugin.h index 6d5d14e1..a423ceb0 100644 --- a/src/mm-plugin.h +++ b/src/mm-plugin.h @@ -67,6 +67,13 @@ typedef enum { MM_PLUGIN_SUPPORTS_PORT_SUPPORTED } MMPluginSupportsResult; +typedef enum { + MM_PLUGIN_SUPPORTS_HINT_UNSUPPORTED, + MM_PLUGIN_SUPPORTS_HINT_MAYBE, + MM_PLUGIN_SUPPORTS_HINT_LIKELY, + MM_PLUGIN_SUPPORTS_HINT_SUPPORTED, +} MMPluginSupportsHint; + typedef struct _MMPlugin MMPlugin; typedef struct _MMPluginClass MMPluginClass; typedef struct _MMPluginPrivate MMPluginPrivate; @@ -102,8 +109,12 @@ struct _MMPluginClass { GType mm_plugin_get_type (void); const gchar *mm_plugin_get_name (MMPlugin *plugin); -gint mm_plugin_cmp (const MMPlugin *plugin_a, - const MMPlugin *plugin_b); + +/* This method will run all pre-probing filters, to see if we can discard this + * plugin from the probing logic as soon as possible. */ +MMPluginSupportsHint mm_plugin_discard_port_early (MMPlugin *plugin, + MMDevice *device, + GUdevDevice *port); void mm_plugin_supports_port (MMPlugin *plugin, MMDevice *device, |