* [PATCH 1/2] leds: accept trigger parameters in "trigger:params" format
[not found] <1348915776.459857.1763933207303.ref@mail.yahoo.com>
@ 2025-11-23 21:26 ` Mieczyslaw Nalewaj
2025-11-24 14:17 ` Pavel Machek
0 siblings, 1 reply; 2+ messages in thread
From: Mieczyslaw Nalewaj @ 2025-11-23 21:26 UTC (permalink / raw)
To: linux-kernel@vger.kernel.org
Cc: linux-leds@vger.kernel.org, pavel@ucw.cz,
jacek.anaszewski@gmail.com
Allow parameters to be passed along with the trigger name when
writing to /sys/class/leds/<led>/trigger in the format:
echo "trigger_name:params" > /sys/class/leds/<led>/trigger
Core stores the RHS in led_cdev->params for the duration of the
activate() call; triggers may read and optionally consume or copy it.
Core frees any remaining buffer after activate() returns.
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -33,6 +33,12 @@ trigger_relevant(struct led_classdev *le
return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
}
+/*
+ * core: accept "<trigger>" or "<trigger>:<params>" and pass params via led_cdev->params.
+ * - If a colon is present, the RHS is duplicated and stored in led_cdev->params.
+ * - The trigger's activate callback may consume the pointer (free it and set to NULL).
+ * - If the trigger does not consume it, core frees the buffer after activate returns.
+ */
ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t pos, size_t count)
@@ -41,6 +47,10 @@ ssize_t led_trigger_write(struct file *f
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_trigger *trig;
int ret = count;
+ char *tmp = NULL;
+ char *params = NULL;
+ char *pcolon;
+ bool found = false;
mutex_lock(&led_cdev->led_access);
@@ -49,26 +59,81 @@ ssize_t led_trigger_write(struct file *f
goto unlock;
}
- if (sysfs_streq(buf, "none")) {
- led_trigger_remove(led_cdev);
+ /* copy input and NUL-terminate; trim trailing newline if present */
+ tmp = kstrndup(buf, count, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
goto unlock;
}
+ if (strlen(tmp) && tmp[strlen(tmp) - 1] == '\n')
+ tmp[strlen(tmp) - 1] = '\0';
+
+ /* handle special keywords */
+ if (sysfs_streq(tmp, "none")) {
+ led_trigger_remove(led_cdev);
+ goto out_free;
+ }
+ if (sysfs_streq(tmp, "default")) {
+ led_trigger_set_default(led_cdev);
+ goto out_free;
+ }
+
+ /* split on first ':' to accept "<trigger>" or "<trigger>:<params>" */
+ pcolon = strchr(tmp, ':');
+ if (pcolon) {
+ *pcolon = '\0';
+ params = kstrdup(pcolon + 1, GFP_KERNEL);
+ if (!params) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+ }
down_read(&triggers_list_lock);
list_for_each_entry(trig, &trigger_list, next_trig) {
- if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
+ if (!trigger_relevant(led_cdev, trig))
+ continue;
+
+ if (sysfs_streq(tmp, trig->name)) {
down_write(&led_cdev->trigger_lock);
+
+ /* attach transient params to led_cdev before setting trigger */
+ if (params) {
+ kfree(led_cdev->params);
+ led_cdev->params = params;
+ params = NULL; /* ownership transferred */
+ } else {
+ kfree(led_cdev->params);
+ led_cdev->params = NULL;
+ }
+
+ /* set the trigger (this will call trig->activate/led_trigger_set) */
led_trigger_set(led_cdev, trig);
up_write(&led_cdev->trigger_lock);
- up_read(&triggers_list_lock);
- goto unlock;
+ found = true;
+ break;
}
}
- /* we come here only if buf matches no trigger */
- ret = -EINVAL;
up_read(&triggers_list_lock);
+ if (!found) {
+ /* no matching trigger name found */
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ /* If the trigger didn't consume the transient params, free it now. */
+ down_write(&led_cdev->trigger_lock);
+ if (led_cdev->params) {
+ kfree(led_cdev->params);
+ led_cdev->params = NULL;
+ }
+ up_write(&led_cdev->trigger_lock);
+
+out_free:
+ kfree(tmp);
+ kfree(params); /* free if not attached */
unlock:
mutex_unlock(&led_cdev->led_access);
return ret;
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -240,6 +240,17 @@ struct led_classdev {
/* Ensures consistent access to the LED class device */
struct mutex led_access;
+ /*
+ * Optional transient parameter provided by core when user writes
+ * "<trigger_name>:<param>" to /sys/class/leds/<led>/trigger.
+ * - Core allocates a NUL-terminated string and stores it here before
+ * calling trigger->activate(led_cdev).
+ * - Trigger may "consume" the string by freeing it and setting the
+ * pointer to NULL.
+ * - If the trigger does not consume it, core frees the buffer after
+ * activate returns.
+ */
+ char *params;
};
/**
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 1/2] leds: accept trigger parameters in "trigger:params" format
2025-11-23 21:26 ` [PATCH 1/2] leds: accept trigger parameters in "trigger:params" format Mieczyslaw Nalewaj
@ 2025-11-24 14:17 ` Pavel Machek
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Machek @ 2025-11-24 14:17 UTC (permalink / raw)
To: Mieczyslaw Nalewaj
Cc: linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org,
jacek.anaszewski@gmail.com
[-- Attachment #1: Type: text/plain, Size: 5597 bytes --]
Hi!
> Allow parameters to be passed along with the trigger name when
> writing to /sys/class/leds/<led>/trigger in the format:
> echo "trigger_name:params" > /sys/class/leds/<led>/trigger
There's "one value per sysfs file" rule. Lets not do this.
Normal way is that trigger creates separate sysfs files for
parameters.
Best regards,
Pavel
> Core stores the RHS in led_cdev->params for the duration of the
> activate() call; triggers may read and optionally consume or copy it.
> Core frees any remaining buffer after activate() returns.
>
> Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
>
> --- a/drivers/leds/led-triggers.c
> +++ b/drivers/leds/led-triggers.c
> @@ -33,6 +33,12 @@ trigger_relevant(struct led_classdev *le
> return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
> }
>
> +/*
> + * core: accept "<trigger>" or "<trigger>:<params>" and pass params via led_cdev->params.
> + * - If a colon is present, the RHS is duplicated and stored in led_cdev->params.
> + * - The trigger's activate callback may consume the pointer (free it and set to NULL).
> + * - If the trigger does not consume it, core frees the buffer after activate returns.
> + */
> ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
> struct bin_attribute *bin_attr, char *buf,
> loff_t pos, size_t count)
> @@ -41,6 +47,10 @@ ssize_t led_trigger_write(struct file *f
> struct led_classdev *led_cdev = dev_get_drvdata(dev);
> struct led_trigger *trig;
> int ret = count;
> + char *tmp = NULL;
> + char *params = NULL;
> + char *pcolon;
> + bool found = false;
>
> mutex_lock(&led_cdev->led_access);
>
> @@ -49,26 +59,81 @@ ssize_t led_trigger_write(struct file *f
> goto unlock;
> }
>
> - if (sysfs_streq(buf, "none")) {
> - led_trigger_remove(led_cdev);
> + /* copy input and NUL-terminate; trim trailing newline if present */
> + tmp = kstrndup(buf, count, GFP_KERNEL);
> + if (!tmp) {
> + ret = -ENOMEM;
> goto unlock;
> }
> + if (strlen(tmp) && tmp[strlen(tmp) - 1] == '\n')
> + tmp[strlen(tmp) - 1] = '\0';
> +
> + /* handle special keywords */
> + if (sysfs_streq(tmp, "none")) {
> + led_trigger_remove(led_cdev);
> + goto out_free;
> + }
> + if (sysfs_streq(tmp, "default")) {
> + led_trigger_set_default(led_cdev);
> + goto out_free;
> + }
> +
> + /* split on first ':' to accept "<trigger>" or "<trigger>:<params>" */
> + pcolon = strchr(tmp, ':');
> + if (pcolon) {
> + *pcolon = '\0';
> + params = kstrdup(pcolon + 1, GFP_KERNEL);
> + if (!params) {
> + ret = -ENOMEM;
> + goto out_free;
> + }
> + }
>
> down_read(&triggers_list_lock);
> list_for_each_entry(trig, &trigger_list, next_trig) {
> - if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
> + if (!trigger_relevant(led_cdev, trig))
> + continue;
> +
> + if (sysfs_streq(tmp, trig->name)) {
> down_write(&led_cdev->trigger_lock);
> +
> + /* attach transient params to led_cdev before setting trigger */
> + if (params) {
> + kfree(led_cdev->params);
> + led_cdev->params = params;
> + params = NULL; /* ownership transferred */
> + } else {
> + kfree(led_cdev->params);
> + led_cdev->params = NULL;
> + }
> +
> + /* set the trigger (this will call trig->activate/led_trigger_set) */
> led_trigger_set(led_cdev, trig);
> up_write(&led_cdev->trigger_lock);
>
> - up_read(&triggers_list_lock);
> - goto unlock;
> + found = true;
> + break;
> }
> }
> - /* we come here only if buf matches no trigger */
> - ret = -EINVAL;
> up_read(&triggers_list_lock);
>
> + if (!found) {
> + /* no matching trigger name found */
> + ret = -EINVAL;
> + goto out_free;
> + }
> +
> + /* If the trigger didn't consume the transient params, free it now. */
> + down_write(&led_cdev->trigger_lock);
> + if (led_cdev->params) {
> + kfree(led_cdev->params);
> + led_cdev->params = NULL;
> + }
> + up_write(&led_cdev->trigger_lock);
> +
> +out_free:
> + kfree(tmp);
> + kfree(params); /* free if not attached */
> unlock:
> mutex_unlock(&led_cdev->led_access);
> return ret;
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -240,6 +240,17 @@ struct led_classdev {
>
> /* Ensures consistent access to the LED class device */
> struct mutex led_access;
> + /*
> + * Optional transient parameter provided by core when user writes
> + * "<trigger_name>:<param>" to /sys/class/leds/<led>/trigger.
> + * - Core allocates a NUL-terminated string and stores it here before
> + * calling trigger->activate(led_cdev).
> + * - Trigger may "consume" the string by freeing it and setting the
> + * pointer to NULL.
> + * - If the trigger does not consume it, core frees the buffer after
> + * activate returns.
> + */
> + char *params;
> };
>
> /**
--
I don't work for Nazis and criminals, and neither should you.
Boycott Putin, Trump, Netanyahu and Musk!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-11-24 14:17 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1348915776.459857.1763933207303.ref@mail.yahoo.com>
2025-11-23 21:26 ` [PATCH 1/2] leds: accept trigger parameters in "trigger:params" format Mieczyslaw Nalewaj
2025-11-24 14:17 ` Pavel Machek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).