[PATCH 05/10] base-manager: if udev supported, use MMKernelDeviceUdev also for kernel events

Aleksander Morgado aleksander at aleksander.es
Sat Aug 6 13:03:33 UTC 2016


The kernel event reporting logic will use the udev-backend of MMKernelDevice if
the build is compiled with udev support.
---
 src/kerneldevice/mm-kernel-device-udev.c | 249 +++++++++++++++++++++++++++----
 src/kerneldevice/mm-kernel-device-udev.h |   9 +-
 src/mm-base-manager.c                    |   5 +
 3 files changed, 236 insertions(+), 27 deletions(-)

diff --git a/src/kerneldevice/mm-kernel-device-udev.c b/src/kerneldevice/mm-kernel-device-udev.c
index 1870206..7730d0e 100644
--- a/src/kerneldevice/mm-kernel-device-udev.c
+++ b/src/kerneldevice/mm-kernel-device-udev.c
@@ -21,11 +21,15 @@
 #include "mm-kernel-device-udev.h"
 #include "mm-log.h"
 
-G_DEFINE_TYPE (MMKernelDeviceUdev, mm_kernel_device_udev,  MM_TYPE_KERNEL_DEVICE)
+static void initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMKernelDeviceUdev, mm_kernel_device_udev,  MM_TYPE_KERNEL_DEVICE, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
 
 enum {
     PROP_0,
     PROP_UDEV_DEVICE,
+    PROP_PROPERTIES,
     PROP_LAST
 };
 
@@ -37,6 +41,8 @@ struct _MMKernelDeviceUdevPrivate {
     GUdevDevice *physdev;
     guint16      vendor;
     guint16      product;
+
+    MMKernelEventProperties *properties;
 };
 
 /*****************************************************************************/
@@ -150,13 +156,33 @@ out:
 static void
 ensure_device_ids (MMKernelDeviceUdev *self)
 {
+    guint16 probed_vid = 0;
+    guint16 probed_pid = 0;
+
     if (self->priv->vendor || self->priv->product)
         return;
 
-    if (!get_device_ids (self->priv->device, &self->priv->vendor, &self->priv->product))
+    /* Prefer the ones coming in the properties, if any */
+    if (self->priv->properties) {
+        self->priv->vendor  = mm_kernel_event_properties_get_physdev_vid (self->priv->properties);
+        self->priv->product = mm_kernel_event_properties_get_physdev_pid (self->priv->properties);
+        if (self->priv->vendor && self->priv->product)
+            return;
+    }
+
+    if (!self->priv->device)
+        return;
+
+    if (!get_device_ids (self->priv->device, &probed_vid, &probed_pid))
         mm_dbg ("(%s/%s) could not get vendor/product ID",
                 g_udev_device_get_subsystem (self->priv->device),
                 g_udev_device_get_name      (self->priv->device));
+
+    if (!self->priv->vendor)
+        self->priv->vendor = probed_vid;
+
+    if (!self->priv->product)
+        self->priv->product = probed_pid;
 }
 
 /*****************************************************************************/
@@ -240,25 +266,42 @@ ensure_physdev (MMKernelDeviceUdev *self)
 {
     if (self->priv->physdev)
         return;
-    self->priv->physdev = find_physical_gudevdevice (self->priv->device);
+    if (self->priv->device)
+        self->priv->physdev = find_physical_gudevdevice (self->priv->device);
 }
 
 /*****************************************************************************/
 
 static const gchar *
-kernel_device_get_subsystem (MMKernelDevice *self)
+kernel_device_get_subsystem (MMKernelDevice *_self)
 {
-    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (self), NULL);
+    MMKernelDeviceUdev *self;
+
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL);
+
+    self = MM_KERNEL_DEVICE_UDEV (_self);
 
-    return g_udev_device_get_subsystem (MM_KERNEL_DEVICE_UDEV (self)->priv->device);
+    if (self->priv->device)
+        return g_udev_device_get_subsystem (self->priv->device);
+
+    g_assert (self->priv->properties);
+    return mm_kernel_event_properties_get_subsystem (self->priv->properties);
 }
 
 static const gchar *
-kernel_device_get_name (MMKernelDevice *self)
+kernel_device_get_name (MMKernelDevice *_self)
 {
-    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (self), NULL);
+    MMKernelDeviceUdev *self;
 
