blob: 1911dae19e4f6947c9f1401e3894c0b3cce72f77 [file] [log] [blame]
Russell King373b32a2010-01-10 17:15:32 +00001/*
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 */
Paul Gortmakerecea4ab2011-07-22 10:58:34 -040010#include <linux/export.h>
Russell King373b32a2010-01-10 17:15:32 +000011#include <linux/init.h>
Kay Sievers8f1e9382011-12-21 15:52:57 -080012#include <linux/device.h>
Rafael J. Wysocki328f5cc2011-04-22 22:02:33 +020013#include <linux/syscore_ops.h>
Paul Gortmakerd44b28c2011-07-31 10:52:44 -040014#include <linux/string.h>
Russell King373b32a2010-01-10 17:15:32 +000015
16#include <asm/leds.h>
17
18static void dummy_leds_event(led_event_t evt)
19{
20}
21
22void (*leds_event)(led_event_t) = dummy_leds_event;
23
24struct leds_evt_name {
25 const char name[8];
26 int on;
27 int off;
28};
29
30static 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
Kay Sievers8f1e9382011-12-21 15:52:57 -080037static ssize_t leds_store(struct device *dev,
38 struct device_attribute *attr,
Russell King373b32a2010-01-10 17:15:32 +000039 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
Kay Sievers8f1e9382011-12-21 15:52:57 -080072static DEVICE_ATTR(event, 0200, NULL, leds_store);
Russell King373b32a2010-01-10 17:15:32 +000073
Kay Sievers8f1e9382011-12-21 15:52:57 -080074static struct bus_type leds_subsys = {
Russell King373b32a2010-01-10 17:15:32 +000075 .name = "leds",
Kay Sievers8f1e9382011-12-21 15:52:57 -080076 .dev_name = "leds",
Russell King373b32a2010-01-10 17:15:32 +000077};
78
Kay Sievers8f1e9382011-12-21 15:52:57 -080079static struct device leds_device = {
Russell King373b32a2010-01-10 17:15:32 +000080 .id = 0,
Kay Sievers8f1e9382011-12-21 15:52:57 -080081 .bus = &leds_subsys,
Russell King373b32a2010-01-10 17:15:32 +000082};
83
Rafael J. Wysocki328f5cc2011-04-22 22:02:33 +020084static int leds_suspend(void)
85{
86 leds_event(led_stop);
87 return 0;
88}
89
90static void leds_resume(void)
91{
92 leds_event(led_start);
93}
94
95static void leds_shutdown(void)
96{
97 leds_event(led_halted);
98}
99
100static struct syscore_ops leds_syscore_ops = {
101 .shutdown = leds_shutdown,
102 .suspend = leds_suspend,
103 .resume = leds_resume,
104};
105
Russell King373b32a2010-01-10 17:15:32 +0000106static int __init leds_init(void)
107{
108 int ret;
Kay Sievers8f1e9382011-12-21 15:52:57 -0800109 ret = subsys_system_register(&leds_subsys, NULL);
Russell King373b32a2010-01-10 17:15:32 +0000110 if (ret == 0)
Kay Sievers8f1e9382011-12-21 15:52:57 -0800111 ret = device_register(&leds_device);
Russell King373b32a2010-01-10 17:15:32 +0000112 if (ret == 0)
Kay Sievers8f1e9382011-12-21 15:52:57 -0800113 ret = device_create_file(&leds_device, &dev_attr_event);
Rafael J. Wysocki328f5cc2011-04-22 22:02:33 +0200114 if (ret == 0)
115 register_syscore_ops(&leds_syscore_ops);
Russell King373b32a2010-01-10 17:15:32 +0000116 return ret;
117}
118
119device_initcall(leds_init);
120
121EXPORT_SYMBOL(leds_event);