aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-manager.c75
-rw-r--r--src/mm-plugin-base.c176
-rw-r--r--src/mm-plugin.c55
-rw-r--r--src/mm-plugin.h56
4 files changed, 244 insertions, 118 deletions
diff --git a/src/mm-manager.c b/src/mm-manager.c
index 5dfb86d7..8e0cff06 100644
--- a/src/mm-manager.c
+++ b/src/mm-manager.c
@@ -486,10 +486,9 @@ static void supports_callback (MMPlugin *plugin,
guint32 level,
gpointer user_data);
-static void try_supports_port (MMManager *manager,
- MMPlugin *plugin,
- MMModem *existing,
- SupportsInfo *info);
+static void supports_port_ready_cb (MMPlugin *plugin,
+ GAsyncResult *result,
+ SupportsInfo *info);
static gboolean
supports_defer_timeout (gpointer user_data)
@@ -500,30 +499,43 @@ supports_defer_timeout (gpointer user_data)
existing = find_modem_for_device (info->manager, info->physdev_path);
mm_dbg ("(%s): re-checking support...", info->name);
- try_supports_port (info->manager,
- MM_PLUGIN (info->cur_plugin->data),
- existing,
- info);
+ 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
-try_supports_port (MMManager *manager,
- MMPlugin *plugin,
- MMModem *existing,
- SupportsInfo *info)
+supports_port_ready_cb (MMPlugin *plugin,
+ GAsyncResult *result,
+ SupportsInfo *info)
{
- MMPluginSupportsResult result;
-
- result = mm_plugin_supports_port (plugin,
- info->subsys,
- info->name,
- info->physdev_path,
- existing,
- supports_callback,
- 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 (result) {
+ 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.
@@ -541,7 +553,8 @@ try_supports_port (MMManager *manager,
info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
break;
case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
- default:
+ /* This should never happen at this level */
+ g_warn_if_reached ();
break;
}
}
@@ -730,7 +743,13 @@ supports_callback (MMPlugin *plugin,
if (next_plugin) {
/* Try the next plugin */
- try_supports_port (info->manager, next_plugin, existing, info);
+ 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);
@@ -895,7 +914,13 @@ device_added (MMManager *manager, GUdevDevice *device)
if (existing)
plugin = MM_PLUGIN (g_object_get_data (G_OBJECT (existing), MANAGER_PLUGIN_TAG));
- try_supports_port (manager, plugin, existing, info);
+ mm_plugin_supports_port (plugin,
+ info->subsys,
+ info->name,
+ info->physdev_path,
+ existing,
+ (GAsyncReadyCallback)supports_port_ready_cb,
+ info);
out:
if (physdev)
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index c4b514bb..24ec9deb 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -150,6 +150,11 @@ G_DEFINE_TYPE (MMPluginBaseSupportsTask, mm_plugin_base_supports_task, G_TYPE_OB
#define MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, MMPluginBaseSupportsTaskPrivate))
typedef struct {
+ MMPluginSupportsResult result;
+ guint support_level;
+} SupportsPortResult;
+
+typedef struct {
char *command;
guint32 tries;
guint32 delay_seconds;
@@ -181,28 +186,23 @@ typedef struct {
GSList *custom;
GSList *cur_custom; /* Pointer to current custom init command */
- MMSupportsPortResultFunc callback;
- gpointer callback_data;
+ GSimpleAsyncResult *async_result;
} MMPluginBaseSupportsTaskPrivate;
+static SupportsPortResult *supports_port_result_new (MMPluginSupportsResult result,
+ guint support_level);
+static void supports_port_result_free (SupportsPortResult *spr);
+
static MMPluginBaseSupportsTask *
supports_task_new (MMPluginBase *self,
GUdevDevice *port,
const char *physdev_path,
const char *driver,
- MMSupportsPortResultFunc callback,
- gpointer callback_data)
+ GSimpleAsyncResult *result)
{
MMPluginBaseSupportsTask *task;
MMPluginBaseSupportsTaskPrivate *priv;
- 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_path != NULL, NULL);
- g_return_val_if_fail (driver != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
-
task = (MMPluginBaseSupportsTask *) g_object_new (MM_TYPE_PLUGIN_BASE_SUPPORTS_TASK, NULL);
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
@@ -210,8 +210,7 @@ supports_task_new (MMPluginBase *self,
priv->port = g_object_ref (port);
priv->physdev_path = g_strdup (physdev_path);
priv->driver = g_strdup (driver);
- priv->callback = callback;
- priv->callback_data = callback_data;
+ priv->async_result = g_object_ref (result);
return task;
}
@@ -316,27 +315,24 @@ mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
guint32 level)
{
MMPluginBaseSupportsTaskPrivate *priv;
- const char *subsys, *name;
- g_return_if_fail (task != NULL);
g_return_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task));
priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
- g_return_if_fail (priv->callback != NULL);
if (priv->full_id) {
g_source_remove (priv->full_id);
priv->full_id = 0;
}
- subsys = g_udev_device_get_subsystem (priv->port);
- name = g_udev_device_get_name (priv->port);
-
- priv->callback (MM_PLUGIN (priv->plugin), subsys, name, level, priv->callback_data);
-
- /* Clear out the callback, it shouldn't be called more than once */
- priv->callback = NULL;
- priv->callback_data = NULL;
+ g_simple_async_result_set_op_res_gpointer (
+ priv->async_result,
+ supports_port_result_new ((level > 0 ?
+ MM_PLUGIN_SUPPORTS_PORT_SUPPORTED :
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED),
+ level),
+ (GDestroyNotify)supports_port_result_free);
+ g_simple_async_result_complete (priv->async_result);
}
void
@@ -1306,71 +1302,148 @@ device_file_exists(const char *name)
return (0 == result) ? TRUE : FALSE;
}
+static SupportsPortResult *
+supports_port_result_new (MMPluginSupportsResult result,
+ guint support_level)
+{
+ SupportsPortResult *spr;
+
+ spr = g_malloc (sizeof (SupportsPortResult));
+ spr->result = result;
+ spr->support_level = support_level;
+ return spr;
+}
+
+static void
+supports_port_result_free (SupportsPortResult *spr)
+{
+ g_free (spr);
+}
+
static MMPluginSupportsResult
+supports_port_finish (MMPlugin *self,
+ GAsyncResult *result,
+ guint *level,
+ GError **error)
+{
+ SupportsPortResult *spr;
+
+ g_return_val_if_fail (MM_IS_PLUGIN (self),
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result),
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+
+ /* Propagate error, if any */
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error)) {
+ return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ }
+
+ spr = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ *level = spr->support_level;
+ return spr->result;
+}
+
+static void
supports_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- const char *physdev_path,
+ const gchar *subsys,
+ const gchar *name,
+ const gchar *physdev_path,
MMModem *existing,
- MMSupportsPortResultFunc callback,
- gpointer callback_data)
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
+ MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
MMPluginBase *self = MM_PLUGIN_BASE (plugin);
MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
GUdevDevice *port = NULL;
- char *driver = NULL, *key = NULL;
+ gchar *driver = NULL;
+ gchar *key = NULL;
MMPluginBaseSupportsTask *task;
- MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- int idx;
+ gint idx;
+ GSimpleAsyncResult *async_result;
+
+ async_result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ supports_port);
+ /* Lookup task, there shouldn't be any */
key = get_key (subsys, name);
task = g_hash_table_lookup (priv->tasks, key);
if (task) {
- g_free (key);
- g_return_val_if_fail (task == NULL, MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+ g_warn_if_reached ();
+ goto unsupported;
}
- port = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
+ /* Get port device */
+ port = g_udev_client_query_by_subsystem_and_name (priv->client,
+ subsys,
+ name);
if (!port)
- goto out;
+ goto unsupported;
- // Detect any modems accessible through the list of virtual ports
+ /* Detect any modems accessible through the list of virtual ports */
for (idx = 0; virtual_port[idx]; idx++) {
if (strcmp(name, virtual_port[idx]))
continue;
if (!device_file_exists(virtual_port[idx]))
continue;
- task = supports_task_new (self, port, physdev_path, "virtual", callback, callback_data);
- g_assert (task);
- g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));
+ task = supports_task_new (self,
+ port,
+ physdev_path,
+ "virtual",
+ async_result);
goto find_plugin;
}
driver = get_driver_name (port);
if (!driver)
- goto out;
+ goto unsupported;
- 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));
+ /* Create new supports task for this port */
+ task = supports_task_new (self,
+ port,
+ physdev_path,
+ driver,
+ async_result);
find_plugin:
- result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task);
- if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
- /* If the plugin doesn't support the port at all, the supports task is
- * not needed.
- */
- g_hash_table_remove (priv->tasks, key);
+ /* Keep track of the task */
+ g_hash_table_insert (priv->tasks,
+ g_strdup (key),
+ g_object_ref (task));
+
+ /* Let the specific plugin check port support */
+ result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self,
+ existing,
+ task);
+ if (result == MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
+ /* It will really be asynchronous */
+ goto out;
}
+
+ /* If the plugin doesn't support the port at all, the supports task is
+ * not needed.
+ */
+ g_hash_table_remove (priv->tasks, key);
g_object_unref (task);
+unsupported:
+ /* Set the result of the asynchronous method just here */
+ g_simple_async_result_set_op_res_gpointer (
+ async_result,
+ supports_port_result_new (result, 0),
+ (GDestroyNotify)supports_port_result_free);
+ g_simple_async_result_complete_in_idle (async_result);
+
out:
if (port)
g_object_unref (port);
g_free (key);
g_free (driver);
- return result;
+ g_object_unref (async_result);
}
static void
@@ -1434,6 +1507,7 @@ plugin_init (MMPlugin *plugin_class)
plugin_class->get_name = get_name;
plugin_class->get_sort_last = get_sort_last;
plugin_class->supports_port = supports_port;
+ plugin_class->supports_port_finish = supports_port_finish;
plugin_class->cancel_supports_port = cancel_supports_port;
plugin_class->grab_port = grab_port;
}
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index 167af474..1c584a3e 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -32,28 +32,45 @@ mm_plugin_get_sort_last (const MMPlugin *plugin)
return MM_PLUGIN_GET_INTERFACE (plugin)->get_sort_last (plugin);
}
-MMPluginSupportsResult
-mm_plugin_supports_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- const char *physdev_path,
+void
+mm_plugin_supports_port (MMPlugin *self,
+ const gchar *subsys,
+ const gchar *name,
+ const gchar *physdev_path,
MMModem *existing,
- MMSupportsPortResultFunc callback,
+ GAsyncReadyCallback 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,
- physdev_path,
- existing,
- callback,
- user_data);
+ g_return_if_fail (MM_IS_PLUGIN (self));
+ g_return_if_fail (subsys != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (physdev_path != NULL);
+ g_return_if_fail (callback != NULL);
+
+ MM_PLUGIN_GET_INTERFACE (self)->supports_port (self,
+ subsys,
+ name,
+ physdev_path,
+ existing,
+ callback,
+ user_data);
+}
+
+MMPluginSupportsResult
+mm_plugin_supports_port_finish (MMPlugin *self,
+ GAsyncResult *result,
+ guint *level,
+ GError **error)
+{
+ g_return_val_if_fail (MM_IS_PLUGIN (self),
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result),
+ MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+
+ return MM_PLUGIN_GET_INTERFACE (self)->supports_port_finish (self,
+ result,
+ level,
+ error);
}
void
diff --git a/src/mm-plugin.h b/src/mm-plugin.h
index 07e3ee09..39598de8 100644
--- a/src/mm-plugin.h
+++ b/src/mm-plugin.h
@@ -18,6 +18,8 @@
#define MM_PLUGIN_H
#include <glib-object.h>
+#include <gio/gio.h>
+
#include <mm-modem.h>
#define MM_PLUGIN_GENERIC_NAME "Generic"
@@ -48,7 +50,8 @@ typedef void (*MMSupportsPortResultFunc) (MMPlugin *plugin,
typedef enum {
MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0,
MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS,
- MM_PLUGIN_SUPPORTS_PORT_DEFER
+ MM_PLUGIN_SUPPORTS_PORT_DEFER,
+ MM_PLUGIN_SUPPORTS_PORT_SUPPORTED
} MMPluginSupportsResult;
struct _MMPlugin {
@@ -63,22 +66,24 @@ struct _MMPlugin {
gboolean (*get_sort_last) (const MMPlugin *self);
/* Check whether a plugin supports a particular modem port, and what level
- * of support the plugin has for the device. If the plugin can immediately
- * determine whether a port is unsupported, it should return
- * FALSE. Otherwise, if the plugin needs to perform additional operations
- * (ie, probing) to determine the level of support or additional details
- * about a port, it should queue that operation (but *not* block on the
- * result) and return TRUE to indicate the operation is ongoing. When the
- * operation is finished or the level of support is known, the plugin should
- * call the provided callback and pass that callback the provided user_data.
+ * of support the plugin has for the device.
+ * The check is done always asynchronously. When the result of the check is
+ * ready, the passed callback will be called, and the result will be ready
+ * to get retrieved with supports_port_finish().
*/
- MMPluginSupportsResult (*supports_port) (MMPlugin *self,
- const char *subsys,
- const char *name,
- const char *physdev_path,
- MMModem *existing,
- MMSupportsPortResultFunc callback,
- gpointer user_data);
+ void (* supports_port) (MMPlugin *self,
+ const gchar *subsys,
+ const gchar *name,
+ const gchar *physdev_path,
+ MMModem *existing,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ /* Allows to get the result of an asynchronous port support check. */
+ MMPluginSupportsResult (* supports_port_finish) (MMPlugin *self,
+ GAsyncResult *result,
+ guint *level,
+ GError **error);
/* Called to cancel an ongoing supports_port() operation or to notify the
* plugin to clean up that operation. For example, if two plugins support
@@ -111,13 +116,18 @@ const char *mm_plugin_get_name (MMPlugin *plugin);
gboolean mm_plugin_get_sort_last (const MMPlugin *plugin);
-MMPluginSupportsResult mm_plugin_supports_port (MMPlugin *plugin,
- const char *subsys,
- const char *name,
- const char *physdev_path,
- MMModem *existing,
- MMSupportsPortResultFunc callback,
- gpointer user_data);
+void mm_plugin_supports_port (MMPlugin *plugin,
+ const gchar *subsys,
+ const gchar *name,
+ const gchar *physdev_path,
+ MMModem *existing,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+MMPluginSupportsResult mm_plugin_supports_port_finish (MMPlugin *plugin,
+ GAsyncResult *result,
+ guint *level,
+ GError **error);
void mm_plugin_cancel_supports_port (MMPlugin *plugin,
const char *subsys,