[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