4 * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
6 * Based on ledtrig-timer.c by Richard Purdie <rpurdie@openedhand.com>
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.
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>
23 #define DEFAULT_DELAY 100
25 struct oneshot_trig_data
{
29 static ssize_t
led_shot(struct device
*dev
,
30 struct device_attribute
*attr
, const char *buf
, size_t size
)
32 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
33 struct oneshot_trig_data
*oneshot_data
= led_cdev
->trigger_data
;
35 led_blink_set_oneshot(led_cdev
,
36 &led_cdev
->blink_delay_on
, &led_cdev
->blink_delay_off
,
37 oneshot_data
->invert
);
39 /* content is ignored */
42 static ssize_t
led_invert_show(struct device
*dev
,
43 struct device_attribute
*attr
, char *buf
)
45 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
46 struct oneshot_trig_data
*oneshot_data
= led_cdev
->trigger_data
;
48 return sprintf(buf
, "%u\n", oneshot_data
->invert
);
51 static ssize_t
led_invert_store(struct device
*dev
,
52 struct device_attribute
*attr
, const char *buf
, size_t size
)
54 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
55 struct oneshot_trig_data
*oneshot_data
= led_cdev
->trigger_data
;
59 ret
= kstrtoul(buf
, 0, &state
);
63 oneshot_data
->invert
= !!state
;
65 if (oneshot_data
->invert
)
66 led_set_brightness_nosleep(led_cdev
, LED_FULL
);
68 led_set_brightness_nosleep(led_cdev
, LED_OFF
);
73 static ssize_t
led_delay_on_show(struct device
*dev
,
74 struct device_attribute
*attr
, char *buf
)
76 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
78 return sprintf(buf
, "%lu\n", led_cdev
->blink_delay_on
);
81 static ssize_t
led_delay_on_store(struct device
*dev
,
82 struct device_attribute
*attr
, const char *buf
, size_t size
)
84 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
88 ret
= kstrtoul(buf
, 0, &state
);
92 led_cdev
->blink_delay_on
= state
;
96 static ssize_t
led_delay_off_show(struct device
*dev
,
97 struct device_attribute
*attr
, char *buf
)
99 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
101 return sprintf(buf
, "%lu\n", led_cdev
->blink_delay_off
);
104 static ssize_t
led_delay_off_store(struct device
*dev
,
105 struct device_attribute
*attr
, const char *buf
, size_t size
)
107 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
111 ret
= kstrtoul(buf
, 0, &state
);
115 led_cdev
->blink_delay_off
= state
;
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
);
125 static void oneshot_trig_activate(struct led_classdev
*led_cdev
)
127 struct oneshot_trig_data
*oneshot_data
;
130 oneshot_data
= kzalloc(sizeof(*oneshot_data
), GFP_KERNEL
);
134 led_cdev
->trigger_data
= oneshot_data
;
136 rc
= device_create_file(led_cdev
->dev
, &dev_attr_delay_on
);
138 goto err_out_trig_data
;
139 rc
= device_create_file(led_cdev
->dev
, &dev_attr_delay_off
);
141 goto err_out_delayon
;
142 rc
= device_create_file(led_cdev
->dev
, &dev_attr_invert
);
144 goto err_out_delayoff
;
145 rc
= device_create_file(led_cdev
->dev
, &dev_attr_shot
);
149 led_cdev
->blink_delay_on
= DEFAULT_DELAY
;
150 led_cdev
->blink_delay_off
= DEFAULT_DELAY
;
152 led_cdev
->activated
= true;
157 device_remove_file(led_cdev
->dev
, &dev_attr_invert
);
159 device_remove_file(led_cdev
->dev
, &dev_attr_delay_off
);
161 device_remove_file(led_cdev
->dev
, &dev_attr_delay_on
);
163 kfree(led_cdev
->trigger_data
);
166 static void oneshot_trig_deactivate(struct led_classdev
*led_cdev
)
168 struct oneshot_trig_data
*oneshot_data
= led_cdev
->trigger_data
;
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
);
176 led_cdev
->activated
= false;
180 led_set_brightness(led_cdev
, LED_OFF
);
183 static struct led_trigger oneshot_led_trigger
= {
185 .activate
= oneshot_trig_activate
,
186 .deactivate
= oneshot_trig_deactivate
,
189 static int __init
oneshot_trig_init(void)
191 return led_trigger_register(&oneshot_led_trigger
);
194 static void __exit
oneshot_trig_exit(void)
196 led_trigger_unregister(&oneshot_led_trigger
);
199 module_init(oneshot_trig_init
);
200 module_exit(oneshot_trig_exit
);
202 MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
203 MODULE_DESCRIPTION("One-shot LED trigger");
204 MODULE_LICENSE("GPL v2");