Merge remote-tracking branch 'agust/next' into merge
[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/export.h>
11 #include <linux/init.h>
12 #include <linux/sysdev.h>
13 #include <linux/syscore_ops.h>
14 #include <linux/string.h>
15
16 #include <asm/leds.h>
17
18 static void dummy_leds_event(led_event_t evt)
19 {
20 }
21
22 void (*leds_event)(led_event_t) = dummy_leds_event;
23
24 struct leds_evt_name {
25         const char      name[8];
26         int             on;
27         int             off;
28 };
29
30 static const struct leds_evt_name evt_names[] = {
31         { "amber", led_amber_on, led_amber_off },
32         { "blue",  led_blue_on,  led_blue_off  },
33         { "green", led_green_on, led_green_off },
34         { "red",   led_red_on,   led_red_off   },
35 };
36
37 static ssize_t leds_store(struct sys_device *dev,
38                         struct sysdev_attribute *attr,
39                         const char *buf, size_t size)
40 {
41         int ret = -EINVAL, len = strcspn(buf, " ");
42
43         if (len > 0 && buf[len] == '\0')
44                 len--;
45
46         if (strncmp(buf, "claim", len) == 0) {
47                 leds_event(led_claim);
48                 ret = size;
49         } else if (strncmp(buf, "release", len) == 0) {
50                 leds_event(led_release);
51                 ret = size;
52         } else {
53                 int i;
54
55                 for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
56                         if (strlen(evt_names[i].name) != len ||
57                             strncmp(buf, evt_names[i].name, len) != 0)
58                                 continue;
59                         if (strncmp(buf+len, " on", 3) == 0) {
60                                 leds_event(evt_names[i].on);
61                                 ret = size;
62                         } else if (strncmp(buf+len, " off", 4) == 0) {
63                                 leds_event(evt_names[i].off);
64                                 ret = size;
65                         }
66                         break;
67                 }
68         }
69         return ret;
70 }
71
72 static SYSDEV_ATTR(event, 0200, NULL, leds_store);
73
74 static struct sysdev_class leds_sysclass = {
75         .name           = "leds",
76 };
77
78 static struct sys_device leds_device = {
79         .id             = 0,
80         .cls            = &leds_sysclass,
81 };
82
83 static int leds_suspend(void)
84 {
85         leds_event(led_stop);
86         return 0;
87 }
88
89 static void leds_resume(void)
90 {
91         leds_event(led_start);
92 }
93
94 static void leds_shutdown(void)
95 {
96         leds_event(led_halted);
97 }
98
99 static struct syscore_ops leds_syscore_ops = {
100         .shutdown       = leds_shutdown,
101         .suspend        = leds_suspend,
102         .resume         = leds_resume,
103 };
104
105 static int __init leds_init(void)
106 {
107         int ret;
108         ret = sysdev_class_register(&leds_sysclass);
109         if (ret == 0)
110                 ret = sysdev_register(&leds_device);
111         if (ret == 0)
112                 ret = sysdev_create_file(&leds_device, &attr_event);
113         if (ret == 0)
114                 register_syscore_ops(&leds_syscore_ops);
115         return ret;
116 }
117
118 device_initcall(leds_init);
119
120 EXPORT_SYMBOL(leds_event);