aboutsummaryrefslogtreecommitdiff
path: root/src/mm-plugin.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-01-15 17:54:51 +0100
committerAleksander Morgado <aleksander@aleksander.es>2016-03-09 23:59:46 +0100
commitd3bf07e7a87bac85778750a87463b95f2180c55c (patch)
tree8f72a3161b36be28584ebab24fa5ce5f42fd1df3 /src/mm-plugin.c
parentfd4fdbf21b20983cdd46fc925389dd96ca3a99d3 (diff)
plugin: allow cancellation of the port probe operation
Diffstat (limited to 'src/mm-plugin.c')
-rw-r--r--src/mm-plugin.c224
1 files changed, 103 insertions, 121 deletions
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index 7a3986cc..ec3f6e33 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -582,125 +582,119 @@ apply_post_probing_filters (MMPlugin *self,
/* Context for the asynchronous probing operation */
typedef struct {
- GSimpleAsyncResult *result;
MMPlugin *self;
- MMPortProbeFlag flags;
MMDevice *device;
+ MMPortProbeFlag flags;
} PortProbeRunContext;
static void
+port_probe_run_context_free (PortProbeRunContext *ctx)
+{
+ g_object_unref (ctx->device);
+ g_object_unref (ctx->self);
+ g_slice_free (PortProbeRunContext, ctx);
+}
+
+static void
port_probe_run_ready (MMPortProbe *probe,
GAsyncResult *probe_result,
- PortProbeRunContext *ctx)
+ GTask *task)
{
GError *error = NULL;
+ MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNKNOWN;
+ PortProbeRunContext *ctx;
if (!mm_port_probe_run_finish (probe, probe_result, &error)) {
/* Probing failed saying the port is unsupported. This is not to be
* treated as a generic error, the plugin is just telling us as nicely
* as it can that the port is not supported, so don't warn these cases.
*/
- if (g_error_matches (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED)) {
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED),
- NULL);
- g_error_free (error);
+ if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {
+ result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ goto out;
}
+
/* Probing failed but the plugin tells us to retry; so we'll defer the
* probing a bit */
- else if (g_error_matches (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_RETRY)) {
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_DEFER),
- NULL);
- g_error_free (error);
- }
- /* For remaining errors, just propagate them */
- else {
- g_simple_async_result_take_error (ctx->result, error);
- }
- } else {
- /* Probing succeeded */
- MMPluginSupportsResult supports_result;
-
- if (!apply_post_probing_filters (ctx->self, ctx->flags, probe)) {
- /* Port is supported! */
- supports_result = MM_PLUGIN_SUPPORTS_PORT_SUPPORTED;
-
- /* If we were looking for AT ports, and the port is AT,
- * and we were told that only one AT port is expected, cancel AT
- * probings in the other available support tasks of the SAME
- * device. */
- if (ctx->self->priv->single_at &&
- ctx->flags & MM_PORT_PROBE_AT &&
- mm_port_probe_is_at (probe)) {
- GList *l;
-
- for (l = mm_device_peek_port_probe_list (ctx->device); l; l = g_list_next (l)) {
- if (l->data != probe) {
- mm_port_probe_run_cancel_at_probing (MM_PORT_PROBE (l->data));
- }
- }
- }
- } else {
- /* Unsupported port, remove from internal tracking HT */
- supports_result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
+ if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY)) {
+ result = MM_PLUGIN_SUPPORTS_PORT_DEFER;
+ goto out;
}
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- GUINT_TO_POINTER (supports_result),
- NULL);
+ /* For remaining errors, just propagate them */
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
- /* Complete the async supports port request */
- g_simple_async_result_complete_in_idle (ctx->result);
+ /* Probing succeeded, recover context */
+ ctx = g_task_get_task_data (task);
+
+ /* Apply post probing filters */
+ if (!apply_post_probing_filters (ctx->self, ctx->flags, probe)) {
+ /* Port is supported! */
+ result = MM_PLUGIN_SUPPORTS_PORT_SUPPORTED;
+
+ /* If we were looking for AT ports, and the port is AT,
+ * and we were told that only one AT port is expected, cancel AT
+ * probings in the other available support tasks of the SAME
+ * device. */
+ if (ctx->self->priv->single_at &&
+ ctx->flags & MM_PORT_PROBE_AT &&
+ mm_port_probe_is_at (probe)) {
+ GList *l;
+
+ for (l = mm_device_peek_port_probe_list (ctx->device); l; l = g_list_next (l)) {
+ if (l->data != probe)
+ mm_port_probe_run_cancel_at_probing (MM_PORT_PROBE (l->data));
+ }
+ }
+ } else
+ /* Filtered by post probing filters */
+ result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- g_object_unref (ctx->device);
- g_object_unref (ctx->result);
- g_object_unref (ctx->self);
- g_free (ctx);
+out:
+ /* Complete action */
+ g_clear_error (&error);
+ g_task_return_int (task, result);
+ g_object_unref (task);
}
+G_STATIC_ASSERT (MM_PLUGIN_SUPPORTS_PORT_UNKNOWN == -1);
+
MMPluginSupportsResult
-mm_plugin_supports_port_finish (MMPlugin *self,
- GAsyncResult *result,
- GError **error)
+mm_plugin_supports_port_finish (MMPlugin *self,
+ GAsyncResult *result,
+ 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);
-
- /* Propagate error, if any */
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) {
- return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
- }
+ g_return_val_if_fail (MM_IS_PLUGIN (self), MM_PLUGIN_SUPPORTS_PORT_UNKNOWN);
+ g_return_val_if_fail (G_IS_TASK (result), MM_PLUGIN_SUPPORTS_PORT_UNKNOWN);
- return (MMPluginSupportsResult) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
+ return (MMPluginSupportsResult) g_task_propagate_int (G_TASK (result), error);
}
void
-mm_plugin_supports_port (MMPlugin *self,
- MMDevice *device,
- GUdevDevice *port,
- GAsyncReadyCallback callback,
- gpointer user_data)
+mm_plugin_supports_port (MMPlugin *self,
+ MMDevice *device,
+ GUdevDevice *port,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
MMPortProbe *probe = NULL;
- GSimpleAsyncResult *async_result;
+ GTask *task;
PortProbeRunContext *ctx;
gboolean need_vendor_probing;
gboolean need_product_probing;
MMPortProbeFlag probe_run_flags;
gchar *probe_list_str;
- async_result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- mm_plugin_supports_port);
+ g_return_if_fail (MM_IS_PLUGIN (self));
+ g_return_if_fail (MM_IS_DEVICE (device));
+ g_return_if_fail (G_UDEV_IS_DEVICE (port));
+
+ /* Create new cancellable task */
+ task = g_task_new (self, cancellable, callback, user_data);
/* Apply filters before launching the probing */
if (apply_pre_probing_filters (self,
@@ -709,46 +703,40 @@ mm_plugin_supports_port (MMPlugin *self,
&need_vendor_probing,
&need_product_probing)) {
/* Filtered! */
- g_simple_async_result_set_op_res_gpointer (async_result,
- GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED),
- NULL);
- g_simple_async_result_complete_in_idle (async_result);
- goto out;
+ g_task_return_int (task, MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
+ g_object_unref (task);
+ return;
}
/* Need to launch new probing */
- probe = MM_PORT_PROBE (mm_device_get_port_probe (device, port));
+ probe = MM_PORT_PROBE (mm_device_peek_port_probe (device, port));
if (!probe) {
/* This may happen if the ports get removed from the device while
* probing is ongoing */
- g_simple_async_result_set_error (async_result,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "(%s) Missing port probe for port (%s/%s)",
- self->priv->name,
- g_udev_device_get_subsystem (port),
- g_udev_device_get_name (port));
- g_simple_async_result_complete_in_idle (async_result);
- goto out;
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "(%s) Missing port probe for port (%s/%s)",
+ self->priv->name,
+ g_udev_device_get_subsystem (port),
+ g_udev_device_get_name (port));
+ g_object_unref (task);
+ return;
}
/* Before launching any probing, check if the port is a net device. */
if (g_str_equal (g_udev_device_get_subsystem (port), "net")) {
mm_dbg ("(%s) [%s] probing deferred until result suggested",
- self->priv->name,
- g_udev_device_get_name (port));
- g_simple_async_result_set_op_res_gpointer (
- async_result,
- GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED),
- NULL);
- g_simple_async_result_complete_in_idle (async_result);
- goto out;
+ self->priv->name, g_udev_device_get_name (port));
+ g_task_return_int (task, MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED);
+ g_object_unref (task);
+ return;
}
/* Build flags depending on what probing needed */
+ probe_run_flags = MM_PORT_PROBE_NONE;
if (!g_str_has_prefix (g_udev_device_get_name (port), "cdc-wdm")) {
/* Serial ports... */
- probe_run_flags = MM_PORT_PROBE_NONE;
if (self->priv->at)
probe_run_flags |= MM_PORT_PROBE_AT;
else if (self->priv->single_at)
@@ -757,7 +745,6 @@ mm_plugin_supports_port (MMPlugin *self,
probe_run_flags |= MM_PORT_PROBE_QCDM;
} else {
/* cdc-wdm ports... */
- probe_run_flags = MM_PORT_PROBE_NONE;
if (self->priv->qmi && !g_strcmp0 (mm_device_utils_get_port_driver (port), "qmi_wwan"))
probe_run_flags |= MM_PORT_PROBE_QMI;
else if (self->priv->mbim && !g_strcmp0 (mm_device_utils_get_port_driver (port), "cdc_mbim"))
@@ -779,11 +766,9 @@ mm_plugin_supports_port (MMPlugin *self,
/* If no explicit probing was required, just request to grab it without probing anything.
* This may happen, e.g. with cdc-wdm ports which do not need QMI/MBIM probing. */
if (probe_run_flags == MM_PORT_PROBE_NONE) {
- g_simple_async_result_set_op_res_gpointer (async_result,
- GUINT_TO_POINTER (MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED),
- NULL);
- g_simple_async_result_complete_in_idle (async_result);
- goto out;
+ g_task_return_int (task, MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED);
+ g_object_unref (task);
+ return;
}
/* If a modem is already available and the plugin says that only one AT port is
@@ -803,11 +788,13 @@ mm_plugin_supports_port (MMPlugin *self,
}
/* Setup async call context */
- ctx = g_new (PortProbeRunContext, 1);
- ctx->self = g_object_ref (self);
+ ctx = g_slice_new0 (PortProbeRunContext);
+ ctx->self = g_object_ref (self);
ctx->device = g_object_ref (device);
- ctx->result = g_object_ref (async_result);
- ctx->flags = probe_run_flags;
+ ctx->flags = probe_run_flags;
+
+ /* Store context in task */
+ g_task_set_task_data (task, ctx, (GDestroyNotify) port_probe_run_context_free);
/* Launch the probe */
probe_list_str = mm_port_probe_flag_build_string_from_mask (ctx->flags);
@@ -824,13 +811,8 @@ mm_plugin_supports_port (MMPlugin *self,
self->priv->send_lf,
self->priv->custom_at_probe,
self->priv->custom_init,
- (GAsyncReadyCallback)port_probe_run_ready,
- ctx);
-
-out:
- g_object_unref (async_result);
- if (probe)
- g_object_unref (probe);
+ (GAsyncReadyCallback) port_probe_run_ready,
+ task);
}
/*****************************************************************************/