diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-01-15 17:54:51 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-03-09 23:59:46 +0100 |
commit | d3bf07e7a87bac85778750a87463b95f2180c55c (patch) | |
tree | 8f72a3161b36be28584ebab24fa5ce5f42fd1df3 | |
parent | fd4fdbf21b20983cdd46fc925389dd96ca3a99d3 (diff) |
plugin: allow cancellation of the port probe operation
-rw-r--r-- | src/mm-plugin-manager.c | 3 | ||||
-rw-r--r-- | src/mm-plugin.c | 224 | ||||
-rw-r--r-- | src/mm-plugin.h | 20 |
3 files changed, 117 insertions, 130 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index 636af09b..abf714d6 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -465,6 +465,7 @@ plugin_supports_port_ready (MMPlugin *plugin, /* Get supports check results */ support_result = mm_plugin_supports_port_finish (plugin, res, &error); if (error) { + g_assert_cmpuint (support_result, ==, MM_PLUGIN_SUPPORTS_PORT_UNKNOWN); mm_warn ("[plugin manager] task %s: error when checking support with plugin '%s': '%s'", port_context->name, mm_plugin_get_name (plugin), error->message); g_error_free (error); @@ -474,6 +475,7 @@ plugin_supports_port_ready (MMPlugin *plugin, case MM_PLUGIN_SUPPORTS_PORT_SUPPORTED: port_context_supported (port_context, plugin); break; + case MM_PLUGIN_SUPPORTS_PORT_UNKNOWN: case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED: port_context_unsupported (port_context, plugin); break; @@ -518,6 +520,7 @@ port_context_next (PortContext *port_context) mm_plugin_supports_port (plugin, port_context->device, port_context->port, + port_context->cancellable, (GAsyncReadyCallback) plugin_supports_port_ready, port_context_ref (port_context)); } 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); } /*****************************************************************************/ diff --git a/src/mm-plugin.h b/src/mm-plugin.h index 7497afbd..ee03686b 100644 --- a/src/mm-plugin.h +++ b/src/mm-plugin.h @@ -64,7 +64,8 @@ #define MM_PLUGIN_SEND_LF "send-lf" typedef enum { - MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED = 0x0, + MM_PLUGIN_SUPPORTS_PORT_UNKNOWN = -1, + MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED, MM_PLUGIN_SUPPORTS_PORT_DEFER, MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED, MM_PLUGIN_SUPPORTS_PORT_SUPPORTED @@ -119,14 +120,15 @@ MMPluginSupportsHint mm_plugin_discard_port_early (MMPlugin *plugin, MMDevice *device, GUdevDevice *port); -void mm_plugin_supports_port (MMPlugin *plugin, - MMDevice *device, - GUdevDevice *port, - GAsyncReadyCallback callback, - gpointer user_data); -MMPluginSupportsResult mm_plugin_supports_port_finish (MMPlugin *plugin, - GAsyncResult *result, - GError **error); +void mm_plugin_supports_port (MMPlugin *plugin, + MMDevice *device, + GUdevDevice *port, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +MMPluginSupportsResult mm_plugin_supports_port_finish (MMPlugin *plugin, + GAsyncResult *result, + GError **error); MMBaseModem *mm_plugin_create_modem (MMPlugin *plugin, MMDevice *device, |