| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * LED Kernel Timer Trigger | 
 | 3 |  * | 
 | 4 |  * Copyright 2005-2006 Openedhand Ltd. | 
 | 5 |  * | 
 | 6 |  * Author: 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 |  | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 14 | #include <linux/module.h> | 
 | 15 | #include <linux/kernel.h> | 
 | 16 | #include <linux/init.h> | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 17 | #include <linux/device.h> | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 18 | #include <linux/ctype.h> | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 19 | #include <linux/leds.h> | 
 | 20 | #include "leds.h" | 
 | 21 |  | 
| Németh Márton | 4d404fd | 2008-03-09 20:59:57 +0000 | [diff] [blame] | 22 | static ssize_t led_delay_on_show(struct device *dev, | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 23 | 		struct device_attribute *attr, char *buf) | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 24 | { | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 25 | 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 26 |  | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 27 | 	return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 28 | } | 
 | 29 |  | 
| Németh Márton | 4d404fd | 2008-03-09 20:59:57 +0000 | [diff] [blame] | 30 | static ssize_t led_delay_on_store(struct device *dev, | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 31 | 		struct device_attribute *attr, const char *buf, size_t size) | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 32 | { | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 33 | 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 34 | 	int ret = -EINVAL; | 
 | 35 | 	char *after; | 
 | 36 | 	unsigned long state = simple_strtoul(buf, &after, 10); | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 37 | 	size_t count = after - buf; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 38 |  | 
| André Goddard Rosa | e7d2860 | 2009-12-14 18:01:06 -0800 | [diff] [blame] | 39 | 	if (isspace(*after)) | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 40 | 		count++; | 
 | 41 |  | 
 | 42 | 	if (count == size) { | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 43 | 		led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off); | 
| Johan Hovold | 7a5caab | 2011-09-14 16:22:16 -0700 | [diff] [blame] | 44 | 		led_cdev->blink_delay_on = state; | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 45 | 		ret = count; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 46 | 	} | 
 | 47 |  | 
 | 48 | 	return ret; | 
 | 49 | } | 
 | 50 |  | 
| Németh Márton | 4d404fd | 2008-03-09 20:59:57 +0000 | [diff] [blame] | 51 | static ssize_t led_delay_off_show(struct device *dev, | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 52 | 		struct device_attribute *attr, char *buf) | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 53 | { | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 54 | 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 55 |  | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 56 | 	return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 57 | } | 
 | 58 |  | 
| Németh Márton | 4d404fd | 2008-03-09 20:59:57 +0000 | [diff] [blame] | 59 | static ssize_t led_delay_off_store(struct device *dev, | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 60 | 		struct device_attribute *attr, const char *buf, size_t size) | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 61 | { | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 62 | 	struct led_classdev *led_cdev = dev_get_drvdata(dev); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 63 | 	int ret = -EINVAL; | 
 | 64 | 	char *after; | 
 | 65 | 	unsigned long state = simple_strtoul(buf, &after, 10); | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 66 | 	size_t count = after - buf; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 67 |  | 
| André Goddard Rosa | e7d2860 | 2009-12-14 18:01:06 -0800 | [diff] [blame] | 68 | 	if (isspace(*after)) | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 69 | 		count++; | 
 | 70 |  | 
 | 71 | 	if (count == size) { | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 72 | 		led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state); | 
| Johan Hovold | 7a5caab | 2011-09-14 16:22:16 -0700 | [diff] [blame] | 73 | 		led_cdev->blink_delay_off = state; | 
| Richard Purdie | 3dc7b82 | 2006-05-15 09:44:17 -0700 | [diff] [blame] | 74 | 		ret = count; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 75 | 	} | 
 | 76 |  | 
 | 77 | 	return ret; | 
 | 78 | } | 
 | 79 |  | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 80 | static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); | 
 | 81 | static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 82 |  | 
 | 83 | static void timer_trig_activate(struct led_classdev *led_cdev) | 
 | 84 | { | 
| Jeff Garzik | 12fda16 | 2006-10-17 00:10:20 -0700 | [diff] [blame] | 85 | 	int rc; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 86 |  | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 87 | 	led_cdev->trigger_data = NULL; | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 88 |  | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 89 | 	rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); | 
 | 90 | 	if (rc) | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 91 | 		return; | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 92 | 	rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); | 
 | 93 | 	if (rc) | 
 | 94 | 		goto err_out_delayon; | 
| Jeff Garzik | 12fda16 | 2006-10-17 00:10:20 -0700 | [diff] [blame] | 95 |  | 
| Esben Haabendal | fff26f8 | 2011-05-24 17:13:22 -0700 | [diff] [blame] | 96 | 	led_blink_set(led_cdev, &led_cdev->blink_delay_on, | 
 | 97 | 		      &led_cdev->blink_delay_off); | 
 | 98 |  | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 99 | 	led_cdev->trigger_data = (void *)1; | 
| Márton Németh | 4c79141 | 2007-10-31 15:07:12 +0100 | [diff] [blame] | 100 |  | 
| Jeff Garzik | 12fda16 | 2006-10-17 00:10:20 -0700 | [diff] [blame] | 101 | 	return; | 
 | 102 |  | 
 | 103 | err_out_delayon: | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 104 | 	device_remove_file(led_cdev->dev, &dev_attr_delay_on); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 105 | } | 
 | 106 |  | 
 | 107 | static void timer_trig_deactivate(struct led_classdev *led_cdev) | 
 | 108 | { | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 109 | 	if (led_cdev->trigger_data) { | 
| Richard Purdie | f8a7c6f | 2007-07-08 23:19:31 +0100 | [diff] [blame] | 110 | 		device_remove_file(led_cdev->dev, &dev_attr_delay_on); | 
 | 111 | 		device_remove_file(led_cdev->dev, &dev_attr_delay_off); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 112 | 	} | 
| Rodolfo Giometti | ce70a24 | 2009-01-08 19:50:15 +0000 | [diff] [blame] | 113 |  | 
| Johannes Berg | 5ada28b | 2010-11-11 14:05:21 -0800 | [diff] [blame] | 114 | 	/* Stop blinking */ | 
 | 115 | 	led_brightness_set(led_cdev, LED_OFF); | 
| Richard Purdie | 6655c6f | 2006-03-31 02:31:07 -0800 | [diff] [blame] | 116 | } | 
 | 117 |  | 
 | 118 | static struct led_trigger timer_led_trigger = { | 
 | 119 | 	.name     = "timer", | 
 | 120 | 	.activate = timer_trig_activate, | 
 | 121 | 	.deactivate = timer_trig_deactivate, | 
 | 122 | }; | 
 | 123 |  | 
 | 124 | static int __init timer_trig_init(void) | 
 | 125 | { | 
 | 126 | 	return led_trigger_register(&timer_led_trigger); | 
 | 127 | } | 
 | 128 |  | 
 | 129 | static void __exit timer_trig_exit(void) | 
 | 130 | { | 
 | 131 | 	led_trigger_unregister(&timer_led_trigger); | 
 | 132 | } | 
 | 133 |  | 
 | 134 | module_init(timer_trig_init); | 
 | 135 | module_exit(timer_trig_exit); | 
 | 136 |  | 
 | 137 | MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); | 
 | 138 | MODULE_DESCRIPTION("Timer LED trigger"); | 
 | 139 | MODULE_LICENSE("GPL"); |