diff options
author | Fabio Baltieri <fabio.baltieri@gmail.com> | 2012-06-06 18:11:05 -0400 |
---|---|---|
committer | Bryan Wu <bryan.wu@canonical.com> | 2012-07-23 19:52:34 -0400 |
commit | 5e417281cde2ef56e9eb1a95d080d6254402e794 (patch) | |
tree | 142bdedb0e099b96276c0e094bf89a10251a7bc4 /drivers/leds | |
parent | 437864828d82b9dee50b5741106fbf5fa12b139a (diff) |
leds: add oneshot trigger
Add oneshot trigger to blink a led with configurale parameters via
sysfs.
Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
Cc: Shuah Khan <shuahkhan@gmail.com>
Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 14 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/ledtrig-oneshot.c | 204 |
3 files changed, 219 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 12b2b55c519e..54dd1a396fa9 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -443,6 +443,20 @@ config LEDS_TRIGGER_TIMER | |||
443 | 443 | ||
444 | If unsure, say Y. | 444 | If unsure, say Y. |
445 | 445 | ||
446 | config LEDS_TRIGGER_ONESHOT | ||
447 | tristate "LED One-shot Trigger" | ||
448 | depends on LEDS_TRIGGERS | ||
449 | help | ||
450 | This allows LEDs to blink in one-shot pulses with parameters | ||
451 | controlled via sysfs. It's useful to notify the user on | ||
452 | sporadic events, when there are no clear begin and end trap points, | ||
453 | or on dense events, where this blinks the LED at constant rate if | ||
454 | rearmed continuously. | ||
455 | |||
456 | It also shows how to use the led_blink_set_oneshot() function. | ||
457 | |||
458 | If unsure, say Y. | ||
459 | |||
446 | config LEDS_TRIGGER_IDE_DISK | 460 | config LEDS_TRIGGER_IDE_DISK |
447 | bool "LED IDE Disk Trigger" | 461 | bool "LED IDE Disk Trigger" |
448 | depends on IDE_GD_ATA | 462 | depends on IDE_GD_ATA |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index f8958cd6cf6e..9112d518f9d4 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o | |||
53 | 53 | ||
54 | # LED Triggers | 54 | # LED Triggers |
55 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o | 55 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o |
56 | obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o | ||
56 | obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o | 57 | obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o |
57 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o | 58 | obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o |
58 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o | 59 | obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o |
diff --git a/drivers/leds/ledtrig-oneshot.c b/drivers/leds/ledtrig-oneshot.c new file mode 100644 index 000000000000..5c9edf7f489c --- /dev/null +++ b/drivers/leds/ledtrig-oneshot.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * One-shot LED Trigger | ||
3 | * | ||
4 | * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com> | ||
5 | * | ||
6 | * Based on ledtrig-timer.c by Richard Purdie <rpurdie@openedhand.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/leds.h> | ||
21 | #include "leds.h" | ||
22 | |||
23 | #define DEFAULT_DELAY 100 | ||
24 | |||
25 | struct oneshot_trig_data { | ||
26 | unsigned int invert; | ||
27 | }; | ||
28 | |||
29 | static ssize_t led_shot(struct device *dev, | ||
30 | struct device_attribute *attr, const char *buf, size_t size) | ||
31 | { | ||
32 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
33 | struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; | ||
34 | |||
35 | led_blink_set_oneshot(led_cdev, | ||
36 | &led_cdev->blink_delay_on, &led_cdev->blink_delay_off, | ||
37 | oneshot_data->invert); | ||
38 | |||
39 | /* content is ignored */ | ||
40 | return size; | ||
41 | } | ||
42 | static ssize_t led_invert_show(struct device *dev, | ||
43 | struct device_attribute *attr, char *buf) | ||
44 | { | ||
45 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
46 | struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; | ||
47 | |||
48 | return sprintf(buf, "%u\n", oneshot_data->invert); | ||
49 | } | ||
50 | |||
51 | static ssize_t led_invert_store(struct device *dev, | ||
52 | struct device_attribute *attr, const char *buf, size_t size) | ||
53 | { | ||
54 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
55 | struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; | ||
56 | unsigned long state; | ||
57 | int ret; | ||
58 | |||
59 | ret = kstrtoul(buf, 0, &state); | ||
60 | if (ret) | ||
61 | return ret; | ||
62 | |||
63 | oneshot_data->invert = !!state; | ||
64 | |||
65 | if (oneshot_data->invert) | ||
66 | led_set_brightness(led_cdev, LED_FULL); | ||
67 | else | ||
68 | led_set_brightness(led_cdev, LED_OFF); | ||
69 | |||
70 | return size; | ||
71 | } | ||
72 | |||
73 | static ssize_t led_delay_on_show(struct device *dev, | ||
74 | struct device_attribute *attr, char *buf) | ||
75 | { | ||
76 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
77 | |||
78 | return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); | ||
79 | } | ||
80 | |||
81 | static ssize_t led_delay_on_store(struct device *dev, | ||
82 | struct device_attribute *attr, const char *buf, size_t size) | ||
83 | { | ||
84 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
85 | unsigned long state; | ||
86 | int ret; | ||
87 | |||
88 | ret = kstrtoul(buf, 0, &state); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | |||
92 | led_cdev->blink_delay_on = state; | ||
93 | |||
94 | return size; | ||
95 | } | ||
96 | static ssize_t led_delay_off_show(struct device *dev, | ||
97 | struct device_attribute *attr, char *buf) | ||
98 | { | ||
99 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
100 | |||
101 | return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); | ||
102 | } | ||
103 | |||
104 | static ssize_t led_delay_off_store(struct device *dev, | ||
105 | struct device_attribute *attr, const char *buf, size_t size) | ||
106 | { | ||
107 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
108 | unsigned long state; | ||
109 | int ret; | ||
110 | |||
111 | ret = kstrtoul(buf, 0, &state); | ||
112 | if (ret) | ||
113 | return ret; | ||
114 | |||
115 | led_cdev->blink_delay_off = state; | ||
116 | |||
117 | return size; | ||
118 | } | ||
119 | |||
120 | static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); | ||
121 | static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); | ||
122 | static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); | ||
123 | static DEVICE_ATTR(shot, 0200, NULL, led_shot); | ||
124 | |||
125 | static void oneshot_trig_activate(struct led_classdev *led_cdev) | ||
126 | { | ||
127 | struct oneshot_trig_data *oneshot_data; | ||
128 | int rc; | ||
129 | |||
130 | oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); | ||
131 | if (!oneshot_data) | ||
132 | return; | ||
133 | |||
134 | led_cdev->trigger_data = oneshot_data; | ||
135 | |||
136 | rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); | ||
137 | if (rc) | ||
138 | goto err_out_trig_data; | ||
139 | rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); | ||
140 | if (rc) | ||
141 | goto err_out_delayon; | ||
142 | rc = device_create_file(led_cdev->dev, &dev_attr_invert); | ||
143 | if (rc) | ||
144 | goto err_out_delayoff; | ||
145 | rc = device_create_file(led_cdev->dev, &dev_attr_shot); | ||
146 | if (rc) | ||
147 | goto err_out_invert; | ||
148 | |||
149 | led_cdev->blink_delay_on = DEFAULT_DELAY; | ||
150 | led_cdev->blink_delay_off = DEFAULT_DELAY; | ||
151 | |||
152 | led_cdev->activated = true; | ||
153 | |||
154 | return; | ||
155 | |||
156 | err_out_invert: | ||
157 | device_remove_file(led_cdev->dev, &dev_attr_invert); | ||
158 | err_out_delayoff: | ||
159 | device_remove_file(led_cdev->dev, &dev_attr_delay_off); | ||
160 | err_out_delayon: | ||
161 | device_remove_file(led_cdev->dev, &dev_attr_delay_on); | ||
162 | err_out_trig_data: | ||
163 | kfree(led_cdev->trigger_data); | ||
164 | } | ||
165 | |||
166 | static void oneshot_trig_deactivate(struct led_classdev *led_cdev) | ||
167 | { | ||
168 | struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; | ||
169 | |||
170 | if (led_cdev->activated) { | ||
171 | device_remove_file(led_cdev->dev, &dev_attr_delay_on); | ||
172 | device_remove_file(led_cdev->dev, &dev_attr_delay_off); | ||
173 | device_remove_file(led_cdev->dev, &dev_attr_invert); | ||
174 | device_remove_file(led_cdev->dev, &dev_attr_shot); | ||
175 | kfree(oneshot_data); | ||
176 | led_cdev->activated = false; | ||
177 | } | ||
178 | |||
179 | /* Stop blinking */ | ||
180 | led_brightness_set(led_cdev, LED_OFF); | ||
181 | } | ||
182 | |||
183 | static struct led_trigger oneshot_led_trigger = { | ||
184 | .name = "oneshot", | ||
185 | .activate = oneshot_trig_activate, | ||
186 | .deactivate = oneshot_trig_deactivate, | ||
187 | }; | ||
188 | |||
189 | static int __init oneshot_trig_init(void) | ||
190 | { | ||
191 | return led_trigger_register(&oneshot_led_trigger); | ||
192 | } | ||
193 | |||
194 | static void __exit oneshot_trig_exit(void) | ||
195 | { | ||
196 | led_trigger_unregister(&oneshot_led_trigger); | ||
197 | } | ||
198 | |||
199 | module_init(oneshot_trig_init); | ||
200 | module_exit(oneshot_trig_exit); | ||
201 | |||
202 | MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>"); | ||
203 | MODULE_DESCRIPTION("One-shot LED trigger"); | ||
204 | MODULE_LICENSE("GPL"); | ||