Merge remote branch 'tip/x86/tsc' into fortglx/2.6.38/tip/x86/tsc
[pandora-kernel.git] / arch / arm / kernel / leds.c
1 /*
2  * LED support code, ripped out of arch/arm/kernel/time.c
3  *
4  *  Copyright (C) 1994-2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/sysdev.h>
13
14 #include <asm/leds.h>
15
16 static void dummy_leds_event(led_event_t evt)
17 {
18 }
19
20 void (*leds_event)(led_event_t) = dummy_leds_event;
21
22 struct leds_evt_name {
23         const char      name[8];
24         int             on;
25         int             off;
26 };
27
28 static const struct leds_evt_name evt_names[] = {
29         { "amber", led_amber_on, led_amber_off },
30         { "blue",  led_blue_on,  led_blue_off  },
31         { "green", led_green_on, led_green_off },
32         { "red",   led_red_on,   led_red_off   },
33 };
34
35 static ssize_t leds_store(struct sys_device *dev,
36                         struct sysdev_attribute *attr,
37                         const char *buf, size_t size)
38 {
39         int ret = -EINVAL, len = strcspn(buf, " ");
40
41         if (len > 0 && buf[len] == '\0')
42                 len--;
43
44         if (strncmp(buf, "claim", len) == 0) {
45                 leds_event(led_claim);
46                 ret = size;
47         } else if (strncmp(buf, "release", len) == 0) {
48                 leds_event(led_release);
49                 ret = size;
50         } else {
51                 int i;
52
53                 for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
54                         if (strlen(evt_names[i].name) != len ||
55                             strncmp(buf, evt_names[i].name, len) != 0)
56                                 continue;
57                         if (strncmp(buf+len, " on", 3) == 0) {
58                                 leds_event(evt_names[i].on);
59                                 ret = size;
60                         } else if (strncmp(buf+len, " off", 4) == 0) {
61                                 leds_event(evt_names[i].off);
62                                 ret = size;
63                         }
64                         break;
65                 }
66         }
67         return ret;
68 }
69
70 static SYSDEV_ATTR(event, 0200, NULL, leds_store);
71
72 static int leds_suspend(struct sys_device *dev, pm_message_t state)
73 {
74         leds_event(led_stop);
75         return 0;
76 }
77
78 static int leds_resume(struct sys_device *dev)
79 {
80         leds_event(led_start);
81         return 0;
82 }
83
84 static int leds_shutdown(struct sys_device *dev)
85 {
86         leds_event(led_halted);
87         return 0;
88 }
89
90 static struct sysdev_class leds_sysclass = {
91         .name           = "leds",
92         .shutdown       = leds_shutdown,
93         .suspend        = leds_suspend,
94         .resume         = leds_resume,
95 };
96
97 static struct sys_device leds_device = {
98         .id             = 0,
99         .cls            = &leds_sysclass,
100 };
101
102 static int __init leds_init(void)
103 {
104         int ret;
105         ret = sysdev_class_register(&leds_sysclass);
106         if (ret == 0)
107                 ret = sysdev_register(&leds_device);
108         if (ret == 0)
109                 ret = sysdev_create_file(&leds_device, &attr_event);
110         return ret;
111 }
112
113 device_initcall(leds_init);
114
115 EXPORT_SYMBOL(leds_event);