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