-    return g_udev_device_get_name (MM_KERNEL_DEVICE_UDEV (self)->priv->device);
+    g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL);
+
+    self = MM_KERNEL_DEVICE_UDEV (_self);
+
+    if (self->priv->device)
+        return g_udev_device_get_name (self->priv->device);
+
+    g_assert (self->priv->properties);
+    return mm_kernel_event_properties_get_name (self->priv->properties);
 }
 
 static const gchar *
@@ -271,6 +314,16 @@ kernel_device_get_driver (MMKernelDevice *_self)
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
 
+    /* Prefer the one coming in properties, if any */
+    if (self->priv->properties) {
+        driver = mm_kernel_event_properties_get_driver (self->priv->properties);
+        if (driver)
+            return driver;
+    }
+
+    if (!self->priv->device)
+        return NULL;
+
     driver = g_udev_device_get_driver (self->priv->device);
     if (!driver) {
         GUdevDevice *parent;
@@ -308,6 +361,9 @@ kernel_device_get_sysfs_path (MMKernelDevice *self)
 {
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE (self), NULL);
 
+    if (!MM_KERNEL_DEVICE_UDEV (self)->priv->device)
+        return NULL;
+
     return g_udev_device_get_sysfs_path (MM_KERNEL_DEVICE_UDEV (self)->priv->device);
 }
 
@@ -315,12 +371,22 @@ static const gchar *
 kernel_device_get_physdev_uid (MMKernelDevice *_self)
 {
     MMKernelDeviceUdev *self;
+    const gchar        *physdev_uid = NULL;
 
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
-    ensure_physdev (self);
-    return (self->priv->physdev ? g_udev_device_get_sysfs_path (self->priv->physdev) : NULL);
+
+    /* Prefer the one coming in the properties, if any */
+    if (self->priv->properties)
+        physdev_uid = mm_kernel_event_properties_get_physdev_uid (MM_KERNEL_DEVICE_UDEV (self)->priv->properties);
+
+    if (!physdev_uid) {
+        ensure_physdev (self);
+        physdev_uid = (self->priv->physdev ? g_udev_device_get_sysfs_path (self->priv->physdev) : NULL);
+    }
+
+    return physdev_uid;
 }
 
 static guint16
@@ -355,7 +421,8 @@ kernel_device_get_parent_sysfs_path (MMKernelDevice *_self)
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), 0);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
-    if (!self->priv->parent)
+
+    if (!self->priv->parent && self->priv->device)
         self->priv->parent = g_udev_device_get_parent (self->priv->device);
     return (self->priv->parent ? g_udev_device_get_sysfs_path (self->priv->parent) : NULL);
 }
@@ -373,6 +440,17 @@ kernel_device_is_candidate (MMKernelDevice *_self,
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
 
+    /* If being candidate is forced, do it */
+    if (self->priv->properties && mm_kernel_event_properties_get_candidate (self->priv->properties)) {
+        mm_dbg ("(%s/%s) device forced to be candidate",
+                mm_kernel_event_properties_get_subsystem (self->priv->properties),
+                mm_kernel_event_properties_get_name      (self->priv->properties));
+        return TRUE;
+    }
+
+    if (!self->priv->device)
+        return FALSE;
+
     name   = g_udev_device_get_name      (self->priv->device);
     subsys = g_udev_device_get_subsystem (self->priv->device);
 
@@ -446,17 +524,22 @@ kernel_device_cmp (MMKernelDevice *_a,
     a = MM_KERNEL_DEVICE_UDEV (_a);
     b = MM_KERNEL_DEVICE_UDEV (_b);
 
-    if (g_udev_device_has_property (a->priv->device, "DEVPATH_OLD") &&
-        g_str_has_suffix (g_udev_device_get_sysfs_path (b->priv->device),
-                          g_udev_device_get_property   (a->priv->device, "DEVPATH_OLD")))
-        return TRUE;
+    if (a->priv->device && b->priv->device) {
+        if (g_udev_device_has_property (a->priv->device, "DEVPATH_OLD") &&
+            g_str_has_suffix (g_udev_device_get_sysfs_path (b->priv->device),
+                              g_udev_device_get_property   (a->priv->device, "DEVPATH_OLD")))
+            return TRUE;
 
-    if (g_udev_device_has_property (b->priv->device, "DEVPATH_OLD") &&
-        g_str_has_suffix (g_udev_device_get_sysfs_path (a->priv->device),
-                          g_udev_device_get_property   (b->priv->device, "DEVPATH_OLD")))
-        return TRUE;
+        if (g_udev_device_has_property (b->priv->device, "DEVPATH_OLD") &&
+            g_str_has_suffix (g_udev_device_get_sysfs_path (a->priv->device),
+                              g_udev_device_get_property   (b->priv->device, "DEVPATH_OLD")))
+            return TRUE;
 
-    return !g_strcmp0 (g_udev_device_get_sysfs_path (a->priv->device), g_udev_device_get_sysfs_path (b->priv->device));
+        return !g_strcmp0 (g_udev_device_get_sysfs_path (a->priv->device), g_udev_device_get_sysfs_path (b->priv->device));
+    }
+
+    return (!g_strcmp0 (mm_kernel_device_get_subsystem (_a), mm_kernel_device_get_subsystem (_b)) &&
+            !g_strcmp0 (mm_kernel_device_get_name      (_a), mm_kernel_device_get_name      (_b)));
 }
 
 static gboolean
@@ -468,6 +551,10 @@ kernel_device_has_property (MMKernelDevice *_self,
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), FALSE);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
+
+    if (!self->priv->device)
+        return FALSE;
+
     return g_udev_device_has_property (self->priv->device, property);
 }
 
