diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-manager.c | 109 | ||||
-rw-r--r-- | src/mm-plugin-base.c | 77 | ||||
-rw-r--r-- | src/mm-plugin-base.h | 9 | ||||
-rw-r--r-- | src/mm-plugin.c | 9 | ||||
-rw-r--r-- | src/mm-plugin.h | 2 |
5 files changed, 118 insertions, 88 deletions
diff --git a/src/mm-manager.c b/src/mm-manager.c index d838fa1a..5a85f02a 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -299,6 +299,7 @@ typedef struct { MMManager *manager; char *subsys; char *name; + char *physdev_path; GSList *plugins; GSList *cur_plugin; guint defer_id; @@ -309,7 +310,10 @@ typedef struct { } SupportsInfo; static SupportsInfo * -supports_info_new (MMManager *self, const char *subsys, const char *name) +supports_info_new (MMManager *self, + const char *subsys, + const char *name, + const char *physdev_path) { MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self); SupportsInfo *info; @@ -318,6 +322,7 @@ supports_info_new (MMManager *self, const char *subsys, const char *name) 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; @@ -358,8 +363,6 @@ static void supports_callback (MMPlugin *plugin, static void try_supports_port (MMManager *manager, MMPlugin *plugin, - const char *subsys, - const char *name, SupportsInfo *info); static gboolean @@ -370,8 +373,6 @@ supports_defer_timeout (gpointer user_data) g_debug ("(%s): re-checking support...", info->name); try_supports_port (info->manager, MM_PLUGIN (info->cur_plugin->data), - info->subsys, - info->name, info); return FALSE; } @@ -379,23 +380,28 @@ supports_defer_timeout (gpointer user_data) static void try_supports_port (MMManager *manager, MMPlugin *plugin, - const char *subsys, - const char *name, SupportsInfo *info) { MMPluginSupportsResult result; - result = mm_plugin_supports_port (plugin, subsys, name, supports_callback, info); + result = mm_plugin_supports_port (plugin, + info->subsys, + info->name, + info->physdev_path, + supports_callback, + info); switch (result) { 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, subsys, name, 0, info); + supports_callback (plugin, info->subsys, info->name, 0, info); break; case MM_PLUGIN_SUPPORTS_PORT_DEFER: - g_debug ("(%s): (%s) deferring support check", mm_plugin_get_name (plugin), name); + g_debug ("(%s): (%s) deferring support check", + mm_plugin_get_name (plugin), + info->name); if (info->defer_id) g_source_remove (info->defer_id); @@ -494,21 +500,59 @@ supports_callback (MMPlugin *plugin, if (next_plugin) { /* Try the next plugin */ - try_supports_port (info->manager, next_plugin, info->subsys, info->name, info); + try_supports_port (info->manager, next_plugin, info); } else { /* All done; let the best modem grab the port */ info->done_id = g_idle_add (do_grab_port, info); } } +static GUdevDevice * +find_physical_device (GUdevDevice *child) +{ + GUdevDevice *iter, *old = NULL; + GUdevDevice *physdev = NULL; + const char *subsys, *type; + guint32 i = 0; + gboolean is_usb = FALSE, is_pci = FALSE; + + g_return_val_if_fail (child != NULL, NULL); + + iter = g_object_ref (child); + while (iter && i++ < 8) { + subsys = g_udev_device_get_subsystem (iter); + if (subsys) { + if (is_usb || !strcmp (subsys, "usb")) { + is_usb = TRUE; + type = g_udev_device_get_devtype (iter); + if (type && !strcmp (type, "usb_device")) { + physdev = iter; + break; + } + } else if (is_pci || !strcmp (subsys, "pci")) { + is_pci = TRUE; + physdev = iter; + break; + } + } + + old = iter; + iter = g_udev_device_get_parent (old); + g_object_unref (old); + } + + return physdev; +} + static void device_added (MMManager *manager, GUdevDevice *device) { MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager); - const char *subsys, *name; + const char *subsys, *name, *physdev_path; SupportsInfo *info; char *key; gboolean found; + GUdevDevice *physdev = NULL; g_return_if_fail (device != NULL); @@ -527,15 +571,44 @@ device_added (MMManager *manager, GUdevDevice *device) key = get_key (subsys, name); found = !!g_hash_table_lookup (priv->supports, key); - if (found) { - g_free (key); - return; + 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. + */ + physdev = find_physical_device (device); + if (!physdev) { + /* Warn about it, but filter out some common ports that we know don't have + * anything to do with mobile broadband. + */ + if ( strcmp (name, "console") + && strcmp (name, "ptmx") + && strcmp (name, "lo") + && strcmp (name, "tty") + && !strstr (name, "virbr")) + g_debug ("(%s/%s): could not get port's parent device", subsys, name); + + goto out; + } + + physdev_path = g_udev_device_get_sysfs_path (physdev); + if (!physdev_path) { + g_debug ("(%s/%s): could not get port's parent device sysfs path", subsys, name); + goto out; } - info = supports_info_new (manager, subsys, name); - g_hash_table_insert (priv->supports, key, info); + /* 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); + + try_supports_port (manager, MM_PLUGIN (info->cur_plugin->data), info); - try_supports_port (manager, MM_PLUGIN (info->cur_plugin->data), subsys, name, info); +out: + if (physdev) + g_object_unref (physdev); + g_free (key); } static void diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c index 10204366..a8784be4 100644 --- a/src/mm-plugin-base.c +++ b/src/mm-plugin-base.c @@ -91,7 +91,7 @@ G_DEFINE_TYPE (MMPluginBaseSupportsTask, mm_plugin_base_supports_task, G_TYPE_OB typedef struct { MMPluginBase *plugin; GUdevDevice *port; - GUdevDevice *physdev; + char *physdev_path; char *driver; guint open_id; @@ -119,7 +119,7 @@ typedef struct { static MMPluginBaseSupportsTask * supports_task_new (MMPluginBase *self, GUdevDevice *port, - GUdevDevice *physdev, + const char *physdev_path, const char *driver, MMSupportsPortResultFunc callback, gpointer callback_data) @@ -130,7 +130,7 @@ supports_task_new (MMPluginBase *self, g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), NULL); g_return_val_if_fail (port != NULL, NULL); - g_return_val_if_fail (physdev != NULL, NULL); + g_return_val_if_fail (physdev_path != NULL, NULL); g_return_val_if_fail (driver != NULL, NULL); g_return_val_if_fail (callback != NULL, NULL); @@ -139,7 +139,7 @@ supports_task_new (MMPluginBase *self, priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); priv->plugin = self; priv->port = g_object_ref (port); - priv->physdev = g_object_ref (physdev); + priv->physdev_path = g_strdup (physdev_path); priv->driver = g_strdup (driver); priv->callback = callback; priv->callback_data = callback_data; @@ -165,13 +165,13 @@ mm_plugin_base_supports_task_get_port (MMPluginBaseSupportsTask *task) return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->port; } -GUdevDevice * -mm_plugin_base_supports_task_get_physdev (MMPluginBaseSupportsTask *task) +const char * +mm_plugin_base_supports_task_get_physdev_path (MMPluginBaseSupportsTask *task) { g_return_val_if_fail (task != NULL, NULL); g_return_val_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task), NULL); - return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->physdev; + return MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task)->physdev_path; } const char * @@ -255,7 +255,7 @@ supports_task_dispose (GObject *object) mm_serial_port_flash_cancel (MM_SERIAL_PORT (priv->probe_port)); g_object_unref (priv->port); - g_object_unref (priv->physdev); + g_free (priv->physdev_path); g_free (priv->driver); g_free (priv->probe_resp); g_clear_error (&(priv->probe_error)); @@ -1037,58 +1037,21 @@ get_driver_name (GUdevDevice *device) return ret; } -static GUdevDevice * -real_find_physical_device (MMPluginBase *plugin, GUdevDevice *child) -{ - GUdevDevice *iter, *old = NULL; - GUdevDevice *physdev = NULL; - const char *subsys, *type; - guint32 i = 0; - gboolean is_usb = FALSE, is_pci = FALSE; - - g_return_val_if_fail (child != NULL, NULL); - - iter = g_object_ref (child); - while (iter && i++ < 8) { - subsys = g_udev_device_get_subsystem (iter); - if (subsys) { - if (is_usb || !strcmp (subsys, "usb")) { - is_usb = TRUE; - type = g_udev_device_get_devtype (iter); - if (type && !strcmp (type, "usb_device")) { - physdev = iter; - break; - } - } else if (is_pci || !strcmp (subsys, "pci")) { - is_pci = TRUE; - physdev = iter; - break; - } - } - - old = iter; - iter = g_udev_device_get_parent (old); - g_object_unref (old); - } - - return physdev; -} - static MMPluginSupportsResult supports_port (MMPlugin *plugin, const char *subsys, const char *name, + const char *physdev_path, MMSupportsPortResultFunc callback, gpointer callback_data) { MMPluginBase *self = MM_PLUGIN_BASE (plugin); MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self); - GUdevDevice *port = NULL, *physdev = NULL; + GUdevDevice *port = NULL; char *driver = NULL, *key = NULL; MMPluginBaseSupportsTask *task; MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED; MMModem *existing; - const char *master_path; key = get_key (subsys, name); task = g_hash_table_lookup (priv->tasks, key); @@ -1101,21 +1064,16 @@ supports_port (MMPlugin *plugin, if (!port) goto out; - physdev = MM_PLUGIN_BASE_GET_CLASS (self)->find_physical_device (self, port); - if (!physdev) - goto out; - driver = get_driver_name (port); if (!driver) goto out; - task = supports_task_new (self, port, physdev, driver, callback, callback_data); + task = supports_task_new (self, port, physdev_path, driver, callback, callback_data); g_assert (task); g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task)); /* Help the plugin out a bit by finding an existing modem for this port */ - master_path = g_udev_device_get_sysfs_path (physdev); - existing = g_hash_table_lookup (priv->modems, master_path); + existing = g_hash_table_lookup (priv->modems, physdev_path); result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task); if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) { @@ -1127,8 +1085,6 @@ supports_port (MMPlugin *plugin, g_object_unref (task); out: - if (physdev) - g_object_unref (physdev); if (port) g_object_unref (port); g_free (key); @@ -1169,7 +1125,7 @@ grab_port (MMPlugin *plugin, MMPluginBaseSupportsTask *task; char *key; MMModem *existing = NULL, *modem = NULL; - const char *master_path; + const char *physdev_path; key = get_key (subsys, name); task = g_hash_table_lookup (priv->tasks, key); @@ -1179,13 +1135,13 @@ grab_port (MMPlugin *plugin, } /* Help the plugin out a bit by finding an existing modem for this port */ - master_path = g_udev_device_get_sysfs_path (mm_plugin_base_supports_task_get_physdev (task)); - existing = g_hash_table_lookup (priv->modems, master_path); + physdev_path = mm_plugin_base_supports_task_get_physdev_path (task); + existing = g_hash_table_lookup (priv->modems, physdev_path); /* Let the modem grab the port */ modem = MM_PLUGIN_BASE_GET_CLASS (self)->grab_port (self, existing, task, error); if (modem && !existing) { - g_hash_table_insert (priv->modems, g_strdup (master_path), modem); + g_hash_table_insert (priv->modems, g_strdup (physdev_path), modem); g_object_weak_ref (G_OBJECT (modem), modem_destroyed, self); } @@ -1277,7 +1233,6 @@ mm_plugin_base_class_init (MMPluginBaseClass *klass) g_type_class_add_private (object_class, sizeof (MMPluginBasePrivate)); - klass->find_physical_device = real_find_physical_device; klass->handle_probe_response = real_handle_probe_response; /* Virtual methods */ diff --git a/src/mm-plugin-base.h b/src/mm-plugin-base.h index 555113dc..fd3e7368 100644 --- a/src/mm-plugin-base.h +++ b/src/mm-plugin-base.h @@ -60,7 +60,7 @@ MMPlugin *mm_plugin_base_supports_task_get_plugin (MMPluginBaseSupportsTask *tas GUdevDevice *mm_plugin_base_supports_task_get_port (MMPluginBaseSupportsTask *task); -GUdevDevice *mm_plugin_base_supports_task_get_physdev (MMPluginBaseSupportsTask *task); +const char *mm_plugin_base_supports_task_get_physdev_path (MMPluginBaseSupportsTask *task); const char *mm_plugin_base_supports_task_get_driver (MMPluginBaseSupportsTask *task); @@ -108,13 +108,6 @@ struct _MMPluginBaseClass { void (*cancel_task) (MMPluginBase *plugin, MMPluginBaseSupportsTask *task); - /* Find a the physical device of a port, ie the USB or PCI or whatever - * "master" device that owns the port. The GUdevDevice object returned - * will be unref-ed by the caller. - */ - GUdevDevice * (*find_physical_device) (MMPluginBase *plugin, - GUdevDevice *port); - void (*handle_probe_response) (MMPluginBase *plugin, MMPluginBaseSupportsTask *task, const char *command, diff --git a/src/mm-plugin.c b/src/mm-plugin.c index 830f2d66..cc58e621 100644 --- a/src/mm-plugin.c +++ b/src/mm-plugin.c @@ -28,15 +28,22 @@ MMPluginSupportsResult mm_plugin_supports_port (MMPlugin *plugin, const char *subsys, const char *name, + const char *physdev_path, MMSupportsPortResultFunc callback, gpointer user_data) { g_return_val_if_fail (MM_IS_PLUGIN (plugin), FALSE); g_return_val_if_fail (subsys != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (physdev_path != NULL, FALSE); g_return_val_if_fail (callback != NULL, FALSE); - return MM_PLUGIN_GET_INTERFACE (plugin)->supports_port (plugin, subsys, name, callback, user_data); + return MM_PLUGIN_GET_INTERFACE (plugin)->supports_port (plugin, + subsys, + name, + physdev_path, + callback, + user_data); } void diff --git a/src/mm-plugin.h b/src/mm-plugin.h index d1e85b6a..40419d41 100644 --- a/src/mm-plugin.h +++ b/src/mm-plugin.h @@ -70,6 +70,7 @@ struct _MMPlugin { MMPluginSupportsResult (*supports_port) (MMPlugin *self, const char *subsys, const char *name, + const char *physdev_path, MMSupportsPortResultFunc callback, gpointer user_data); @@ -104,6 +105,7 @@ const char *mm_plugin_get_name (MMPlugin *plugin); MMPluginSupportsResult mm_plugin_supports_port (MMPlugin *plugin, const char *subsys, const char *name, + const char *physdev_path, MMSupportsPortResultFunc callback, gpointer user_data); |