root/drivers/input/input-leds.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. input_leds_brightness_get
  2. input_leds_brightness_set
  3. input_leds_event
  4. input_leds_get_count
  5. input_leds_connect
  6. input_leds_disconnect
  7. input_leds_init
  8. input_leds_exit

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

/* [<][>][^][v][top][bottom][index][help] */