@@ -480,6 +567,10 @@ kernel_device_get_property (MMKernelDevice *_self,
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), NULL);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
+
+    if (!self->priv->device)
+        return NULL;
+
     return g_udev_device_get_property (self->priv->device, property);
 }
 
@@ -492,6 +583,10 @@ kernel_device_get_property_as_boolean (MMKernelDevice *_self,
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), FALSE);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
+
+    if (!self->priv->device)
+        return FALSE;
+
     return g_udev_device_get_property_as_boolean (self->priv->device, property);
 }
 
@@ -504,6 +599,10 @@ kernel_device_get_property_as_int (MMKernelDevice *_self,
     g_return_val_if_fail (MM_IS_KERNEL_DEVICE_UDEV (_self), -1);
 
     self = MM_KERNEL_DEVICE_UDEV (_self);
+
+    if (!self->priv->device)
+        return -1;
+
     return g_udev_device_get_property_as_int (self->priv->device, property);
 }
 
@@ -512,11 +611,31 @@ kernel_device_get_property_as_int (MMKernelDevice *_self,
 MMKernelDevice *
 mm_kernel_device_udev_new (GUdevDevice *udev_device)
 {
+    GError *error = NULL;
+    MMKernelDevice *self;
+
     g_return_val_if_fail (G_UDEV_IS_DEVICE (udev_device), NULL);
 
-    return MM_KERNEL_DEVICE (g_object_new (MM_TYPE_KERNEL_DEVICE_UDEV,
-                                           "udev-device", udev_device,
-                                           NULL));
+    self = MM_KERNEL_DEVICE (g_initable_new (MM_TYPE_KERNEL_DEVICE_UDEV,
+                                             NULL,
+                                             &error,
+                                             "udev-device", udev_device,
+                                             NULL));
+    g_assert_no_error (error);
+    return self;
+}
+
+/*****************************************************************************/
+
+MMKernelDevice *
+mm_kernel_device_udev_new_from_properties (MMKernelEventProperties  *properties,
+                                           GError                  **error)
+{
+    return MM_KERNEL_DEVICE (g_initable_new (MM_TYPE_KERNEL_DEVICE_UDEV,
+                                             NULL,
+                                             error,
+                                             "properties", properties,
+                                             NULL));
 }
 
 /*****************************************************************************/
@@ -541,6 +660,10 @@ set_property (GObject      *object,
         g_assert (!self->priv->device);
         self->priv->device = g_value_dup_object (value);
         break;
+    case PROP_PROPERTIES:
+        g_assert (!self->priv->properties);
+        self->priv->properties = g_value_dup_object (value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -559,12 +682,73 @@ get_property (GObject    *object,
     case PROP_UDEV_DEVICE:
         g_value_set_object (value, self->priv->device);
         break;
+    case PROP_PROPERTIES:
+        g_value_set_object (value, self->priv->properties);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
 }
 
+static gboolean
+initable_init (GInitable     *initable,
+               GCancellable  *cancellable,
+               GError       **error)
+{
+    MMKernelDeviceUdev *self = MM_KERNEL_DEVICE_UDEV (initable);
+    const gchar *subsystem;
+    const gchar *name;
+
+    /* When created from a GUdevDevice, we're done */
+    if (self->priv->device)
+        return TRUE;
+
+    /* Otherwise, we do need properties with subsystem and name */
+    if (!self->priv->properties) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "missing properties in kernel device");
+        return FALSE;
+    }
+
+    subsystem = mm_kernel_event_properties_get_subsystem (self->priv->properties);
+    if (!subsystem) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "subsystem is mandatory in kernel device");
+        return FALSE;
+    }
+
+    name = mm_kernel_event_properties_get_name (self->priv->properties);
+    if (!mm_kernel_device_get_name (MM_KERNEL_DEVICE (self))) {
+        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                     "name is mandatory in kernel device");
+        return FALSE;
+    }
+
+    /* On remove events, we don't look for the GUdevDevice */
+    if (g_strcmp0 (mm_kernel_event_properties_get_action (self->priv->properties), "remove")) {
+        GUdevClient *client;
+        GUdevDevice *device;
+
+        client = g_udev_client_new (NULL);
+        device = g_udev_client_query_by_subsystem_and_name (client, subsystem, name);
+        if (!device) {
+            g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+                         "device %s/%s not found",
+                         subsystem,
+                         name);
+            g_object_unref (client);
+            return FALSE;
+        }
+
+        /* Store device */
+        self->priv->device = device;
+        g_object_unref (client);
+    }
+
+    return TRUE;
+}
+
 static void
 dispose (GObject *object)
 {
@@ -573,11 +757,18 @@ dispose (GObject *object)
     g_clear_object (&self->priv->physdev);
     g_clear_object (&self->priv->parent);
     g_clear_object (&self->priv->device);
+    g_clear_object (&self->priv->properties);
 
     G_OBJECT_CLASS (mm_kernel_device_udev_parent_class)->dispose (object);
 }
 
 static void
