leds: class: Store the color index in struct led_classdev
authorJean-Jacques Hiblot <jjhiblot@traphandler.com>
Fri, 28 Jul 2023 15:37:29 +0000 (17:37 +0200)
committerLee Jones <lee@kernel.org>
Thu, 17 Aug 2023 08:00:34 +0000 (09:00 +0100)
Store the color of the LED so that it is not lost after the LED's
name has been composed. This color information can then be exposed to
the user space or used by the LED consumer.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
Link: https://lore.kernel.org/r/20230728153731.3742339-3-jjhiblot@traphandler.com
Signed-off-by: Lee Jones <lee@kernel.org>
Documentation/ABI/testing/sysfs-class-led
drivers/leds/led-class.c
include/linux/leds.h

index 2e24ac3bd7efa4e64d8dc084462cc0ef92dc9202..b2ff0012c0f2b8df7d843fc50f3568c0ca03f715 100644 (file)
@@ -59,6 +59,15 @@ Description:
                brightness. Reading this file when no hw brightness change
                event has happened will return an ENODATA error.
 
+What:          /sys/class/leds/<led>/color
+Date:          June 2023
+KernelVersion: 6.5
+Description:
+               Color of the LED.
+
+               This is a read-only file. Reading this file returns the color
+               of the LED as a string (e.g: "red", "green", "multicolor").
+
 What:          /sys/class/leds/<led>/trigger
 Date:          March 2006
 KernelVersion: 2.6.17
index 78068b06d009a0713b2b20ee9fc506efe122663c..4bcbd46ec75a0a04cf567e677221403a232d8287 100644 (file)
@@ -76,6 +76,19 @@ static ssize_t max_brightness_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(max_brightness);
 
+static ssize_t color_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       const char *color_text = "invalid";
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+       if (led_cdev->color < LED_COLOR_ID_MAX)
+               color_text = led_colors[led_cdev->color];
+
+       return sysfs_emit(buf, "%s\n", color_text);
+}
+static DEVICE_ATTR_RO(color);
+
 #ifdef CONFIG_LEDS_TRIGGERS
 static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0);
 static struct bin_attribute *led_trigger_bin_attrs[] = {
@@ -90,6 +103,7 @@ static const struct attribute_group led_trigger_group = {
 static struct attribute *led_class_attrs[] = {
        &dev_attr_brightness.attr,
        &dev_attr_max_brightness.attr,
+       &dev_attr_color.attr,
        NULL,
 };
 
@@ -486,6 +500,10 @@ int led_classdev_register_ext(struct device *parent,
                        fwnode_property_read_u32(init_data->fwnode,
                                "max-brightness",
                                &led_cdev->max_brightness);
+
+                       if (fwnode_property_present(init_data->fwnode, "color"))
+                               fwnode_property_read_u32(init_data->fwnode, "color",
+                                                        &led_cdev->color);
                }
        } else {
                proposed_name = led_cdev->name;
@@ -495,6 +513,9 @@ int led_classdev_register_ext(struct device *parent,
        if (ret < 0)
                return ret;
 
+       if (led_cdev->color >= LED_COLOR_ID_MAX)
+               dev_warn(parent, "LED %s color identifier out of range\n", final_name);
+
        mutex_init(&led_cdev->led_access);
        mutex_lock(&led_cdev->led_access);
        led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
index 8740b4e47f88922fa6ba3f6e861fc6b2a6e2e1f4..aa16dc2a8230fa50ebcb6c8005f8806922e0d958 100644 (file)
@@ -100,6 +100,7 @@ struct led_classdev {
        const char              *name;
        unsigned int brightness;
        unsigned int max_brightness;
+       unsigned int color;
        int                      flags;
 
        /* Lower 16 bits reflect status */