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 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/init.h> 16 #include <linux/device.h> 17 #include <linux/ctype.h> 18 #include <linux/slab.h> 19 #include <linux/leds.h> 20 #include "../leds.h" 21 22 #define DEFAULT_DELAY 100 23 24 struct oneshot_trig_data { 25 unsigned int invert; 26 }; 27 28 static ssize_t led_shot(struct device *dev, 29 struct device_attribute *attr, const char *buf, size_t size) 30 { 31 struct led_classdev *led_cdev = led_trigger_get_led(dev); 32 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); 33 34 led_blink_set_oneshot(led_cdev, 35 &led_cdev->blink_delay_on, &led_cdev->blink_delay_off, 36 oneshot_data->invert); 37 38 /* content is ignored */ 39 return size; 40 } 41 static ssize_t led_invert_show(struct device *dev, 42 struct device_attribute *attr, char *buf) 43 { 44 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); 45 46 return sprintf(buf, "%u\n", oneshot_data->invert); 47 } 48 49 static ssize_t led_invert_store(struct device *dev, 50 struct device_attribute *attr, const char *buf, size_t size) 51 { 52 struct led_classdev *led_cdev = led_trigger_get_led(dev); 53 struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); 54 unsigned long state; 55 int ret; 56 57 ret = kstrtoul(buf, 0, &state); 58 if (ret) 59 return ret; 60 61 oneshot_data->invert = !!state; 62 63 if (oneshot_data->invert) 64 led_set_brightness_nosleep(led_cdev, LED_FULL); 65 else 66 led_set_brightness_nosleep(led_cdev, LED_OFF); 67 68 return size; 69 } 70 71 static ssize_t led_delay_on_show(struct device *dev, 72 struct device_attribute *attr, char *buf) 73 { 74 struct led_classdev *led_cdev = led_trigger_get_led(dev); 75 76 return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); 77 } 78 79 static ssize_t led_delay_on_store(struct device *dev, 80 struct device_attribute *attr, const char *buf, size_t size) 81 { 82 struct led_classdev *led_cdev = led_trigger_get_led(dev); 83 unsigned long state; 84 int ret; 85 86 ret = kstrtoul(buf, 0, &state); 87 if (ret) 88 return ret; 89 90 led_cdev->blink_delay_on = state; 91 92 return size; 93 } 94 95 static ssize_t led_delay_off_show(struct device *dev, 96 struct device_attribute *attr, char *buf) 97 { 98 struct led_classdev *led_cdev = led_trigger_get_led(dev); 99 100 return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); 101 } 102 103 static ssize_t led_delay_off_store(struct device *dev, 104 struct device_attribute *attr, const char *buf, size_t size) 105 { 106 struct led_classdev *led_cdev = led_trigger_get_led(dev); 107 unsigned long state; 108 int ret; 109 110 ret = kstrtoul(buf, 0, &state); 111 if (ret) 112 return ret; 113 114 led_cdev->blink_delay_off = state; 115 116 return size; 117 } 118 119 static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); 120 static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); 121 static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); 122 static DEVICE_ATTR(shot, 0200, NULL, led_shot); 123 124 static struct attribute *oneshot_trig_attrs[] = { 125 &dev_attr_delay_on.attr, 126 &dev_attr_delay_off.attr, 127 &dev_attr_invert.attr, 128 &dev_attr_shot.attr, 129 NULL 130 }; 131 ATTRIBUTE_GROUPS(oneshot_trig); 132 133 static int oneshot_trig_activate(struct led_classdev *led_cdev) 134 { 135 struct oneshot_trig_data *oneshot_data; 136 137 oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); 138 if (!oneshot_data) 139 return -ENOMEM; 140 141 led_set_trigger_data(led_cdev, oneshot_data); 142 143 led_cdev->blink_delay_on = DEFAULT_DELAY; 144 led_cdev->blink_delay_off = DEFAULT_DELAY; 145 146 return 0; 147 } 148 149 static void oneshot_trig_deactivate(struct led_classdev *led_cdev) 150 { 151 struct oneshot_trig_data *oneshot_data = led_get_trigger_data(led_cdev); 152 153 kfree(oneshot_data); 154 155 /* Stop blinking */ 156 led_set_brightness(led_cdev, LED_OFF); 157 } 158 159 static struct led_trigger oneshot_led_trigger = { 160 .name = "oneshot", 161 .activate = oneshot_trig_activate, 162 .deactivate = oneshot_trig_deactivate, 163 .groups = oneshot_trig_groups, 164 }; 165 module_led_trigger(oneshot_led_trigger); 166 167 MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>"); 168 MODULE_DESCRIPTION("One-shot LED trigger"); 169 MODULE_LICENSE("GPL v2"); 170