+initable_iface_init (GInitableIface *iface)
+{
+    iface->init = initable_init;
+}
+
+static void
 mm_kernel_device_udev_class_init (MMKernelDeviceUdevClass *klass)
 {
     GObjectClass        *object_class        = G_OBJECT_CLASS (klass);
@@ -609,6 +800,14 @@ mm_kernel_device_udev_class_init (MMKernelDeviceUdevClass *klass)
                              "udev device",
                              "Device object as reported by GUdev",
                              G_UDEV_TYPE_DEVICE,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+                             G_PARAM_READWRITE);
     g_object_class_install_property (object_class, PROP_UDEV_DEVICE, properties[PROP_UDEV_DEVICE]);
+
+    properties[PROP_PROPERTIES] =
+        g_param_spec_object ("properties",
+                             "Properties",
+                             "Generic kernel event properties",
+                             MM_TYPE_KERNEL_EVENT_PROPERTIES,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (object_class, PROP_PROPERTIES, properties[PROP_PROPERTIES]);
 }
diff --git a/src/kerneldevice/mm-kernel-device-udev.h b/src/kerneldevice/mm-kernel-device-udev.h
index ed83159..9096ca7 100644
--- a/src/kerneldevice/mm-kernel-device-udev.h
+++ b/src/kerneldevice/mm-kernel-device-udev.h
@@ -20,6 +20,9 @@
 #include <glib-object.h>
 #include <gudev/gudev.h>
 
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
 #include "mm-kernel-device.h"
 
 #define MM_TYPE_KERNEL_DEVICE_UDEV            (mm_kernel_device_udev_get_type ())
@@ -42,7 +45,9 @@ struct _MMKernelDeviceUdevClass {
     MMKernelDeviceClass parent;
 };
 
-GType           mm_kernel_device_udev_get_type (void);
-MMKernelDevice *mm_kernel_device_udev_new      (GUdevDevice *udev_device);
+GType           mm_kernel_device_udev_get_type            (void);
+MMKernelDevice *mm_kernel_device_udev_new                 (GUdevDevice              *udev_device);
+MMKernelDevice *mm_kernel_device_udev_new_from_properties (MMKernelEventProperties  *properties,
+                                                           GError                  **error);
 
 #endif /* MM_KERNEL_DEVICE_UDEV_H */
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index 991b7e5..0c12e10 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -713,7 +713,12 @@ report_kernel_event_auth_ready (MMAuthProvider           *authp,
     if (mm_kernel_event_properties_get_candidate (properties))
         mm_dbg ("  candidate:   yes");
 
+#if WITH_UDEV
+    kernel_device = mm_kernel_device_udev_new_from_properties (properties, &error);
+#else
     kernel_device = mm_kernel_device_generic_new (properties, &error);
+#endif
+
     if (!kernel_device)
         goto out;
 
-- 
2.9.0



More information about the ModemManager-devel mailing list