0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/device.h>
0014 #include <linux/ctype.h>
0015 #include <linux/slab.h>
0016 #include <linux/leds.h>
0017 #include "../leds.h"
0018
0019 #define DEFAULT_DELAY 100
0020
0021 struct oneshot_trig_data {
0022 unsigned int invert;
0023 };
0024
0025 static ssize_t led_shot(struct device *dev,
0026 struct device_attribute *attr, const char *buf, size_t size)
0027 {
0028 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0029 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
0030
0031 led_blink_set_oneshot(led_cdev,
0032 &led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
0033 oneshot_data->invert);
0034
0035
0036 return size;
0037 }
0038 static ssize_t led_invert_show(struct device *dev,
0039 struct device_attribute *attr, char *buf)
0040 {
0041 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
0042
0043 return sprintf(buf, "%u\n", oneshot_data->invert);
0044 }
0045
0046 static ssize_t led_invert_store(struct device *dev,
0047 struct device_attribute *attr, const char *buf, size_t size)
0048 {
0049 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0050 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
0051 unsigned long state;
0052 int ret;
0053
0054 ret = kstrtoul(buf, 0, &state);
0055 if (ret)
0056 return ret;
0057
0058 oneshot_data->invert = !!state;
0059
0060 if (oneshot_data->invert)
0061 led_set_brightness_nosleep(led_cdev, LED_FULL);
0062 else
0063 led_set_brightness_nosleep(led_cdev, LED_OFF);
0064
0065 return size;
0066 }
0067
0068 static ssize_t led_delay_on_show(struct device *dev,
0069 struct device_attribute *attr, char *buf)
0070 {
0071 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0072
0073 return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
0074 }
0075
0076 static ssize_t led_delay_on_store(struct device *dev,
0077 struct device_attribute *attr, const char *buf, size_t size)
0078 {
0079 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0080 unsigned long state;
0081 int ret;
0082
0083 ret = kstrtoul(buf, 0, &state);
0084 if (ret)
0085 return ret;
0086
0087 led_cdev->blink_delay_on = state;
0088
0089 return size;
0090 }
0091
0092 static ssize_t led_delay_off_show(struct device *dev,
0093 struct device_attribute *attr, char *buf)
0094 {
0095 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0096
0097 return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
0098 }
0099
0100 static ssize_t led_delay_off_store(struct device *dev,
0101 struct device_attribute *attr, const char *buf, size_t size)
0102 {
0103 struct led_classdev *led_cdev = led_trigger_get_led(dev);
0104 unsigned long state;
0105 int ret;
0106
0107 ret = kstrtoul(buf, 0, &state);
0108 if (ret)
0109 return ret;
0110
0111 led_cdev->blink_delay_off = state;
0112
0113 return size;
0114 }
0115
0116 static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
0117 static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
0118 static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
0119 static DEVICE_ATTR(shot, 0200, NULL, led_shot);
0120
0121 static struct attribute *oneshot_trig_attrs[] = {
0122 &dev_attr_delay_on.attr,
0123 &dev_attr_delay_off.attr,
0124 &dev_attr_invert.attr,
0125 &dev_attr_shot.attr,
0126 NULL
0127 };
0128 ATTRIBUTE_GROUPS(oneshot_trig);
0129
0130 static void pattern_init(struct led_classdev *led_cdev)
0131 {
0132 u32 *pattern;
0133 unsigned int size = 0;
0134
0135 pattern = led_get_default_pattern(led_cdev, &size);
0136 if (!pattern)
0137 goto out_default;
0138
0139 if (size != 2) {
0140 dev_warn(led_cdev->dev,
0141 "Expected 2 but got %u values for delays pattern\n",
0142 size);
0143 goto out_default;
0144 }
0145
0146 led_cdev->blink_delay_on = pattern[0];
0147 led_cdev->blink_delay_off = pattern[1];
0148 kfree(pattern);
0149
0150 return;
0151
0152 out_default:
0153 kfree(pattern);
0154 led_cdev->blink_delay_on = DEFAULT_DELAY;
0155 led_cdev->blink_delay_off = DEFAULT_DELAY;
0156 }
0157
0158 static int oneshot_trig_activate(struct led_classdev *led_cdev)
0159 {
0160 struct oneshot_trig_data *oneshot_data;
0161
0162 oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
0163 if (!oneshot_data)
0164 return -ENOMEM;
0165
0166 led_set_trigger_data(led_cdev, oneshot_data);
0167
0168 if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
0169 pattern_init(led_cdev);
0170
0171
0172
0173
0174 led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
0175 }
0176
0177 return 0;
0178 }
0179
0180 static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
0181 {
0182 struct oneshot_trig_data *oneshot_data = led_get_trigger_data(led_cdev);
0183
0184 kfree(oneshot_data);
0185
0186
0187 led_set_brightness(led_cdev, LED_OFF);
0188 }
0189
0190 static struct led_trigger oneshot_led_trigger = {
0191 .name = "oneshot",
0192 .activate = oneshot_trig_activate,
0193 .deactivate = oneshot_trig_deactivate,
0194 .groups = oneshot_trig_groups,
0195 };
0196 module_led_trigger(oneshot_led_trigger);
0197
0198 MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
0199 MODULE_DESCRIPTION("One-shot LED trigger");
0200 MODULE_LICENSE("GPL v2");