0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/leds.h>
0013 #include <linux/input.h>
0014
0015 #if IS_ENABLED(CONFIG_VT)
0016 #define VT_TRIGGER(_name) .trigger = _name
0017 #else
0018 #define VT_TRIGGER(_name) .trigger = NULL
0019 #endif
0020
0021 static const struct {
0022 const char *name;
0023 const char *trigger;
0024 } input_led_info[LED_CNT] = {
0025 [LED_NUML] = { "numlock", VT_TRIGGER("kbd-numlock") },
0026 [LED_CAPSL] = { "capslock", VT_TRIGGER("kbd-capslock") },
0027 [LED_SCROLLL] = { "scrolllock", VT_TRIGGER("kbd-scrolllock") },
0028 [LED_COMPOSE] = { "compose" },
0029 [LED_KANA] = { "kana", VT_TRIGGER("kbd-kanalock") },
0030 [LED_SLEEP] = { "sleep" } ,
0031 [LED_SUSPEND] = { "suspend" },
0032 [LED_MUTE] = { "mute" },
0033 [LED_MISC] = { "misc" },
0034 [LED_MAIL] = { "mail" },
0035 [LED_CHARGING] = { "charging" },
0036 };
0037
0038 struct input_led {
0039 struct led_classdev cdev;
0040 struct input_handle *handle;
0041 unsigned int code;
0042 };
0043
0044 struct input_leds {
0045 struct input_handle handle;
0046 unsigned int num_leds;
0047 struct input_led leds[];
0048 };
0049
0050 static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev)
0051 {
0052 struct input_led *led = container_of(cdev, struct input_led, cdev);
0053 struct input_dev *input = led->handle->dev;
0054
0055 return test_bit(led->code, input->led) ? cdev->max_brightness : 0;
0056 }
0057
0058 static void input_leds_brightness_set(struct led_classdev *cdev,
0059 enum led_brightness brightness)
0060 {
0061 struct input_led *led = container_of(cdev, struct input_led, cdev);
0062
0063 input_inject_event(led->handle, EV_LED, led->code, !!brightness);
0064 }
0065
0066 static void input_leds_event(struct input_handle *handle, unsigned int type,
0067 unsigned int code, int value)
0068 {
0069 }
0070
0071 static int input_leds_get_count(struct input_dev *dev)
0072 {
0073 unsigned int led_code;
0074 int count = 0;
0075
0076 for_each_set_bit(led_code, dev->ledbit, LED_CNT)
0077 if (input_led_info[led_code].name)
0078 count++;
0079
0080 return count;
0081 }
0082
0083 static int input_leds_connect(struct input_handler *handler,
0084 struct input_dev *dev,
0085 const struct input_device_id *id)
0086 {
0087 struct input_leds *leds;
0088 struct input_led *led;
0089 unsigned int num_leds;
0090 unsigned int led_code;
0091 int led_no;
0092 int error;
0093
0094 num_leds = input_leds_get_count(dev);
0095 if (!num_leds)
0096 return -ENXIO;
0097
0098 leds = kzalloc(struct_size(leds, leds, num_leds), GFP_KERNEL);
0099 if (!leds)
0100 return -ENOMEM;
0101
0102 leds->num_leds = num_leds;
0103
0104 leds->handle.dev = dev;
0105 leds->handle.handler = handler;
0106 leds->handle.name = "leds";
0107 leds->handle.private = leds;
0108
0109 error = input_register_handle(&leds->handle);
0110 if (error)
0111 goto err_free_mem;
0112
0113 error = input_open_device(&leds->handle);
0114 if (error)
0115 goto err_unregister_handle;
0116
0117 led_no = 0;
0118 for_each_set_bit(led_code, dev->ledbit, LED_CNT) {
0119 if (!input_led_info[led_code].name)
0120 continue;
0121
0122 led = &leds->leds[led_no];
0123 led->handle = &leds->handle;
0124 led->code = led_code;
0125
0126 led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
0127 dev_name(&dev->dev),
0128 input_led_info[led_code].name);
0129 if (!led->cdev.name) {
0130 error = -ENOMEM;
0131 goto err_unregister_leds;
0132 }
0133
0134 led->cdev.max_brightness = 1;
0135 led->cdev.brightness_get = input_leds_brightness_get;
0136 led->cdev.brightness_set = input_leds_brightness_set;
0137 led->cdev.default_trigger = input_led_info[led_code].trigger;
0138
0139 error = led_classdev_register(&dev->dev, &led->cdev);
0140 if (error) {
0141 dev_err(&dev->dev, "failed to register LED %s: %d\n",
0142 led->cdev.name, error);
0143 kfree(led->cdev.name);
0144 goto err_unregister_leds;
0145 }
0146
0147 led_no++;
0148 }
0149
0150 return 0;
0151
0152 err_unregister_leds:
0153 while (--led_no >= 0) {
0154 struct input_led *led = &leds->leds[led_no];
0155
0156 led_classdev_unregister(&led->cdev);
0157 kfree(led->cdev.name);
0158 }
0159
0160 input_close_device(&leds->handle);
0161
0162 err_unregister_handle:
0163 input_unregister_handle(&leds->handle);
0164
0165 err_free_mem:
0166 kfree(leds);
0167 return error;
0168 }
0169
0170 static void input_leds_disconnect(struct input_handle *handle)
0171 {
0172 struct input_leds *leds = handle->private;
0173 int i;
0174
0175 for (i = 0; i < leds->num_leds; i++) {
0176 struct input_led *led = &leds->leds[i];
0177
0178 led_classdev_unregister(&led->cdev);
0179 kfree(led->cdev.name);
0180 }
0181
0182 input_close_device(handle);
0183 input_unregister_handle(handle);
0184
0185 kfree(leds);
0186 }
0187
0188 static const struct input_device_id input_leds_ids[] = {
0189 {
0190 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
0191 .evbit = { BIT_MASK(EV_LED) },
0192 },
0193 { },
0194 };
0195 MODULE_DEVICE_TABLE(input, input_leds_ids);
0196
0197 static struct input_handler input_leds_handler = {
0198 .event = input_leds_event,
0199 .connect = input_leds_connect,
0200 .disconnect = input_leds_disconnect,
0201 .name = "leds",
0202 .id_table = input_leds_ids,
0203 };
0204
0205 static int __init input_leds_init(void)
0206 {
0207 return input_register_handler(&input_leds_handler);
0208 }
0209 module_init(input_leds_init);
0210
0211 static void __exit input_leds_exit(void)
0212 {
0213 input_unregister_handler(&input_leds_handler);
0214 }
0215 module_exit(input_leds_exit);
0216
0217 MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>");
0218 MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>");
0219 MODULE_DESCRIPTION("Input -> LEDs Bridge");
0220 MODULE_LICENSE("GPL v2");