2 * LED support for the input layer
4 * Copyright 2010-2013 Samuel Thibault <samuel.thibault@ens-lyon.org>
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.
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>
19 * Keyboard LEDs are propagated by default like the following example:
21 * VT keyboard numlock trigger
23 * -> vt-numl VT trigger
24 * -> per-device inputX::numl LED
26 * Userland can however choose the trigger for the vt::numl LED, or
27 * independently choose the trigger for any inputx::numl LED.
30 * VT LED classes and triggers are registered on-demand according to
31 * existing LED devices
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) \
41 .max_brightness = 1, \
42 .brightness_set = vt_led_set, \
43 .default_trigger = deftrig, \
45 /* Default triggers for the VT LEDs just correspond to the legacy
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),
59 static const char *const vt_led_names[LED_CNT] = {
61 [LED_CAPSL] = "capsl",
62 [LED_SCROLLL] = "scrolll",
63 [LED_COMPOSE] = "compose",
65 [LED_SLEEP] = "sleep",
66 [LED_SUSPEND] = "suspend",
70 [LED_CHARGING] = "charging",
72 /* Handler for hotplug initialization */
73 static void vt_led_trigger_activate(struct led_classdev *cdev);
75 static struct led_trigger vt_led_triggers[LED_CNT] = {
76 #define DEFINE_INPUT_LED_TRIGGER(vt_led, nam) \
79 .activate = vt_led_trigger_activate, \
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"),
94 /* Lock for registration coherency */
95 static DEFINE_MUTEX(vt_led_registered_lock);
97 /* Which VT LED classes and triggers are registered */
98 static unsigned long vt_led_registered[BITS_TO_LONGS(LED_CNT)];
100 /* Number of input devices having each LED */
101 static int vt_led_references[LED_CNT];
103 /* VT LED state change, tell the VT trigger. */
104 static void vt_led_set(struct led_classdev *cdev,
105 enum led_brightness brightness)
107 int led = cdev - vt_leds;
109 led_trigger_event(&vt_led_triggers[led], !!brightness);
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)
116 struct input_dev *dev;
117 struct led_classdev *leds;
120 dev = cdev->dev->platform_data;
122 /* Still initializing */
127 input_event(dev, EV_LED, led, !!brightness);
128 input_event(dev, EV_SYN, SYN_REPORT, 0);
131 /* Keyboard hotplug, initialize its LED status */
132 static void vt_led_trigger_activate(struct led_classdev *cdev)
134 struct led_trigger *trigger = cdev->trigger;
135 int led = trigger - vt_led_triggers;
137 if (cdev->brightness_set)
138 cdev->brightness_set(cdev, vt_leds[led].brightness);
141 /* Free led stuff from input device, used at abortion and disconnection. */
142 static void input_led_delete(struct input_dev *dev)
145 struct led_classdev *leds = dev->leds;
148 for (i = 0; i < LED_CNT; i++)
156 /* A new input device with potential LEDs to connect. */
157 int input_led_connect(struct input_dev *dev)
160 struct led_classdev *leds;
162 dev->leds = leds = kzalloc(sizeof(*leds) * LED_CNT, GFP_KERNEL);
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;
177 led_trigger_unregister(&vt_led_triggers[i]);
179 vt_led_references[i]++;
181 mutex_unlock(&vt_led_registered_lock);
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",
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;
198 /* No issue so far, we can register for real. */
199 for (i = 0; i < LED_CNT; i++)
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);
210 input_led_delete(dev);
215 * Disconnected input device. Clean it, and deregister now-useless VT LEDs and
218 void input_led_disconnect(struct input_dev *dev)
221 struct led_classdev *leds = dev->leds;
223 for (i = 0; i < LED_CNT; i++)
225 led_classdev_unregister(&leds[i]);
227 input_led_delete(dev);
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))
234 vt_led_references[i]--;
235 if (vt_led_references[i]) {
236 /* Still some devices needing it */
240 led_classdev_unregister(&vt_leds[i]);
241 led_trigger_unregister(&vt_led_triggers[i]);
242 clear_bit(i, vt_led_registered);
244 mutex_unlock(&vt_led_registered_lock);
247 MODULE_LICENSE("GPL");
248 MODULE_DESCRIPTION("User LED support for input layer");
249 MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");