From cca83392f09a2a67178203d493656c4355863106 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Mon, 9 Nov 2020 12:11:43 +0100 Subject: kerneldevice,generic: implement ATTRS matching for any attribute Until now we did not support ATTRS{} matches against attributes we don't support in the core codebase. Implement now a simple lookup mechanism which traverses the tree of sysfs path from the port sysfs path to the physical device sysfs path, looking up the attribute requested. This is not completely equivalent to what udev does, because the udev rules matching ATTRS would usually also include an additional previous matching e.g. SUBSYSTEMS and such, so that the ATTRS is looked up exactly in the device that also matches the additional previous rules. In our case, we just simplify the logic and return the first one found. --- src/kerneldevice/mm-kernel-device-generic.c | 38 +++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/kerneldevice/mm-kernel-device-generic.c b/src/kerneldevice/mm-kernel-device-generic.c index e6e69b67..3b9956b2 100644 --- a/src/kerneldevice/mm-kernel-device-generic.c +++ b/src/kerneldevice/mm-kernel-device-generic.c @@ -123,6 +123,36 @@ read_sysfs_attribute_link_basename (const gchar *path, return g_path_get_basename (canonicalized_path); } +static gchar * +lookup_sysfs_attribute_as_string (MMKernelDeviceGeneric *self, + const gchar *attribute) +{ + g_autofree gchar *iter = NULL; + + /* if there is no parent sysfs path set, we look for the attribute + * only in the port sysfs path */ + if (!self->priv->physdev_sysfs_path) + return read_sysfs_attribute_as_string (self->priv->sysfs_path, attribute); + + iter = g_strdup (self->priv->sysfs_path); + while (iter) { + g_autofree gchar *parent = NULL; + gchar *value; + + /* return first one found */ + if ((value = read_sysfs_attribute_as_string (iter, attribute)) != NULL) + return value; + + if (g_strcmp0 (iter, self->priv->physdev_sysfs_path) == 0) + break; + parent = g_path_get_dirname (iter); + g_clear_pointer (&iter, g_free); + iter = g_steal_pointer (&parent); + } + + return NULL; +} + /*****************************************************************************/ /* Load contents */ @@ -780,8 +810,12 @@ check_condition (MMKernelDeviceGeneric *self, else if (g_str_equal (attribute, "bInterfaceNumber")) result = (g_str_equal (match->value, "?*") || ((mm_get_uint_from_hex_str (match->value, &val)) && ((self->priv->interface_number == val) == condition_equal))); - else - mm_obj_warn (self, "unknown attribute: %s", attribute); + else { + g_autofree gchar *found_value = NULL; + + found_value = lookup_sysfs_attribute_as_string (self, attribute); + result = ((found_value && g_str_equal (found_value, match->value)) == condition_equal); + } g_free (contents); g_free (attribute); -- cgit v1.2.3