Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * LED Kernel Timer Trigger 4 : : * 5 : : * Copyright 2005-2006 Openedhand Ltd. 6 : : * 7 : : * Author: Richard Purdie <rpurdie@openedhand.com> 8 : : */ 9 : : 10 : : #include <linux/module.h> 11 : : #include <linux/kernel.h> 12 : : #include <linux/init.h> 13 : : #include <linux/device.h> 14 : : #include <linux/ctype.h> 15 : : #include <linux/slab.h> 16 : : #include <linux/leds.h> 17 : : 18 : 0 : static ssize_t led_delay_on_show(struct device *dev, 19 : : struct device_attribute *attr, char *buf) 20 : : { 21 : : struct led_classdev *led_cdev = led_trigger_get_led(dev); 22 : : 23 : 0 : return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); 24 : : } 25 : : 26 : 0 : static ssize_t led_delay_on_store(struct device *dev, 27 : : struct device_attribute *attr, const char *buf, size_t size) 28 : : { 29 : : struct led_classdev *led_cdev = led_trigger_get_led(dev); 30 : : unsigned long state; 31 : : ssize_t ret = -EINVAL; 32 : : 33 : : ret = kstrtoul(buf, 10, &state); 34 : 0 : if (ret) 35 : : return ret; 36 : : 37 : 0 : led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off); 38 : 0 : led_cdev->blink_delay_on = state; 39 : : 40 : 0 : return size; 41 : : } 42 : : 43 : 0 : static ssize_t led_delay_off_show(struct device *dev, 44 : : struct device_attribute *attr, char *buf) 45 : : { 46 : : struct led_classdev *led_cdev = led_trigger_get_led(dev); 47 : : 48 : 0 : return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); 49 : : } 50 : : 51 : 0 : static ssize_t led_delay_off_store(struct device *dev, 52 : : struct device_attribute *attr, const char *buf, size_t size) 53 : : { 54 : : struct led_classdev *led_cdev = led_trigger_get_led(dev); 55 : : unsigned long state; 56 : : ssize_t ret = -EINVAL; 57 : : 58 : : ret = kstrtoul(buf, 10, &state); 59 : 0 : if (ret) 60 : : return ret; 61 : : 62 : 0 : led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state); 63 : 0 : led_cdev->blink_delay_off = state; 64 : : 65 : 0 : return size; 66 : : } 67 : : 68 : : static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); 69 : : static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); 70 : : 71 : : static struct attribute *timer_trig_attrs[] = { 72 : : &dev_attr_delay_on.attr, 73 : : &dev_attr_delay_off.attr, 74 : : NULL 75 : : }; 76 : : ATTRIBUTE_GROUPS(timer_trig); 77 : : 78 : 0 : static void pattern_init(struct led_classdev *led_cdev) 79 : : { 80 : : u32 *pattern; 81 : 0 : unsigned int size = 0; 82 : : 83 : 0 : pattern = led_get_default_pattern(led_cdev, &size); 84 : 0 : if (!pattern) 85 : 0 : return; 86 : : 87 : 0 : if (size != 2) { 88 : 0 : dev_warn(led_cdev->dev, 89 : : "Expected 2 but got %u values for delays pattern\n", 90 : : size); 91 : 0 : goto out; 92 : : } 93 : : 94 : 0 : led_cdev->blink_delay_on = pattern[0]; 95 : 0 : led_cdev->blink_delay_off = pattern[1]; 96 : : /* led_blink_set() called by caller */ 97 : : 98 : : out: 99 : 0 : kfree(pattern); 100 : : } 101 : : 102 : 0 : static int timer_trig_activate(struct led_classdev *led_cdev) 103 : : { 104 : 0 : if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) { 105 : 0 : pattern_init(led_cdev); 106 : : /* 107 : : * Mark as initialized even on pattern_init() error because 108 : : * any consecutive call to it would produce the same error. 109 : : */ 110 : 0 : led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER; 111 : : } 112 : : 113 : : /* 114 : : * If "set brightness to 0" is pending in workqueue, we don't 115 : : * want that to be reordered after blink_set() 116 : : */ 117 : 0 : flush_work(&led_cdev->set_brightness_work); 118 : 0 : led_blink_set(led_cdev, &led_cdev->blink_delay_on, 119 : : &led_cdev->blink_delay_off); 120 : : 121 : 0 : return 0; 122 : : } 123 : : 124 : 0 : static void timer_trig_deactivate(struct led_classdev *led_cdev) 125 : : { 126 : : /* Stop blinking */ 127 : 0 : led_set_brightness(led_cdev, LED_OFF); 128 : 0 : } 129 : : 130 : : static struct led_trigger timer_led_trigger = { 131 : : .name = "timer", 132 : : .activate = timer_trig_activate, 133 : : .deactivate = timer_trig_deactivate, 134 : : .groups = timer_trig_groups, 135 : : }; 136 : 3 : module_led_trigger(timer_led_trigger); 137 : : 138 : : MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); 139 : : MODULE_DESCRIPTION("Timer LED trigger"); 140 : : MODULE_LICENSE("GPL v2");