From 1c7b9d0edf5ada916fd02e66355f79f2089ee095 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Thu, 8 Oct 2015 10:32:26 +0200 Subject: [PATCH] leds: triggers: add invert to heartbeat This patch adds possibility to invert heartbeat blinking. The inverted LED is more time ON then OFF. It's because it looks better when the heartbeat LED is next to other LED which is most time ON. The invert value is exported same way via sysfs in file invert like oneshot. I get inspiration from this trigger. Signed-off-by: Jiri Prchal Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-heartbeat.c | 47 +++++++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index fea6871d2609..8622ce651ae2 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -27,6 +27,7 @@ struct heartbeat_trig_data { unsigned int phase; unsigned int period; struct timer_list timer; + unsigned int invert; }; static void led_heartbeat_function(unsigned long data) @@ -56,21 +57,27 @@ static void led_heartbeat_function(unsigned long data) msecs_to_jiffies(heartbeat_data->period); delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = led_cdev->max_brightness; + if (!heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; case 1: delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase++; + if (heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; case 2: delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = led_cdev->max_brightness; + if (!heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; default: delay = heartbeat_data->period - heartbeat_data->period / 4 - msecs_to_jiffies(70); heartbeat_data->phase = 0; + if (heartbeat_data->invert) + brightness = led_cdev->max_brightness; break; } @@ -78,15 +85,50 @@ static void led_heartbeat_function(unsigned long data) mod_timer(&heartbeat_data->timer, jiffies + delay); } +static ssize_t led_invert_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + + return sprintf(buf, "%u\n", heartbeat_data->invert); +} + +static ssize_t led_invert_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + unsigned long state; + int ret; + + ret = kstrtoul(buf, 0, &state); + if (ret) + return ret; + + heartbeat_data->invert = !!state; + + return size; +} + +static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); + static void heartbeat_trig_activate(struct led_classdev *led_cdev) { struct heartbeat_trig_data *heartbeat_data; + int rc; heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); if (!heartbeat_data) return; led_cdev->trigger_data = heartbeat_data; + rc = device_create_file(led_cdev->dev, &dev_attr_invert); + if (rc) { + kfree(led_cdev->trigger_data); + return; + } + setup_timer(&heartbeat_data->timer, led_heartbeat_function, (unsigned long) led_cdev); heartbeat_data->phase = 0; @@ -100,6 +142,7 @@ static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) if (led_cdev->activated) { del_timer_sync(&heartbeat_data->timer); + device_remove_file(led_cdev->dev, &dev_attr_invert); kfree(heartbeat_data); led_cdev->activated = false; } -- 2.20.1