aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2024-03-06 13:47:55 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2024-03-12 10:15:59 +0000
commitbd255849dcdbcaa3280033b0974a6a5e0473566e (patch)
tree128d517534eb046d521d471233ffd3c4b390d285 /src
parent07f1f5864204dfdf455067def863fcd20c8c6a26 (diff)
base-manager: reprobe device on late port additions
There is no guarantee from the kernel that the ports of a given device will all be notified via uevents on a timely manner. We assume it, but we cannot be completely sure. There are two main scenarios that we have been seen when the ports of a device are not notified close enough to each other: * A modem object is created, but not with the desired control protocol. E.g. a QMI or MBIM modem would end up controlled via AT commands if the cdc-wdm port was added too late. * A modem object is not created at all, and the device object was removed completely. E.g. when the net port addition in a QMI or MBIM modem happens too late. In order to avoid those cases, we will now fully reprobe all the ports of the device from scratch whenever a new valid port addition happens after the initial probing of the device has already been completed. If a modem object is available at that time, we will remove it right away.
Diffstat (limited to 'src')
-rw-r--r--src/mm-base-manager.c230
-rw-r--r--src/mm-device.c43
-rw-r--r--src/mm-device.h20
-rw-r--r--src/mm-plugin-manager.c101
-rw-r--r--src/mm-plugin-manager.h8
-rw-r--r--src/mm-port-probe.c35
-rw-r--r--src/mm-port-probe.h5
7 files changed, 310 insertions, 132 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index eec4cd86..a2951d22 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -206,34 +206,31 @@ device_support_check_ready (MMPluginManager *plugin_manager,
GAsyncResult *res,
FindDeviceSupportContext *ctx)
{
- GError *error = NULL;
- MMPlugin *plugin;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(MMPlugin) plugin = NULL;
/* If the device support check fails, either with an error, or afterwards
- * when trying to create a modem object, we must remove the MMDevice from
- * the tracking table of devices, so that a manual scan request afterwards
- * re-scans all ports. */
+ * when trying to create a modem object, we must reset the port probe list
+ * in the MMDevice, so that a manual scan request afterwards re-scans all
+ * ports. */
/* Receive plugin result from the plugin manager */
plugin = mm_plugin_manager_device_support_check_finish (plugin_manager, res, &error);
if (!plugin) {
mm_obj_msg (ctx->self, "couldn't check support for device '%s': %s",
mm_device_get_uid (ctx->device), error->message);
- g_error_free (error);
- g_hash_table_remove (ctx->self->priv->devices, mm_device_get_uid (ctx->device));
+ mm_device_reset_port_probe_list (ctx->device);
find_device_support_context_free (ctx);
return;
}
/* Set the plugin as the one expected in the device */
mm_device_set_plugin (ctx->device, G_OBJECT (plugin));
- g_object_unref (plugin);
if (!mm_device_create_modem (ctx->device, &error)) {
mm_obj_warn (ctx->self, "couldn't create modem for device '%s': %s",
mm_device_get_uid (ctx->device), error->message);
- g_error_free (error);
- g_hash_table_remove (ctx->self->priv->devices, mm_device_get_uid (ctx->device));
+ mm_device_reset_port_probe_list (ctx->device);
find_device_support_context_free (ctx);
return;
}
@@ -297,14 +294,175 @@ device_removed (MMBaseManager *self,
}
static void
+device_support_check_add_all_ports (MMBaseManager *self,
+ MMDevice *device)
+{
+ FindDeviceSupportContext *ctx;
+ GList *l;
+
+ g_assert (!mm_plugin_manager_device_support_check_ongoing (self->priv->plugin_manager, device));
+
+ /* There is no running device support context, so we launch a new one */
+ ctx = g_slice_new (FindDeviceSupportContext);
+ ctx->self = g_object_ref (self);
+ ctx->device = g_object_ref (device);
+ mm_plugin_manager_device_support_check (self->priv->plugin_manager,
+ device,
+ (GAsyncReadyCallback) device_support_check_ready,
+ ctx);
+
+ g_assert (mm_plugin_manager_device_support_check_ongoing (self->priv->plugin_manager, device));
+
+ /* Iterate all known ports and notify them one by one */
+ for (l = mm_device_peek_port_probe_list (device); l; l = g_list_next (l)) {
+ mm_plugin_manager_device_support_check_add_port (self->priv->plugin_manager,
+ device,
+ mm_port_probe_peek_port (MM_PORT_PROBE (l->data)));
+ }
+}
+
+static void
+device_support_check_add_single_port (MMBaseManager *self,
+ MMDevice *device,
+ MMKernelDevice *port)
+{
+ FindDeviceSupportContext *ctx;
+ gboolean added;
+
+ /* Try to add the port to an already running device support context */
+ if (mm_plugin_manager_device_support_check_add_port (self->priv->plugin_manager, device, port))
+ return;
+
+ /* There is no running device support context, so we launch a new one */
+ ctx = g_slice_new (FindDeviceSupportContext);
+ ctx->self = g_object_ref (self);
+ ctx->device = g_object_ref (device);
+ mm_plugin_manager_device_support_check (self->priv->plugin_manager,
+ device,
+ (GAsyncReadyCallback) device_support_check_ready,
+ ctx);
+
+ /* Retry now, which should never fail */
+ added = mm_plugin_manager_device_support_check_add_port (self->priv->plugin_manager, device, port);
+ g_assert (added);
+}
+
+static void
+existing_port (MMBaseManager *self,
+ MMDevice *device,
+ MMKernelDevice *port)
+{
+ const gchar *name;
+ const gchar *uid;
+
+ name = mm_kernel_device_get_name (port);
+ uid = mm_device_get_uid (device);
+
+ mm_obj_dbg (self, "port %s already available in device '%s'", name, uid);
+
+ /* If the port exists already in the device, and we already have a valid modem
+ * object created, there is no point in processing this event, we can warn about
+ * the situation and bail out. This may happen e.g. if a manual scan is requested
+ * after having successfully finished the last probing operation. */
+ if (mm_device_peek_plugin (device) && mm_device_peek_modem (device)) {
+ mm_obj_dbg (self, "ignoring port %s as device '%s' already has a valid modem", name, uid);
+ return;
+ }
+
+ /* The port exists in the device, but we don't have a valid modem associated with
+ * it. This may happen if a manual scan is requested after having failed the last
+ * device probing operation. We need to relaunch a new device probing task, unless
+ * one is already running. */
+ device_support_check_add_single_port (self, device, port);
+}
+
+static void
+additional_port (MMBaseManager *self,
+ MMDevice *device,
+ MMKernelDevice *port)
+{
+ MMBaseModem *modem;
+ const gchar *name;
+ const gchar *uid;
+
+ name = mm_kernel_device_get_name (port);
+ uid = mm_device_get_uid (device);
+
+ mm_obj_dbg (self, "additional port %s in device '%s'", name, uid);
+
+ /* Do nothing if the device is ignoring the new port */
+ if (!mm_device_grab_port (device, port))
+ return;
+
+ /* If there is an ongoing support check, we can add the single port right away */
+ if (mm_plugin_manager_device_support_check_ongoing (self->priv->plugin_manager, device)) {
+ device_support_check_add_single_port (self, device, port);
+ return;
+ }
+
+ mm_obj_warn (self, "additional port %s in device '%s' added after device probing has already finished", name, uid);
+
+ /* If there is no plugin assigned in the device, it means the device probing had failed earlier,
+ * for example if none of the ports that were used for the device probing were usable control ports */
+ if (!mm_device_peek_plugin (device)) {
+ g_assert (!mm_device_peek_modem (device));
+ mm_obj_info (self, "last device '%s' probing had failed, will retry", uid);
+ device_support_check_add_all_ports (self, device);
+ return;
+ }
+
+ /* If there is no modem object assigned to the device, it means the modem object creation had failed earlier,
+ * for example if a required port was missing (e.g. missing net port in a QMI or MBIM modem) */
+ modem = mm_device_peek_modem (device);
+ if (!modem) {
+ mm_obj_info (self, "last modem object creation in device '%s' had failed, will retry", uid);
+ device_support_check_add_all_ports (self, device);
+ return;
+ }
+
+ mm_obj_info (self, "last modem object creation in device '%s' succeeded, but we have a new port addition, will retry", uid);
+ g_cancellable_cancel (mm_base_modem_peek_cancellable (modem));
+ mm_device_remove_modem (device);
+ device_support_check_add_all_ports (self, device);
+}
+
+static void
+first_port (MMBaseManager *self,
+ MMKernelDevice *port,
+ gboolean hotplugged)
+{
+ g_autoptr(MMDevice) device = NULL;
+ const gchar *name;
+ const gchar *uid;
+ const gchar *physdev;
+
+ name = mm_kernel_device_get_name (port);
+ uid = mm_kernel_device_get_physdev_uid (port);
+
+ mm_obj_dbg (self, "port %s is first in device '%s'", name, uid);
+
+ physdev = mm_kernel_device_get_physdev_sysfs_path (port);
+ device = mm_device_new (uid, physdev, hotplugged, FALSE, self->priv->object_manager);
+
+ /* If the device is ignoring the new port, discard the new device as well */
+ if (!mm_device_grab_port (device, port)) {
+ mm_obj_dbg (self, "discarding device '%s' as the first port is not grabbed", uid);
+ return;
+ }
+
+ /* Store the device */
+ g_hash_table_insert (self->priv->devices, g_strdup (uid), g_steal_pointer (&device));
+}
+
+static void
device_added (MMBaseManager *self,
MMKernelDevice *port,
gboolean hotplugged,
gboolean manual_scan)
{
MMDevice *device;
- const gchar *physdev_uid;
const gchar *name;
+ const gchar *uid;
g_return_if_fail (port != NULL);
@@ -333,15 +491,15 @@ device_added (MMBaseManager *self,
/* Get the port's physical device's uid. All ports of the same physical
* device will share the same uid. */
- physdev_uid = mm_kernel_device_get_physdev_uid (port);
- g_assert (physdev_uid);
+ uid = mm_kernel_device_get_physdev_uid (port);
+ g_assert (uid);
/* If the device is inhibited, do nothing else */
- if (is_device_inhibited (self, physdev_uid)) {
+ if (is_device_inhibited (self, uid)) {
/* Note: we will not report as hotplugged an inhibited device port
* because we don't know what was done with the port out of our
* context. */
- device_inhibited_track_port (self, physdev_uid, port, manual_scan);
+ device_inhibited_track_port (self, uid, port, manual_scan);
return;
}
@@ -349,42 +507,22 @@ device_added (MMBaseManager *self,
if (!mm_filter_port (self->priv->filter, port, manual_scan))
return;
- /* If already added, ignore new event */
- if (find_device_by_port (self, port)) {
- mm_obj_dbg (self, "port %s already added", name);
+ /* If the port is already added, don't add it again */
+ device = find_device_by_port (self, port);
+ if (device) {
+ existing_port (self, device, port);
return;
}
/* See if we already created an object to handle ports in this device */
- device = find_device_by_physdev_uid (self, physdev_uid);
- if (!device) {
- const gchar *physdev;
- FindDeviceSupportContext *ctx;
-
- mm_obj_dbg (self, "port %s is first in device %s", name, physdev_uid);
-
- physdev = mm_kernel_device_get_physdev_sysfs_path (port);
-
- /* Keep the device listed in the Manager */
- device = mm_device_new (physdev_uid, physdev, hotplugged, FALSE, self->priv->object_manager);
- g_hash_table_insert (self->priv->devices,
- g_strdup (physdev_uid),
- device);
-
- /* Launch device support check */
- ctx = g_slice_new (FindDeviceSupportContext);
- ctx->self = g_object_ref (self);
- ctx->device = g_object_ref (device);
- mm_plugin_manager_device_support_check (
- self->priv->plugin_manager,
- device,
- (GAsyncReadyCallback) device_support_check_ready,
- ctx);
- } else
- mm_obj_dbg (self, "additional port %s in device %s", name, physdev_uid);
+ device = find_device_by_physdev_uid (self, uid);
+ if (device) {
+ additional_port (self, device, port);
+ return;
+ }
- /* Grab the port in the existing device. */
- mm_device_grab_port (device, port);
+ /* This is the first port in a new device */
+ first_port (self, port, hotplugged);
}
#if defined WITH_QRTR
diff --git a/src/mm-device.c b/src/mm-device.c
index 3d98b4ba..e6bd36bb 100644
--- a/src/mm-device.c
+++ b/src/mm-device.c
@@ -10,7 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2012 Google, Inc.
+ * Copyright (C) 2012-2024 Google, Inc.
*/
#include <config.h>
@@ -26,6 +26,7 @@
#include "mm-device.h"
#include "mm-plugin.h"
#include "mm-log-object.h"
+#include "mm-daemon-enums-types.h"
static void log_object_iface_init (MMLogObjectInterface *iface);
@@ -46,7 +47,6 @@ enum {
};
enum {
- SIGNAL_PORT_GRABBED,
SIGNAL_PORT_RELEASED,
SIGNAL_LAST
};
@@ -76,7 +76,8 @@ struct _MMDevicePrivate {
/* Kernel drivers managing this device */
gchar **drivers;
- /* Best plugin to manage this device */
+ /* Best plugin to manage this device, only if the device probing
+ * has finished successfully. */
MMPlugin *plugin;
/* Lists of port probes in the device */
@@ -213,7 +214,7 @@ add_port_driver (MMDevice *self,
self->priv->drivers[n_items + 1] = NULL;
}
-void
+gboolean
mm_device_grab_port (MMDevice *self,
MMKernelDevice *kernel_port)
{
@@ -221,22 +222,19 @@ mm_device_grab_port (MMDevice *self,
MMKernelDevice *lower_port;
if (mm_device_owns_port (self, kernel_port))
- return;
+ return TRUE;
lower_port = mm_kernel_device_peek_lower_device (kernel_port);
if (lower_port) {
g_autoptr(GError) error = NULL;
/* No port probing done, at this point this is not something we require
- * as all the virtual instantiated ports are net devices. We also avoid
- * emitting the PORT_GRABBED signal in the MMDevice, because that is
- * exclusively linked to a port being added to the list of probes, which
- * we don't do here. */
+ * as all the virtual instantiated ports are net devices. */
if (self->priv->modem && !mm_base_modem_grab_link_port (self->priv->modem, kernel_port, &error))
mm_obj_dbg (self, "fully ignoring link port %s from now on: %s",
mm_kernel_device_get_name (kernel_port),
error->message);
- return;
+ return FALSE;
}
if (!g_strcmp0 ("net", mm_kernel_device_get_subsystem (kernel_port)) &&
mm_kernel_device_get_wwandev_sysfs_path (kernel_port)) {
@@ -256,7 +254,7 @@ mm_device_grab_port (MMDevice *self,
mm_obj_dbg (self, "fully ignoring link port %s from now on: %s",
mm_kernel_device_get_name (kernel_port),
error->message);
- return;
+ return FALSE;
}
}
@@ -278,8 +276,7 @@ mm_device_grab_port (MMDevice *self,
probe = mm_port_probe_new (self, kernel_port);
self->priv->port_probes = g_list_prepend (self->priv->port_probes, probe);
- /* Notify about the grabbed port */
- g_signal_emit (self, signals[SIGNAL_PORT_GRABBED], 0, kernel_port);
+ return TRUE;
}
void
@@ -627,6 +624,17 @@ mm_device_peek_port_probe_list (MMDevice *self)
return self->priv->port_probes;
}
+void
+mm_device_reset_port_probe_list (MMDevice *self)
+{
+ GList *l;
+
+ mm_obj_dbg (self, "port probe list reset...");
+ for (l = self->priv->port_probes; l; l = g_list_next (l)) {
+ mm_port_probe_reset (MM_PORT_PROBE (l->data));
+ }
+}
+
gboolean
mm_device_get_hotplugged (MMDevice *self)
{
@@ -981,15 +989,6 @@ mm_device_class_init (MMDeviceClass *klass)
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_INHIBITED, properties[PROP_INHIBITED]);
- signals[SIGNAL_PORT_GRABBED] =
- g_signal_new (MM_DEVICE_PORT_GRABBED,
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (MMDeviceClass, port_grabbed),
- NULL, NULL,
- g_cclosure_marshal_generic,
- G_TYPE_NONE, 1, MM_TYPE_KERNEL_DEVICE);
-
signals[SIGNAL_PORT_RELEASED] =
g_signal_new (MM_DEVICE_PORT_RELEASED,
G_OBJECT_CLASS_TYPE (object_class),
diff --git a/src/mm-device.h b/src/mm-device.h
index f80d6adb..eb376974 100644
--- a/src/mm-device.h
+++ b/src/mm-device.h
@@ -10,7 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2012 Google, Inc.
+ * Copyright (C) 2012-2024 Google, Inc.
*/
#ifndef MM_DEVICE_H
@@ -42,7 +42,6 @@ typedef struct _MMDevicePrivate MMDevicePrivate;
#define MM_DEVICE_INHIBITED "inhibited"
#define MM_DEVICE_OBJECT_MANAGER "object-manager"
-#define MM_DEVICE_PORT_GRABBED "port-grabbed"
#define MM_DEVICE_PORT_RELEASED "port-released"
struct _MMDevice {
@@ -54,8 +53,6 @@ struct _MMDeviceClass {
GObjectClass parent;
/* signals */
- void (* port_grabbed) (MMDevice *self,
- MMKernelDevice *port);
void (* port_released) (MMDevice *self,
MMKernelDevice *port);
};
@@ -69,7 +66,7 @@ MMDevice *mm_device_new (const gchar *uid,
gboolean virtual,
GDBusObjectManagerServer *object_manager);
-void mm_device_grab_port (MMDevice *self,
+gboolean mm_device_grab_port (MMDevice *self,
MMKernelDevice *kernel_port);
gboolean mm_device_owns_port (MMDevice *self,
MMKernelDevice *kernel_port);
@@ -96,7 +93,6 @@ gboolean mm_device_inhibit_finish (MMDevice *self,
gboolean mm_device_uninhibit (MMDevice *self,
GError **error);
-
const gchar *mm_device_get_uid (MMDevice *self);
const gchar *mm_device_get_physdev (MMDevice *self);
const gchar **mm_device_get_drivers (MMDevice *self);
@@ -109,14 +105,16 @@ GObject *mm_device_peek_plugin (MMDevice *self);
GObject *mm_device_get_plugin (MMDevice *self);
MMBaseModem *mm_device_peek_modem (MMDevice *self);
MMBaseModem *mm_device_get_modem (MMDevice *self);
-GObject *mm_device_peek_port_probe (MMDevice *self,
- MMKernelDevice *kernel_port);
-GObject *mm_device_get_port_probe (MMDevice *self,
- MMKernelDevice *kernel_port);
-GList *mm_device_peek_port_probe_list (MMDevice *self);
gboolean mm_device_get_hotplugged (MMDevice *self);
gboolean mm_device_get_inhibited (MMDevice *self);
+GObject *mm_device_peek_port_probe (MMDevice *self,
+ MMKernelDevice *kernel_port);
+GObject *mm_device_get_port_probe (MMDevice *self,
+ MMKernelDevice *kernel_port);
+GList *mm_device_peek_port_probe_list (MMDevice *self);
+void mm_device_reset_port_probe_list (MMDevice *self);
+
/* For testing purposes */
void mm_device_virtual_grab_ports (MMDevice *self,
const gchar **ports);
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index c2438664..0179e5d0 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -784,10 +784,9 @@ struct _DeviceContext {
* is reset to 0. */
guint extra_probing_time_id;
- /* Signal connection ids for the grabbed/released signals from the device.
- * These are the signals that will give us notifications of what ports are
- * available (or suddenly unavailable) in the device. */
- gulong grabbed_id;
+ /* Signal connection ids for the released signal from the device. This is a
+ * signal that will give us notifications of ports suddenly unavailable in
+ * the device. */
gulong released_id;
/* Port support check contexts being run */
@@ -800,7 +799,6 @@ device_context_unref (DeviceContext *device_context)
if (g_atomic_int_dec_and_test (&device_context->ref_count)) {
/* When the last reference is gone there must be no source scheduled and no
* pending port tasks. */
- g_assert (!device_context->grabbed_id);
g_assert (!device_context->released_id);
g_assert (!device_context->min_wait_time_id);
g_assert (!device_context->min_probing_time_id);
@@ -898,18 +896,13 @@ device_context_complete (DeviceContext *device_context)
/* Steal the task from the context */
g_assert (device_context->task);
- task = device_context->task;
- device_context->task = NULL;
+ task = g_steal_pointer (&device_context->task);
/* Log about the time required to complete the checks */
mm_obj_dbg (self, "task %s: finished in '%lf' seconds",
device_context->name, g_timer_elapsed (device_context->timer, NULL));
/* Remove signal handlers */
- if (device_context->grabbed_id) {
- g_signal_handler_disconnect (device_context->device, device_context->grabbed_id);
- device_context->grabbed_id = 0;
- }
if (device_context->released_id) {
g_signal_handler_disconnect (device_context->device, device_context->released_id);
device_context->released_id = 0;
@@ -1276,16 +1269,13 @@ device_context_port_released (DeviceContext *device_context,
}
static void
-device_context_port_grabbed (DeviceContext *device_context,
- MMKernelDevice *port)
+device_context_port_added (MMPluginManager *self,
+ DeviceContext *device_context,
+ MMKernelDevice *port)
{
- MMPluginManager *self;
- PortContext *port_context;
-
- /* Recover plugin manager */
- self = MM_PLUGIN_MANAGER (device_context->self);
+ PortContext *port_context;
- mm_obj_dbg (self, "task %s: port grabbed: %s",
+ mm_obj_dbg (self, "task %s: port added: %s",
device_context->name, mm_kernel_device_get_name (port));
/* Ignore if for any reason we still have it in the running list */
@@ -1311,7 +1301,7 @@ device_context_port_grabbed (DeviceContext *device_context,
(GSourceFunc) device_context_extra_probing_time_elapsed,
device_context);
- /* Setup a new port context for the newly grabbed port */
+ /* Setup a new port context for the newly added port */
port_context = port_context_new (self,
device_context->name,
device_context->device,
@@ -1332,7 +1322,7 @@ device_context_port_grabbed (DeviceContext *device_context,
/* Store the port reference in the list within the device */
device_context->port_contexts = g_list_prepend (device_context->port_contexts, port_context) ;
- /* If the port has been grabbed after the min wait timeout expired, launch
+ /* If the port has been added after the min wait timeout expired, launch
* probing directly */
device_context_run_port_context (device_context, port_context);
}
@@ -1394,17 +1384,12 @@ device_context_run (MMPluginManager *self,
gpointer user_data)
{
g_assert (!device_context->task);
- g_assert (!device_context->grabbed_id);
g_assert (!device_context->released_id);
g_assert (!device_context->min_wait_time_id);
g_assert (!device_context->min_probing_time_id);
g_assert (!device_context->extra_probing_time_id);
- /* Connect to device port grabbed/released notifications from the device */
- device_context->grabbed_id = g_signal_connect_swapped (device_context->device,
- MM_DEVICE_PORT_GRABBED,
- G_CALLBACK (device_context_port_grabbed),
- device_context);
+ /* Connect to device port released notifications from the device */
device_context->released_id = g_signal_connect_swapped (device_context->device,
MM_DEVICE_PORT_RELEASED,
G_CALLBACK (device_context_port_released),
@@ -1507,21 +1492,6 @@ plugin_manager_peek_device_context (MMPluginManager *self,
return NULL;
}
-gboolean
-mm_plugin_manager_device_support_check_cancel (MMPluginManager *self,
- MMDevice *device)
-{
- DeviceContext *device_context;
-
- /* If the device context isn't found, ignore the cancellation request. */
- device_context = plugin_manager_peek_device_context (self, device);
- if (!device_context)
- return FALSE;
-
- /* Request cancellation, will be completed asynchronously */
- return device_context_cancel (device_context);
-}
-
static void
device_context_run_ready (MMPluginManager *self,
GAsyncResult *res,
@@ -1599,6 +1569,53 @@ mm_plugin_manager_device_support_check (MMPluginManager *self,
}
/*****************************************************************************/
+/* Cancel the ongoing device support check, if any */
+
+gboolean
+mm_plugin_manager_device_support_check_cancel (MMPluginManager *self,
+ MMDevice *device)
+{
+ DeviceContext *device_context;
+
+ /* If the device context isn't found, ignore the cancellation request. */
+ device_context = plugin_manager_peek_device_context (self, device);
+ if (!device_context)
+ return FALSE;
+
+ /* Request cancellation, will be completed asynchronously */
+ return device_context_cancel (device_context);
+}
+
+/*****************************************************************************/
+/* Ask if there is an ongoing device support check */
+
+gboolean
+mm_plugin_manager_device_support_check_ongoing (MMPluginManager *self,
+ MMDevice *device)
+{
+ return !!plugin_manager_peek_device_context (self, device);
+}
+
+/*****************************************************************************/
+/* Report a new port to the ongoing device support check */
+
+gboolean
+mm_plugin_manager_device_support_check_add_port (MMPluginManager *self,
+ MMDevice *device,
+ MMKernelDevice *port)
+{
+ DeviceContext *device_context;
+
+ device_context = plugin_manager_peek_device_context (self, device);
+ if (device_context) {
+ device_context_port_added (self, device_context, port);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
/* Look for plugin */
MMPlugin *
diff --git a/src/mm-plugin-manager.h b/src/mm-plugin-manager.h
index f1ddcc29..41a2d405 100644
--- a/src/mm-plugin-manager.h
+++ b/src/mm-plugin-manager.h
@@ -67,6 +67,14 @@ gboolean mm_plugin_manager_device_support_check_cancel (MMPluginManager
MMPlugin * mm_plugin_manager_device_support_check_finish (MMPluginManager *self,
GAsyncResult *res,
GError **error);
+
+gboolean mm_plugin_manager_device_support_check_ongoing (MMPluginManager *self,
+ MMDevice *device);
+
+gboolean mm_plugin_manager_device_support_check_add_port (MMPluginManager *self,
+ MMDevice *device,
+ MMKernelDevice *port);
+
MMPlugin *mm_plugin_manager_peek_plugin (MMPluginManager *self,
const gchar *plugin_name);
const gchar **mm_plugin_manager_get_subsystems (MMPluginManager *self);
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index 548b5bdc..5b4f7927 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -86,6 +86,15 @@ struct _MMPortProbePrivate {
MMDevice *device;
MMKernelDevice *port;
+ /* From udev tags */
+ gboolean is_ignored;
+ gboolean is_gps;
+ gboolean is_audio;
+ gboolean maybe_at;
+ gboolean maybe_qcdm;
+ gboolean maybe_qmi;
+ gboolean maybe_mbim;
+
/* Probing results */
guint32 flags;
gboolean is_at;
@@ -97,20 +106,28 @@ struct _MMPortProbePrivate {
gboolean is_qmi;
gboolean is_mbim;
- /* From udev tags */
- gboolean is_ignored;
- gboolean is_gps;
- gboolean is_audio;
- gboolean maybe_at;
- gboolean maybe_qcdm;
- gboolean maybe_qmi;
- gboolean maybe_mbim;
-
/* Current probing task. Only one can be available at a time */
GTask *task;
};
/*****************************************************************************/
+
+void
+mm_port_probe_reset (MMPortProbe *self)
+{
+ g_assert (!self->priv->task);
+ self->priv->flags = 0;
+ self->priv->is_at = FALSE;
+ self->priv->is_qcdm = FALSE;
+ g_clear_pointer (&self->priv->vendor, g_free);
+ g_clear_pointer (&self->priv->product, g_free);
+ self->priv->is_icera = FALSE;
+ self->priv->is_xmm = FALSE;
+ self->priv->is_qmi = FALSE;
+ self->priv->is_mbim = FALSE;
+}
+
+/*****************************************************************************/
/* Probe task completions.
* Always make sure that the stored task is NULL when the task is completed.
*/
diff --git a/src/mm-port-probe.h b/src/mm-port-probe.h
index 5dd56a8f..faa3a12c 100644
--- a/src/mm-port-probe.h
+++ b/src/mm-port-probe.h
@@ -81,8 +81,9 @@ typedef gboolean (* MMPortProbeAtCustomInitFinish) (MMPortProbe *probe,
GType mm_port_probe_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPortProbe, g_object_unref)
-MMPortProbe *mm_port_probe_new (MMDevice *device,
- MMKernelDevice *port);
+MMPortProbe *mm_port_probe_new (MMDevice *device,
+ MMKernelDevice *port);
+void mm_port_probe_reset (MMPortProbe *self);
MMDevice *mm_port_probe_peek_device (MMPortProbe *self);
MMDevice *mm_port_probe_get_device (MMPortProbe *self);