]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/input/leds.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / drivers / input / leds.c
1 /*
2  * LED support for the input layer
3  *
4  * Copyright 2010-2013 Samuel Thibault <samuel.thibault@ens-lyon.org>
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
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/leds.h>
16 #include <linux/input.h>
17
18 /*
19  * Keyboard LEDs are propagated by default like the following example:
20  *
21  * VT keyboard numlock trigger
22  * -> vt::numl VT LED
23  * -> vt-numl VT trigger
24  * -> per-device inputX::numl LED
25  *
26  * Userland can however choose the trigger for the vt::numl LED, or
27  * independently choose the trigger for any inputx::numl LED.
28  *
29  *
30  * VT LED classes and triggers are registered on-demand according to
31  * existing LED devices
32  */
33
34 /* Handler for VT LEDs, just triggers the corresponding VT trigger. */
35 static void vt_led_set(struct led_classdev *cdev,
36                           enum led_brightness brightness);
37 static struct led_classdev vt_leds[LED_CNT] = {
38 #define DEFINE_INPUT_LED(vt_led, nam, deftrig) \
39         [vt_led] = { \
40                 .name = "vt::"nam, \
41                 .max_brightness = 1, \
42                 .brightness_set = vt_led_set, \
43                 .default_trigger = deftrig, \
44         }
45 /* Default triggers for the VT LEDs just correspond to the legacy
46  * usage. */
47         DEFINE_INPUT_LED(LED_NUML, "numl", "kbd-numlock"),
48         DEFINE_INPUT_LED(LED_CAPSL, "capsl", "kbd-capslock"),
49         DEFINE_INPUT_LED(LED_SCROLLL, "scrolll", "kbd-scrollock"),
50         DEFINE_INPUT_LED(LED_COMPOSE, "compose", NULL),
51         DEFINE_INPUT_LED(LED_KANA, "kana", "kbd-kanalock"),
52         DEFINE_INPUT_LED(LED_SLEEP, "sleep", NULL),
53         DEFINE_INPUT_LED(LED_SUSPEND, "suspend", NULL),
54         DEFINE_INPUT_LED(LED_MUTE, "mute", NULL),
55         DEFINE_INPUT_LED(LED_MISC, "misc", NULL),
56         DEFINE_INPUT_LED(LED_MAIL, "mail", NULL),
57         DEFINE_INPUT_LED(LED_CHARGING, "charging", NULL),
58 };
59 static const char *const vt_led_names[LED_CNT] = {
60         [LED_NUML] = "numl",
61         [LED_CAPSL] = "capsl",
62         [LED_SCROLLL] = "scrolll",
63         [LED_COMPOSE] = "compose",
64         [LED_KANA] = "kana",
65         [LED_SLEEP] = "sleep",
66         [LED_SUSPEND] = "suspend",
67         [LED_MUTE] = "mute",
68         [LED_MISC] = "misc",
69         [LED_MAIL] = "mail",
70         [LED_CHARGING] = "charging",
71 };
72 /* Handler for hotplug initialization */
73 static void vt_led_trigger_activate(struct led_classdev *cdev);
74 /* VT triggers */
75 static struct led_trigger vt_led_triggers[LED_CNT] = {
76 #define DEFINE_INPUT_LED_TRIGGER(vt_led, nam) \
77         [vt_led] = { \
78                 .name = "vt-"nam, \
79                 .activate = vt_led_trigger_activate, \
80         }
81         DEFINE_INPUT_LED_TRIGGER(LED_NUML, "numl"),
82         DEFINE_INPUT_LED_TRIGGER(LED_CAPSL, "capsl"),
83         DEFINE_INPUT_LED_TRIGGER(LED_SCROLLL, "scrolll"),
84         DEFINE_INPUT_LED_TRIGGER(LED_COMPOSE, "compose"),
85         DEFINE_INPUT_LED_TRIGGER(LED_KANA, "kana"),
86         DEFINE_INPUT_LED_TRIGGER(LED_SLEEP, "sleep"),
87         DEFINE_INPUT_LED_TRIGGER(LED_SUSPEND, "suspend"),
88         DEFINE_INPUT_LED_TRIGGER(LED_MUTE, "mute"),
89         DEFINE_INPUT_LED_TRIGGER(LED_MISC, "misc"),
90         DEFINE_INPUT_LED_TRIGGER(LED_MAIL, "mail"),
91         DEFINE_INPUT_LED_TRIGGER(LED_CHARGING, "charging"),
92 };
93
94 /* Lock for registration coherency */
95 static DEFINE_MUTEX(vt_led_registered_lock);
96
97 /* Which VT LED classes and triggers are registered */
98 static unsigned long vt_led_registered[BITS_TO_LONGS(LED_CNT)];
99
100 /* Number of input devices having each LED */
101 static int vt_led_references[LED_CNT];
102
103 /* VT LED state change, tell the VT trigger.  */
104 static void vt_led_set(struct led_classdev *cdev,
105                           enum led_brightness brightness)
106 {
107         int led = cdev - vt_leds;
108
109         led_trigger_event(&vt_led_triggers[led], !!brightness);
110 }
111
112 /* LED state change for some keyboard, notify that keyboard.  */
113 static void perdevice_input_led_set(struct led_classdev *cdev,
114                           enum led_brightness brightness)
115 {
116         struct input_dev *dev;
117         struct led_classdev *leds;
118         int led;
119
120         dev = cdev->dev->platform_data;
121         if (!dev)
122                 /* Still initializing */
123                 return;
124         leds = dev->leds;
125         led = cdev - leds;
126
127         input_event(dev, EV_LED, led, !!brightness);
128         input_event(dev, EV_SYN, SYN_REPORT, 0);
129 }
130
131 /* Keyboard hotplug, initialize its LED status */
132 static void vt_led_trigger_activate(struct led_classdev *cdev)
133 {
134         struct led_trigger *trigger = cdev->trigger;
135         int led = trigger - vt_led_triggers;
136
137         if (cdev->brightness_set)
138                 cdev->brightness_set(cdev, vt_leds[led].brightness);
139 }
140
141 /* Free led stuff from input device, used at abortion and disconnection.  */
142 static void input_led_delete(struct input_dev *dev)
143 {
144         if (dev) {
145                 struct led_classdev *leds = dev->leds;
146                 if (leds) {
147                         int i;
148                         for (i = 0; i < LED_CNT; i++)
149                                 kfree(leds[i].name);
150                         kfree(leds);
151                         dev->leds = NULL;
152                 }
153         }
154 }
155
156 /* A new input device with potential LEDs to connect.  */
157 int input_led_connect(struct input_dev *dev)
158 {
159         int i, error = 0;
160         struct led_classdev *leds;
161
162         dev->leds = leds = kzalloc(sizeof(*leds) * LED_CNT, GFP_KERNEL);
163         if (!dev->leds)
164                 return -ENOMEM;
165
166         /* lazily register missing VT LEDs */
167         mutex_lock(&vt_led_registered_lock);
168         for (i = 0; i < LED_CNT; i++)
169                 if (vt_leds[i].name && test_bit(i, dev->ledbit)) {
170                         if (!vt_led_references[i]) {
171                                 led_trigger_register(&vt_led_triggers[i]);
172                                 /* This keyboard is first to have led i,
173                                  * try to register it */
174                                 if (!led_classdev_register(NULL, &vt_leds[i]))
175                                         vt_led_references[i] = 1;
176                                 else
177                                         led_trigger_unregister(&vt_led_triggers[i]);
178                         } else
179                                 vt_led_references[i]++;
180                 }
181         mutex_unlock(&vt_led_registered_lock);
182
183         /* and register this device's LEDs */
184         for (i = 0; i < LED_CNT; i++)
185                 if (vt_leds[i].name && test_bit(i, dev->ledbit)) {
186                         leds[i].name = kasprintf(GFP_KERNEL, "%s::%s",
187                                                 dev_name(&dev->dev),
188                                                 vt_led_names[i]);
189                         if (!leds[i].name) {
190                                 error = -ENOMEM;
191                                 goto err;
192                         }
193                         leds[i].max_brightness = 1;
194                         leds[i].brightness_set = perdevice_input_led_set;
195                         leds[i].default_trigger = vt_led_triggers[i].name;
196                 }
197
198         /* No issue so far, we can register for real.  */
199         for (i = 0; i < LED_CNT; i++)
200                 if (leds[i].name) {
201                         led_classdev_register(&dev->dev, &leds[i]);
202                         leds[i].dev->platform_data = dev;
203                         perdevice_input_led_set(&leds[i],
204                                         vt_leds[i].brightness);
205                 }
206
207         return 0;
208
209 err:
210         input_led_delete(dev);
211         return error;
212 }
213
214 /*
215  * Disconnected input device. Clean it, and deregister now-useless VT LEDs and
216  * triggers.
217  */
218 void input_led_disconnect(struct input_dev *dev)
219 {
220         int i;
221         struct led_classdev *leds = dev->leds;
222
223         for (i = 0; i < LED_CNT; i++)
224                 if (leds[i].name)
225                         led_classdev_unregister(&leds[i]);
226
227         input_led_delete(dev);
228
229         mutex_lock(&vt_led_registered_lock);
230         for (i = 0; i < LED_CNT; i++) {
231                 if (!vt_leds[i].name || !test_bit(i, dev->ledbit))
232                         continue;
233
234                 vt_led_references[i]--;
235                 if (vt_led_references[i]) {
236                         /* Still some devices needing it */
237                         continue;
238                 }
239
240                 led_classdev_unregister(&vt_leds[i]);
241                 led_trigger_unregister(&vt_led_triggers[i]);
242                 clear_bit(i, vt_led_registered);
243         }
244         mutex_unlock(&vt_led_registered_lock);
245 }
246
247 MODULE_LICENSE("GPL");
248 MODULE_DESCRIPTION("User LED support for input layer");
249 MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");