1 /* 2 * LED support for the input layer 3 * 4 * Copyright 2010-2015 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 #if IS_ENABLED(CONFIG_VT) 19 #define VT_TRIGGER(_name) .trigger = _name 20 #else 21 #define VT_TRIGGER(_name) .trigger = NULL 22 #endif 23 24 static const struct { 25 const char *name; 26 const char *trigger; 27 } input_led_info[LED_CNT] = { 28 [LED_NUML] = { "numlock", VT_TRIGGER("kbd-numlock") }, 29 [LED_CAPSL] = { "capslock", VT_TRIGGER("kbd-capslock") }, 30 [LED_SCROLLL] = { "scrolllock", VT_TRIGGER("kbd-scrolllock") }, 31 [LED_COMPOSE] = { "compose" }, 32 [LED_KANA] = { "kana", VT_TRIGGER("kbd-kanalock") }, 33 [LED_SLEEP] = { "sleep" } , 34 [LED_SUSPEND] = { "suspend" }, 35 [LED_MUTE] = { "mute" }, 36 [LED_MISC] = { "misc" }, 37 [LED_MAIL] = { "mail" }, 38 [LED_CHARGING] = { "charging" }, 39 }; 40 41 struct input_led { 42 struct led_classdev cdev; 43 struct input_handle *handle; 44 unsigned int code; /* One of LED_* constants */ 45 }; 46 47 struct input_leds { 48 struct input_handle handle; 49 unsigned int num_leds; 50 struct input_led leds[]; 51 }; 52 53 static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev) 54 { 55 struct input_led *led = container_of(cdev, struct input_led, cdev); 56 struct input_dev *input = led->handle->dev; 57 58 return test_bit(led->code, input->led) ? cdev->max_brightness : 0; 59 } 60 61 static void input_leds_brightness_set(struct led_classdev *cdev, 62 enum led_brightness brightness) 63 { 64 struct input_led *led = container_of(cdev, struct input_led, cdev); 65 66 input_inject_event(led->handle, EV_LED, led->code, !!brightness); 67 } 68 69 static void input_leds_event(struct input_handle *handle, unsigned int type, 70 unsigned int code, int value) 71 { 72 } 73 74 static int input_leds_get_count(struct input_dev *dev) 75 { 76 unsigned int led_code; 77 int count = 0; 78 79 for_each_set_bit(led_code, dev->ledbit, LED_CNT) 80 if (input_led_info[led_code].name) 81 count++; 82 83 return count; 84 } 85 86 static int input_leds_connect(struct input_handler *handler, 87 struct input_dev *dev, 88 const struct input_device_id *id) 89 { 90 struct input_leds *leds; 91 unsigned int num_leds; 92 unsigned int led_code; 93 int led_no; 94 int error; 95 96 num_leds = input_leds_get_count(dev); 97 if (!num_leds) 98 return -ENXIO; 99 100 leds = kzalloc(sizeof(*leds) + num_leds * sizeof(*leds->leds), 101 GFP_KERNEL); 102 if (!leds) 103 return -ENOMEM; 104 105 leds->num_leds = num_leds; 106 107 leds->handle.dev = dev; 108 leds->handle.handler = handler; 109 leds->handle.name = "leds"; 110 leds->handle.private = leds; 111 112 error = input_register_handle(&leds->handle); 113 if (error) 114 goto err_free_mem; 115 116 error = input_open_device(&leds->handle); 117 if (error) 118 goto err_unregister_handle; 119 120 led_no = 0; 121 for_each_set_bit(led_code, dev->ledbit, LED_CNT) { 122 struct input_led *led = &leds->leds[led_no]; 123 124 led->handle = &leds->handle; 125 led->code = led_code; 126 127 if (!input_led_info[led_code].name) 128 continue; 129 130 led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", 131 dev_name(&dev->dev), 132 input_led_info[led_code].name); 133 if (!led->cdev.name) { 134 error = -ENOMEM; 135 goto err_unregister_leds; 136 } 137 138 led->cdev.max_brightness = 1; 139 led->cdev.brightness_get = input_leds_brightness_get; 140 led->cdev.brightness_set = input_leds_brightness_set; 141 led->cdev.default_trigger = input_led_info[led_code].trigger; 142 143 error = led_classdev_register(&dev->dev, &led->cdev); 144 if (error) { 145 dev_err(&dev->dev, "failed to register LED %s: %d\n", 146 led->cdev.name, error); 147 kfree(led->cdev.name); 148 goto err_unregister_leds; 149 } 150 151 led_no++; 152 } 153 154 return 0; 155 156 err_unregister_leds: 157 while (--led_no >= 0) { 158 struct input_led *led = &leds->leds[led_no]; 159 160 led_classdev_unregister(&led->cdev); 161 kfree(led->cdev.name); 162 } 163 164 input_close_device(&leds->handle); 165 166 err_unregister_handle: 167 input_unregister_handle(&leds->handle); 168 169 err_free_mem: 170 kfree(leds); 171 return error; 172 } 173 174 static void input_leds_disconnect(struct input_handle *handle) 175 { 176 struct input_leds *leds = handle->private; 177 int i; 178 179 for (i = 0; i < leds->num_leds; i++) { 180 struct input_led *led = &leds->leds[i]; 181 182 led_classdev_unregister(&led->cdev); 183 kfree(led->cdev.name); 184 } 185 186 input_close_device(handle); 187 input_unregister_handle(handle); 188 189 kfree(leds); 190 } 191 192 static const struct input_device_id input_leds_ids[] = { 193 { 194 .flags = INPUT_DEVICE_ID_MATCH_EVBIT, 195 .evbit = { BIT_MASK(EV_LED) }, 196 }, 197 { }, 198 }; 199 MODULE_DEVICE_TABLE(input, input_leds_ids); 200 201 static struct input_handler input_leds_handler = { 202 .event = input_leds_event, 203 .connect = input_leds_connect, 204 .disconnect = input_leds_disconnect, 205 .name = "leds", 206 .id_table = input_leds_ids, 207 }; 208 209 static int __init input_leds_init(void) 210 { 211 return input_register_handler(&input_leds_handler); 212 } 213 module_init(input_leds_init); 214 215 static void __exit input_leds_exit(void) 216 { 217 input_unregister_handler(&input_leds_handler); 218 } 219 module_exit(input_leds_exit); 220 221 MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>"); 222 MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>"); 223 MODULE_DESCRIPTION("Input -> LEDs Bridge"); 224 MODULE_LICENSE("GPL v2"); 225