aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-03-30 14:50:40 -0700
committerDan Williams <dcbw@redhat.com>2010-03-30 14:50:40 -0700
commit720e38aec0a50aa2136f01b7f3620a4e261c0406 (patch)
tree06dbd68d467b4652f6de97c9fe1b70b02b830a71 /src
parent39326f249105b7d71c63125f29e3bee2143a82d2 (diff)
core: move physical device checking into the manager
It turns out that the manager needs to know about the physical device so we can prevent multiple plugins from claiming ports on the same modem.
Diffstat (limited to 'src')
-rw-r--r--src/mm-manager.c109
-rw-r--r--src/mm-plugin-base.c77
-rw-r--r--src/mm-plugin-base.h9
-rw-r--r--src/mm-plugin.c9
-rw-r--r--src/mm-plugin.h2
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);