aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-manager.c754
1 files changed, 200 insertions, 554 deletions
diff --git a/src/mm-manager.c b/src/mm-manager.c
index aeed222d..191fef67 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -11,7 +11,8 @@
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ * Copyright (C) 2009 - 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Aleksander Morgado <aleksander@gnu.org>
*/
#include <string.h>
@@ -22,6 +23,7 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "mm-manager.h"
+#include "mm-plugin-manager.h"
#include "mm-auth-provider.h"
#include "mm-errors.h"
#include "mm-plugin.h"
@@ -38,6 +40,11 @@ static gboolean impl_manager_set_logging (MMManager *manager,
const char *level,
GError **error);
+static void grab_port (MMManager *manager,
+ MMPlugin *plugin,
+ GUdevDevice *device,
+ GUdevDevice *physical_device);
+
#include "mm-manager-glue.h"
G_DEFINE_TYPE (MMManager, mm_manager, G_TYPE_OBJECT)
@@ -56,160 +63,41 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
DBusGConnection *connection;
GUdevClient *udev;
- GSList *plugins;
GHashTable *modems;
MMAuthProvider *authp;
- GHashTable *supports;
+ /* The Plugin Manager object */
+ MMPluginManager *plugin_manager;
} MMManagerPrivate;
typedef struct {
MMManager *manager;
- char *subsys;
- char *name;
- char *physdev_path;
- GSList *plugins;
- GSList *cur_plugin;
- guint defer_id;
- guint done_id;
-
- guint32 best_level;
- MMPlugin *best_plugin;
-} SupportsInfo;
-
+ GUdevDevice *device;
+ GUdevDevice *physical_device;
+} FindPortSupportContext;
-static MMPlugin *
-load_plugin (const char *path)
+static FindPortSupportContext *
+find_port_support_context_new (MMManager *manager,
+ GUdevDevice *device,
+ GUdevDevice *physical_device)
{
- MMPlugin *plugin = NULL;
- GModule *module;
- MMPluginCreateFunc plugin_create_func;
- int *major_plugin_version, *minor_plugin_version;
-
- module = g_module_open (path, G_MODULE_BIND_LAZY);
- if (!module) {
- g_warning ("Could not load plugin %s: %s", path, g_module_error ());
- return NULL;
- }
-
- if (!g_module_symbol (module, "mm_plugin_major_version", (gpointer *) &major_plugin_version)) {
- g_warning ("Could not load plugin %s: Missing major version info", path);
- goto out;
- }
-
- if (*major_plugin_version != MM_PLUGIN_MAJOR_VERSION) {
- g_warning ("Could not load plugin %s: Plugin major version %d, %d is required",
- path, *major_plugin_version, MM_PLUGIN_MAJOR_VERSION);
- goto out;
- }
-
- if (!g_module_symbol (module, "mm_plugin_minor_version", (gpointer *) &minor_plugin_version)) {
- g_warning ("Could not load plugin %s: Missing minor version info", path);
- goto out;
- }
-
- if (*minor_plugin_version != MM_PLUGIN_MINOR_VERSION) {
- g_warning ("Could not load plugin %s: Plugin minor version %d, %d is required",
- path, *minor_plugin_version, MM_PLUGIN_MINOR_VERSION);
- goto out;
- }
-
- if (!g_module_symbol (module, "mm_plugin_create", (gpointer *) &plugin_create_func)) {
- g_warning ("Could not load plugin %s: %s", path, g_module_error ());
- goto out;
- }
-
- plugin = (*plugin_create_func) ();
- if (plugin) {
- g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
- } else
- mm_warn ("Could not load plugin %s: initialization failed", path);
-
- out:
- if (!plugin)
- g_module_close (module);
-
- return plugin;
-}
+ FindPortSupportContext *ctx;
-static gint
-compare_plugins (const MMPlugin *plugin_a,
- const MMPlugin *plugin_b)
-{
- /* 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 (mm_plugin_get_sort_last (plugin_a) &&
- !mm_plugin_get_sort_last (plugin_b))
- return 1;
- if (!mm_plugin_get_sort_last (plugin_a) &&
- mm_plugin_get_sort_last (plugin_b))
- return -1;
- return 0;
-}
+ ctx = g_new0 (FindPortSupportContext, 1);
+ ctx->manager = manager;
+ ctx->device = g_object_ref (device);
+ ctx->physical_device = g_object_ref (physical_device);
-static void
-found_plugin (MMPlugin *plugin)
-{
- mm_info ("Loaded plugin '%s'", mm_plugin_get_name (plugin));
+ return ctx;
}
static void
-load_plugins (MMManager *manager)
+find_port_support_context_free (FindPortSupportContext *ctx)
{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
- GDir *dir;
- const char *fname;
- MMPlugin *generic_plugin = NULL;
-
- if (!g_module_supported ()) {
- g_warning ("GModules are not supported on your platform!");
- return;
- }
-
- dir = g_dir_open (PLUGINDIR, 0, NULL);
- if (!dir) {
- g_warning ("No plugins found");
- return;
- }
-
- while ((fname = g_dir_read_name (dir)) != NULL) {
- char *path;
- MMPlugin *plugin;
-
- if (!g_str_has_suffix (fname, G_MODULE_SUFFIX))
- continue;
-
- path = g_module_build_path (PLUGINDIR, fname);
- plugin = load_plugin (path);
- g_free (path);
-
- if (plugin) {
- if (!strcmp (mm_plugin_get_name (plugin), MM_PLUGIN_GENERIC_NAME))
- generic_plugin = plugin;
- else
- priv->plugins = g_slist_append (priv->plugins, plugin);
- }
- }
-
- /* Sort last plugins that request it */
- priv->plugins = g_slist_sort (priv->plugins, (GCompareFunc)compare_plugins);
-
- /* Make sure the generic plugin is last */
- if (generic_plugin)
- priv->plugins = g_slist_append (priv->plugins, generic_plugin);
-
- /* Now report about all the found plugins, in the same order they will be
- * used while checking support */
- g_slist_foreach (priv->plugins, (GFunc)found_plugin, NULL);
-
- mm_info ("Successfully loaded %u plugins", g_slist_length (priv->plugins));
-
- g_dir_close (dir);
+ g_object_unref (ctx->device);
+ g_object_unref (ctx->physical_device);
+ g_free (ctx);
}
MMManager *
@@ -221,12 +109,23 @@ mm_manager_new (DBusGConnection *bus)
manager = (MMManager *) g_object_new (MM_TYPE_MANAGER, NULL);
if (manager) {
+ GError *error = NULL;
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
priv->connection = dbus_g_connection_ref (bus);
dbus_g_connection_register_g_object (priv->connection,
MM_DBUS_PATH,
G_OBJECT (manager));
+
+ priv->plugin_manager = mm_plugin_manager_new (&error);
+ if (!priv->plugin_manager) {
+ mm_warn ("Error creating Plugin Manager: '%s'",
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+
+ g_object_unref (manager);
+ manager = NULL;
+ }
}
return manager;
@@ -247,36 +146,13 @@ remove_modem (MMManager *manager, MMModem *modem)
g_free (device);
}
-/* Return the first outstanding supports task */
-static SupportsInfo *
-find_supports_info (MMManager *self, MMModem *modem)
-{
- char *modem_physdev;
- GHashTableIter iter;
- SupportsInfo *info, *ret = NULL;
-
- modem_physdev = mm_modem_get_device (modem);
- g_assert (modem_physdev);
-
- /* Check for ports that are in the process of being interrogated by plugins */
- g_hash_table_iter_init (&iter, MM_MANAGER_GET_PRIVATE (self)->supports);
- while (!ret && g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) {
- if (g_strcmp0 (info->physdev_path, modem_physdev) == 0)
- ret = info;
- }
- g_free (modem_physdev);
- return ret;
-}
-
static void
check_export_modem (MMManager *self, MMModem *modem)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self);
- SupportsInfo *info;
- static guint32 id = 0, vid = 0, pid = 0;
- char *path, *data_device = NULL, *modem_physdev;
- GUdevDevice *physdev;
- const char *subsys = NULL;
+ char *modem_physdev;
+ const gchar *name;
+ const gchar *subsys;
/* A modem is only exported to D-Bus when both of the following are true:
*
@@ -291,47 +167,62 @@ check_export_modem (MMManager *self, MMModem *modem)
* chance that a port could show up after the modem is already created and
* all other ports are already handled. That chance is very small though.
*/
+ modem_physdev = mm_modem_get_device (modem);
+ g_assert (modem_physdev);
- info = find_supports_info (self, modem);
- if (info) {
+ /* Check for ports that are in the process of being interrogated by plugins */
+ if (mm_plugin_manager_is_finding_device_support (priv->plugin_manager,
+ modem_physdev,
+ &subsys,
+ &name)) {
mm_dbg ("(%s/%s): outstanding support task prevents export of %s",
- info->subsys, info->name, info->physdev_path);
- return;
+ subsys, name, modem_physdev);
+ goto out;
}
- /* Obviously don't re-export a modem, or try to export one that's not valid */
- if ( g_object_get_data (G_OBJECT (modem), DBUS_PATH_TAG)
- || !mm_modem_get_valid (modem))
- return;
-
- path = g_strdup_printf (MM_DBUS_PATH "/Modems/%d", id++);
- dbus_g_connection_register_g_object (priv->connection, path, G_OBJECT (modem));
- g_object_set_data_full (G_OBJECT (modem), DBUS_PATH_TAG, path, (GDestroyNotify) g_free);
+ /* Already exported? This can happen if the modem is exported and the kernel
+ * discovers another of the modem's ports.
+ */
+ if (g_object_get_data (G_OBJECT (modem), DBUS_PATH_TAG))
+ goto out;
- modem_physdev = mm_modem_get_device (modem);
- g_assert (modem_physdev);
- mm_dbg ("Exported modem %s as %s", modem_physdev, path);
+ /* No outstanding port tasks, so if the modem is valid we can export it */
+ if (mm_modem_get_valid (modem)) {
+ static guint32 id = 0, vid = 0, pid = 0;
+ char *path, *data_device = NULL;
+ GUdevDevice *physdev;
- physdev = g_udev_client_query_by_sysfs_path (priv->udev, modem_physdev);
- g_free (modem_physdev);
- if (physdev)
- subsys = g_udev_device_get_subsystem (physdev);
-
- g_object_get (G_OBJECT (modem),
- MM_MODEM_DATA_DEVICE, &data_device,
- MM_MODEM_HW_VID, &vid,
- MM_MODEM_HW_PID, &pid,
- NULL);
- mm_dbg ("(%s): VID 0x%04X PID 0x%04X (%s)",
- path, (vid & 0xFFFF), (pid & 0xFFFF),
- subsys ? subsys : "unknown");
- mm_dbg ("(%s): data port is %s", path, data_device);
- g_free (data_device);
+ subsys = NULL;
- if (physdev)
- g_object_unref (physdev);
+ path = g_strdup_printf (MM_DBUS_PATH"/Modems/%d", id++);
+ dbus_g_connection_register_g_object (priv->connection, path, G_OBJECT (modem));
+ g_object_set_data_full (G_OBJECT (modem), DBUS_PATH_TAG, path, (GDestroyNotify) g_free);
+
+ mm_dbg ("Exported modem %s as %s", modem_physdev, path);
+
+ physdev = g_udev_client_query_by_sysfs_path (priv->udev, modem_physdev);
+ if (physdev)
+ subsys = g_udev_device_get_subsystem (physdev);
+
+ g_object_get (G_OBJECT (modem),
+ MM_MODEM_DATA_DEVICE, &data_device,
+ MM_MODEM_HW_VID, &vid,
+ MM_MODEM_HW_PID, &pid,
+ NULL);
+ mm_dbg ("(%s): VID 0x%04X PID 0x%04X (%s)",
+ path, (vid & 0xFFFF), (pid & 0xFFFF),
+ subsys ? subsys : "unknown");
+ mm_dbg ("(%s): data port is %s", path, data_device);
+ g_free (data_device);
+
+ if (physdev)
+ g_object_unref (physdev);
- g_signal_emit (self, signals[DEVICE_ADDED], 0, modem);
+ g_signal_emit (self, signals[DEVICE_ADDED], 0, modem);
+ }
+
+out:
+ g_free (modem_physdev);
}
static void
@@ -416,7 +307,6 @@ find_modem_for_device (MMManager *manager, const char *device)
return found;
}
-
static MMModem *
find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
{
@@ -434,330 +324,107 @@ find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
return NULL;
}
-static SupportsInfo *
-supports_info_new (MMManager *self,
- const char *subsys,
- const char *name,
- const char *physdev_path)
-{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self);
- SupportsInfo *info;
-
- info = g_malloc0 (sizeof (SupportsInfo));
- info->manager = self;
- info->subsys = g_strdup (subsys);
- info->name = g_strdup (name);
- info->physdev_path = g_strdup (physdev_path);
- info->plugins = g_slist_copy (priv->plugins);
- info->cur_plugin = info->plugins;
- return info;
-}
-
static void
-supports_info_free (SupportsInfo *info)
+find_port_support_ready_cb (MMPluginManager *plugin_manager,
+ GAsyncResult *result,
+ FindPortSupportContext *ctx)
{
- /* Cancel any in-process operation on the first plugin */
- if (info->cur_plugin)
- mm_plugin_supports_port_cancel (MM_PLUGIN (info->cur_plugin->data),
- info->subsys,
- info->name);
-
- 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);
- memset (info, 0, sizeof (SupportsInfo));
- g_free (info);
-}
-
-static char *
-get_key (const char *subsys, const char *name)
-{
- return g_strdup_printf ("%s%s", subsys, name);
-}
-
-
-static void supports_callback (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- guint32 level,
- gpointer user_data);
-
-static void supports_port_ready_cb (MMPlugin *plugin,
- GAsyncResult *result,
- SupportsInfo *info);
-
-static gboolean
-supports_defer_timeout (gpointer user_data)
-{
- SupportsInfo *info = user_data;
- MMModem *existing;
-
- existing = find_modem_for_device (info->manager, info->physdev_path);
-
- mm_dbg ("(%s): re-checking support...", info->name);
- mm_plugin_supports_port (MM_PLUGIN (info->cur_plugin->data),
- info->subsys,
- info->name,
- info->physdev_path,
- existing,
- (GAsyncReadyCallback)supports_port_ready_cb,
- info);
- return FALSE;
-}
-
-static void
-supports_port_ready_cb (MMPlugin *plugin,
- GAsyncResult *result,
- SupportsInfo *info)
-{
- MMPluginSupportsResult supports_result;
- GError *error = NULL;
- guint level = 0;
-
- /* Get supports check results */
- supports_result = mm_plugin_supports_port_finish (plugin,
- result,
- &level,
- &error);
- if (error) {
- mm_warn ("(%s): (%s) error when checking support: '%s'",
- mm_plugin_get_name (plugin),
- info->name,
- error->message);
- g_error_free (error);
- }
-
- switch (supports_result) {
- case MM_PLUGIN_SUPPORTS_PORT_SUPPORTED:
- /* Report support level to the callback */
- supports_callback (plugin, info->subsys, info->name, level, info);
- break;
- case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED:
- /* If the plugin knows it doesn't support the modem, just call the
- * callback and indicate 0 support.
- */
- supports_callback (plugin, info->subsys, info->name, 0, info);
- break;
- case MM_PLUGIN_SUPPORTS_PORT_DEFER:
- mm_dbg ("(%s): (%s) deferring support check",
- mm_plugin_get_name (plugin),
- info->name);
- if (info->defer_id)
- g_source_remove (info->defer_id);
-
- /* defer port detection for a bit as requested by the plugin */
- info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
- break;
- case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
- /* This should never happen at this level */
- g_warn_if_reached ();
- break;
- }
-}
-
-static void
-supports_cleanup (MMManager *self,
- const char *subsys,
- const char *name,
- MMModem *modem)
-{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self);
- char *key;
GError *error = NULL;
+ MMPlugin *best_plugin;
- g_return_if_fail (subsys != NULL);
- g_return_if_fail (name != NULL);
-
- key = get_key (subsys, name);
- g_hash_table_remove (priv->supports, key);
- g_free (key);
-
- if (modem == NULL)
- return;
-
- if ( (find_supports_info (self, modem) == NULL)
- && !g_object_get_data (G_OBJECT (modem), "organized")) {
- /* Yay, we're done with supports tasks, tell the modem to organize
- * all its ports. Guard against multiple organize calls though since
- * if the kernel or udev is slow, ports may show up long after the
- * first bunch of supports tasks is done.
- */
- g_object_set_data (G_OBJECT (modem), "organized", GUINT_TO_POINTER (1));
- if (!mm_modem_organize_ports (modem, &error)) {
- mm_err ("Failed to organize modem ports: (%d) %s",
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
- remove_modem (self, modem);
- return;
- }
- }
-
- /* Each time a supports task is cleaned up, check whether the modem is
- * now completely probed/handled and should be exported to D-Bus clients.
- *
- * IMPORTANT: this must be done after removing the supports info from
- * priv->supports since check_export_modem() searches through priv->supports
- * for outstanding supports tasks.
- */
- check_export_modem (self, modem);
-}
-
-static gboolean
-do_grab_port (gpointer user_data)
-{
- SupportsInfo *info = user_data;
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (info->manager);
- MMModem *modem = NULL;
- GError *error = NULL;
- GSList *iter;
-
- /* No more plugins to try */
- if (info->best_plugin) {
+ best_plugin = mm_plugin_manager_find_port_support_finish (plugin_manager,
+ result,
+ &error);
+ if (!best_plugin) {
MMModem *existing;
- existing = g_hash_table_lookup (priv->modems, info->physdev_path);
-
- /* Create the modem */
- modem = mm_plugin_grab_port (info->best_plugin, info->subsys, info->name, existing, &error);
- if (modem) {
- guint32 modem_type = MM_MODEM_TYPE_UNKNOWN;
- const char *type_name = "UNKNOWN";
- char *device;;
-
- g_object_get (G_OBJECT (modem), MM_MODEM_TYPE, &modem_type, NULL);
- if (modem_type == MM_MODEM_TYPE_GSM)
- type_name = "GSM";
- else if (modem_type == MM_MODEM_TYPE_CDMA)
- type_name = "CDMA";
-
- device = mm_modem_get_device (modem);
- mm_info ("(%s): %s modem %s claimed port %s",
- mm_plugin_get_name (info->best_plugin),
- type_name,
- device,
- info->name);
- g_free (device);
-
- add_modem (info->manager, modem, info->best_plugin);
+ if (error) {
+ mm_dbg ("(%s/%s): error checking support: '%s'",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device),
+ error->message);
+ g_error_free (error);
} else {
- mm_warn ("plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
- mm_plugin_get_name (info->best_plugin),
- info->subsys,
- info->name,
- error ? error->code : -1,
- (error && error->message) ? error->message : "(unknown)");
- modem = existing;
+ mm_dbg ("(%s/%s): not supported by any plugin",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device));
}
- }
- /* Tell each plugin to clean up any outstanding supports task */
- for (iter = info->plugins; iter; iter = g_slist_next (iter))
- mm_plugin_supports_port_cancel (MM_PLUGIN (iter->data),
- info->subsys,
- info->name);
- g_slist_free (info->plugins);
- info->cur_plugin = info->plugins = NULL;
+ /* So we couldn't get a plugin for this port, we should anyway check if
+ * there is already an existing modem for the physical device, and if
+ * so, check if it can already be exported. */
+ existing = find_modem_for_device (
+ ctx->manager,
+ g_udev_device_get_sysfs_path (ctx->physical_device));
+ if (existing)
+ check_export_modem (ctx->manager, existing);
+ } else {
+ mm_dbg ("(%s/%s): found plugin '%s' giving best support",
+ g_udev_device_get_subsystem (ctx->device),
+ g_udev_device_get_name (ctx->device),
+ mm_plugin_get_name ((MMPlugin *)best_plugin));
- supports_cleanup (info->manager, info->subsys, info->name, modem);
- return FALSE;
+ grab_port (ctx->manager,
+ best_plugin,
+ ctx->device,
+ ctx->physical_device);
+ }
+
+ find_port_support_context_free (ctx);
}
static void
-supports_callback (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- guint32 level,
- gpointer user_data)
+grab_port (MMManager *manager,
+ MMPlugin *plugin,
+ GUdevDevice *device,
+ GUdevDevice *physical_device)
{
- SupportsInfo *info = user_data;
- MMPlugin *next_plugin = NULL;
+ MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
+ MMModem *modem = NULL;
+ GError *error = NULL;
+ /* GSList *iter; */
MMModem *existing;
- /* 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;
- }
+ existing = g_hash_table_lookup (priv->modems,
+ g_udev_device_get_sysfs_path (physical_device));
- /* If there's already a modem for this port's physical device, stop asking
- * plugins because the same plugin that owns the modem gets this port no
- * matter what.
- */
- existing = find_modem_for_device (info->manager, info->physdev_path);
- if (existing) {
- MMPlugin *existing_plugin;
-
- existing_plugin = MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG));
- g_assert (existing_plugin);
-
- if (plugin == existing_plugin) {
- if (level == 0) {
- /* If the plugin that just completed the support check claims not to
- * support this port, but this plugin is clearly the right plugin
- * since it claimed this port's physical modem, just drop the port.
- */
- mm_dbg ("(%s/%s): ignoring port unsupported by physical modem's plugin",
- info->subsys, info->name);
- supports_cleanup (info->manager, info->subsys, info->name, existing);
- return;
- }
+ /* Create the modem */
+ modem = mm_plugin_grab_port (plugin,
+ g_udev_device_get_subsystem (device),
+ g_udev_device_get_name (device),
+ existing,
+ &error);
+ if (modem) {
+ guint32 modem_type = MM_MODEM_TYPE_UNKNOWN;
+ const gchar *type_name = "UNKNOWN";
+ gchar *modem_device;
+
+ g_object_get (G_OBJECT (modem), MM_MODEM_TYPE, &modem_type, NULL);
+ if (modem_type == MM_MODEM_TYPE_GSM)
+ type_name = "GSM";
+ else if (modem_type == MM_MODEM_TYPE_CDMA)
+ type_name = "CDMA";
+
+ modem_device = mm_modem_get_device (modem);
+ mm_info ("(%s): %s modem %s claimed port %s",
+ mm_plugin_get_name (plugin),
+ type_name,
+ modem_device,
+ g_udev_device_get_name (device));
+ g_free (modem_device);
- /* Otherwise, this port was supported by the plugin that owns the
- * port's physical modem, so we stop the supports checks anyway.
- */
- next_plugin = NULL;
- } else if (info->best_plugin != existing_plugin) {
- /* If this port hasn't yet been handled by the right plugin, stop
- * asking all other plugins if they support this port, just let the
- * plugin that handles this port's physical device see if it
- * supports it.
- */
- next_plugin = existing_plugin;
- } else {
- mm_dbg ("(%s/%s): plugin %p (%s) existing %p (%s) info->best %p (%s)",
- info->subsys, info->name,
- plugin,
- plugin ? mm_plugin_get_name (plugin) : "none",
- existing_plugin,
- existing_plugin ? mm_plugin_get_name (existing_plugin) : "none",
- info->best_plugin,
- info->best_plugin ? mm_plugin_get_name (info->best_plugin) : "none");
- g_assert_not_reached ();
- }
+ add_modem (manager, modem, plugin);
} else {
- info->cur_plugin = g_slist_next (info->cur_plugin);
- if (info->cur_plugin)
- next_plugin = MM_PLUGIN (info->cur_plugin->data);
- }
-
- /* Don't bother with Generic if some other plugin already supports this port */
- if (next_plugin) {
- const char *next_name = mm_plugin_get_name (next_plugin);
-
- if (info->best_plugin && !strcmp (next_name, MM_PLUGIN_GENERIC_NAME))
- next_plugin = NULL;
+ mm_warn ("plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
+ mm_plugin_get_name (plugin),
+ g_udev_device_get_subsystem (device),
+ g_udev_device_get_name (device),
+ error ? error->code : -1,
+ (error && error->message) ? error->message : "(unknown)");
+ modem = existing;
}
- if (next_plugin) {
- /* Try the next plugin */
- mm_plugin_supports_port (next_plugin,
- info->subsys,
- info->name,
- info->physdev_path,
- existing,
- (GAsyncReadyCallback)supports_port_ready_cb,
- info);
- } else {
- /* All done; let the best modem grab the port */
- info->done_id = g_idle_add (do_grab_port, info);
- }
+ check_export_modem (manager, modem);
}
static GUdevDevice *
@@ -827,18 +494,13 @@ device_added (MMManager *manager, GUdevDevice *device)
{
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
const char *subsys, *name, *physdev_path, *physdev_subsys;
- SupportsInfo *info;
- char *key;
- gboolean found, is_candidate;
+ gboolean is_candidate;
GUdevDevice *physdev = NULL;
MMPlugin *plugin;
MMModem *existing;
g_return_if_fail (device != NULL);
- if (!g_slist_length (priv->plugins))
- return;
-
subsys = g_udev_device_get_subsystem (device);
name = g_udev_device_get_name (device);
@@ -860,11 +522,6 @@ device_added (MMManager *manager, GUdevDevice *device)
if (find_modem_for_port (manager, subsys, name))
return;
- key = get_key (subsys, name);
- found = !!g_hash_table_lookup (priv->supports, key);
- if (found)
- goto out;
-
/* Find the port's physical device's sysfs path. This is the kernel device
* that "owns" all the ports of the device, like the USB device or the PCI
* device the provides each tty or network port.
@@ -905,47 +562,51 @@ device_added (MMManager *manager, GUdevDevice *device)
goto out;
}
- /* Success; now ask plugins if they can handle this port */
- info = supports_info_new (manager, subsys, name, physdev_path);
- g_hash_table_insert (priv->supports, g_strdup (key), info);
+ /* Already launched the same port support check? */
+ if (mm_plugin_manager_is_finding_port_support (priv->plugin_manager,
+ subsys,
+ name,
+ physdev_path)) {
+ mm_dbg ("(%s/%s): support check already requested in port", subsys, name);
+ goto out;
+ }
/* If this port's physical modem is already owned by a plugin, don't bother
* asking all plugins whether they support this port, just let the owning
* plugin check if it supports the port.
*/
- plugin = MM_PLUGIN (info->cur_plugin->data);
existing = find_modem_for_device (manager, physdev_path);
- if (existing)
- plugin = MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG));
-
- mm_plugin_supports_port (plugin,
- info->subsys,
- info->name,
- info->physdev_path,
- existing,
- (GAsyncReadyCallback)supports_port_ready_cb,
- info);
+ plugin = (existing ?
+ MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG)) :
+ NULL);
+
+ /* Launch supports check in the Plugin Manager */
+ mm_plugin_manager_find_port_support (
+ priv->plugin_manager,
+ subsys,
+ name,
+ physdev_path,
+ plugin,
+ existing,
+ (GAsyncReadyCallback)find_port_support_ready_cb,
+ find_port_support_context_new (manager,
+ device,
+ physdev));
out:
if (physdev)
g_object_unref (physdev);
- g_free (key);
}
static void
device_removed (MMManager *manager, GUdevDevice *device)
{
- MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
MMModem *modem;
const char *subsys, *name;
- char *key, *modem_device;
- SupportsInfo *info;
+ gchar *modem_device;
g_return_if_fail (device != NULL);
- if (!g_slist_length (priv->plugins))
- return;
-
subsys = g_udev_device_get_subsystem (device);
name = g_udev_device_get_name (device);
@@ -978,19 +639,8 @@ device_removed (MMManager *manager, GUdevDevice *device)
}
}
- /* Maybe a plugin is checking whether or not the port is supported */
- key = get_key (subsys, name);
- info = g_hash_table_lookup (priv->supports, key);
-
- if (info) {
- if (info->plugins)
- mm_plugin_supports_port_cancel (MM_PLUGIN (info->plugins->data),
- subsys,
- name);
- g_hash_table_remove (priv->supports, key);
- }
-
- g_free (key);
+ /* Maybe a plugin is checking whether or not the port is supported.
+ * TODO: Cancel every possible supports check in this port. */
}
static void
@@ -1180,9 +830,6 @@ mm_manager_init (MMManager *manager)
priv->authp = mm_auth_provider_get ();
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
- load_plugins (manager);
-
- priv->supports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) supports_info_free);
priv->udev = g_udev_client_new (subsys);
g_assert (priv->udev);
@@ -1196,15 +843,14 @@ finalize (GObject *object)
mm_auth_provider_cancel_for_owner (priv->authp, object);
- g_hash_table_destroy (priv->supports);
g_hash_table_destroy (priv->modems);
- g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
- g_slist_free (priv->plugins);
-
if (priv->udev)
g_object_unref (priv->udev);
+ if (priv->plugin_manager)
+ g_object_unref (priv->plugin_manager);
+
if (priv->connection)
dbus_g_connection_unref (priv->connection);