Message ID | 20150609174211.GH6338@dtor-ws (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hello, Thanks for the modified version. This all seems to be working as expected with multiple keyboards. Samuel -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Jun 10, 2015 at 02:32:32AM +0200, Samuel Thibault wrote: > Hello, > > Thanks for the modified version. This all seems to be working as > expected with multiple keyboards. Excellent. Let's give Pavel and Pali chance to test it out and let's get it in 4.2. Thanks.
On Tue 2015-06-09 18:24:54, Dmitry Torokhov wrote: > On Wed, Jun 10, 2015 at 02:32:32AM +0200, Samuel Thibault wrote: > > Hello, > > > > Thanks for the modified version. This all seems to be working as > > expected with multiple keyboards. > > Excellent. Let's give Pavel and Pali chance to test it out and let's get > it in 4.2. Tested-by: Pavel Machek <pavel@ucw.cz> Acked-by: Pavel Machek <pavel@ucw.cz> Pavel
On Tue 2015-06-09 18:24:54, Dmitry Torokhov wrote: > On Wed, Jun 10, 2015 at 02:32:32AM +0200, Samuel Thibault wrote: > > Hello, > > > > Thanks for the modified version. This all seems to be working as > > expected with multiple keyboards. > > Excellent. Let's give Pavel and Pali chance to test it out and let's get > it in 4.2. I guess Pali is busy... but please don't let that stop 4.2 merge :-). Thanks, Pavel
On Monday 15 June 2015 12:03:08 Pavel Machek wrote: > On Tue 2015-06-09 18:24:54, Dmitry Torokhov wrote: > > On Wed, Jun 10, 2015 at 02:32:32AM +0200, Samuel Thibault wrote: > > > Hello, > > > > > > Thanks for the modified version. This all seems to be working as > > > expected with multiple keyboards. > > > > Excellent. Let's give Pavel and Pali chance to test it out and let's get > > it in 4.2. > > I guess Pali is busy... but please don't let that stop 4.2 merge :-). > > Thanks, > Pavel Yes... Do you need to do tests also by me? Pavel and Samuel already tested it, so in this case I would trust them and if there will be some problems I will report them later... I also want to see this option finally in 4.2 kernel.
On 06/09/2015 07:42 PM, Dmitry Torokhov wrote: > From: Samuel Thibault <samuel.thibault@ens-lyon.org> > > This change creates a new input handler called "leds" that exports LEDs on input > devices as standard LED class devices in sysfs and allows controlling their > ptate via sysfs or via any of the standard LED triggers. This allows to > re-purpose and reassign LDEs on the keyboards to represent states other > than the standard keyboard states (CapsLock, NumLock, etc). > > The old API of controlling input LEDs by writing into /dev/input/eventX > devices is still present and will take precedence over acessing via LEDs > subsystem (i.e. it may override state set by a trigger). If input device is > "grabbed" then requests coming through LED subsystem will be ignored. > > Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> > --- > + led_no = 0; > + for_each_set_bit(led_code, dev->ledbit, LED_CNT) { > + struct input_led *led = &leds->leds[led_no]; > + > + led->handle = &leds->handle; > + led->code = led_code; > + > + if (WARN_ON(!input_led_info[led_code].name)) > + continue; > + Hi, I get several warnings on booting 4.2-rc2 here. Should I be worried? [ 2.782432] ------------[ cut here ]------------ [ 2.782440] WARNING: CPU: 2 PID: 356 at ../drivers/input/input-leds.c:115 input_leds_connect+0x22b/0x260() [ 2.782441] Modules linked in: btrfs xor raid6_pq crc32c_intel radeon i2c_algo_bit sr_mod cdrom drm_kms_helper ttm e1000e drm xhci_pci ptp pps_core xhci_hcd sg [ 2.782453] CPU: 2 PID: 356 Comm: kworker/2:2 Not tainted 4.2.0-rc2-1.g288d56b-desktop #1 [ 2.782454] Hardware name: Dell Inc. OptiPlex 9010/0M9KCM, BIOS A13 03/27/2013 [ 2.782458] Workqueue: usb_hub_wq hub_event [ 2.782459] ffffffff81a917b7 ffff880213ecf298 ffffffff8169f19d 0000000000000007 [ 2.782462] 0000000000000000 ffff880213ecf2d8 ffffffff810674f6 ffff880213ecf2f8 [ 2.782463] ffff8802132fb000 0000000000000003 000000000000000b ffff8800369ff000 [ 2.782465] Call Trace: [ 2.782470] [<ffffffff8169f19d>] dump_stack+0x4c/0x6e [ 2.782474] [<ffffffff810674f6>] warn_slowpath_common+0x86/0xc0 [ 2.782476] [<ffffffff810675ea>] warn_slowpath_null+0x1a/0x20 [ 2.782478] [<ffffffff8152ccdb>] input_leds_connect+0x22b/0x260 [ 2.782480] [<ffffffff815281b2>] input_attach_handler+0x1a2/0x1f0 [ 2.782483] [<ffffffff81528640>] input_register_device+0x440/0x4f0 [ 2.782486] [<ffffffff8156e494>] hidinput_connect+0x334/0x5d0 [ 2.782488] [<ffffffff815683d4>] hid_connect+0x324/0x400 [ 2.782490] [<ffffffff81578b7a>] ? usbhid_start+0x54a/0x780 [ 2.782492] [<ffffffff81569858>] hid_device_probe+0x118/0x140 [ 2.782495] [<ffffffff81482134>] driver_probe_device+0x1f4/0x460 [ 2.782497] [<ffffffff814824b9>] __device_attach_driver+0x79/0xa0 [ 2.782499] [<ffffffff81482440>] ? __driver_attach+0xa0/0xa0 [ 2.782501] [<ffffffff8147ff6b>] bus_for_each_drv+0x5b/0x90 [ 2.782502] [<ffffffff81481e58>] __device_attach+0xa8/0x120 [ 2.782504] [<ffffffff81482523>] device_initial_probe+0x13/0x20 [ 2.782506] [<ffffffff8148116a>] bus_probe_device+0x9a/0xb0 [ 2.782508] [<ffffffff8147edee>] device_add+0x3fe/0x670 [ 2.782511] [<ffffffff812bf9d3>] ? debugfs_create_file+0xd3/0x110 [ 2.782513] [<ffffffff8156956c>] hid_add_device+0xcc/0x2a0 [ 2.782515] [<ffffffff81578404>] usbhid_probe+0x2e4/0x410 [ 2.782518] [<ffffffff814fe0d2>] usb_probe_interface+0x1b2/0x2d0 [ 2.782519] [<ffffffff81482134>] driver_probe_device+0x1f4/0x460 [ 2.782521] [<ffffffff814824b9>] __device_attach_driver+0x79/0xa0 [ 2.782523] [<ffffffff81482440>] ? __driver_attach+0xa0/0xa0 [ 2.782525] [<ffffffff8147ff6b>] bus_for_each_drv+0x5b/0x90 [ 2.782526] [<ffffffff81481e58>] __device_attach+0xa8/0x120 [ 2.782528] [<ffffffff81482523>] device_initial_probe+0x13/0x20 [ 2.782530] [<ffffffff8148116a>] bus_probe_device+0x9a/0xb0 [ 2.782531] [<ffffffff8147edee>] device_add+0x3fe/0x670 [ 2.782533] [<ffffffff814fbfb1>] usb_set_configuration+0x501/0x8e0 [ 2.782535] [<ffffffff81253efe>] ? kernfs_add_one+0xee/0x140 [ 2.782537] [<ffffffff8150656e>] generic_probe+0x2e/0x80 [ 2.782539] [<ffffffff814fdee2>] usb_probe_device+0x32/0x70 [ 2.782541] [<ffffffff81482134>] driver_probe_device+0x1f4/0x460 [ 2.782542] [<ffffffff814824b9>] __device_attach_driver+0x79/0xa0 [ 2.782544] [<ffffffff81482440>] ? __driver_attach+0xa0/0xa0 [ 2.782546] [<ffffffff8147ff6b>] bus_for_each_drv+0x5b/0x90 [ 2.782547] [<ffffffff81481e58>] __device_attach+0xa8/0x120 [ 2.782549] [<ffffffff81482523>] device_initial_probe+0x13/0x20 [ 2.782551] [<ffffffff8148116a>] bus_probe_device+0x9a/0xb0 [ 2.782552] [<ffffffff8147edee>] device_add+0x3fe/0x670 [ 2.782554] [<ffffffff814f15c6>] ? usb_new_device+0x216/0x5d0 [ 2.782556] [<ffffffff814f164e>] usb_new_device+0x29e/0x5d0 [ 2.782559] [<ffffffff8148cff1>] ? pm_runtime_set_autosuspend_delay+0x51/0x60 [ 2.782561] [<ffffffff81506612>] ? __usb_detect_quirks+0x52/0x110 [ 2.782563] [<ffffffff814f2c3f>] hub_port_connect+0x31f/0x9c0 [ 2.782565] [<ffffffff814f39b1>] hub_event+0x6d1/0xb10 [ 2.782568] [<ffffffff8107f039>] process_one_work+0x159/0x470 [ 2.782570] [<ffffffff8107f398>] worker_thread+0x48/0x4a0 [ 2.782572] [<ffffffff8107f350>] ? process_one_work+0x470/0x470 [ 2.782574] [<ffffffff8107f350>] ? process_one_work+0x470/0x470 [ 2.782576] [<ffffffff81085089>] kthread+0xc9/0xe0 [ 2.782579] [<ffffffff81084fc0>] ? kthread_worker_fn+0x170/0x170 [ 2.782581] [<ffffffff816a55df>] ret_from_fork+0x3f/0x70 [ 2.782583] [<ffffffff81084fc0>] ? kthread_worker_fn+0x170/0x170 [ 2.782585] ---[ end trace ce1cb4ca0f2cbd0b ]--- [ 2.782586] ------------[ cut here ]------------ -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt index 79699c2..62261c0 100644 --- a/Documentation/leds/leds-class.txt +++ b/Documentation/leds/leds-class.txt @@ -2,9 +2,6 @@ LED handling under Linux ======================== -If you're reading this and thinking about keyboard leds, these are -handled by the input subsystem and the led class is *not* needed. - In its simplest form, the LED class just allows control of LEDs from userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the LED is defined in max_brightness file. The brightness file will set the brightness diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index a11ff74..a35532e 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -25,6 +25,19 @@ config INPUT if INPUT +config INPUT_LEDS + tristate "Export input device LEDs in sysfs" + depends on LEDS_CLASS + default INPUT + help + Say Y here if you would like to export LEDs on input devices + as standard LED class devices in sysfs. + + If unsure, say Y. + + To compile this driver as a module, choose M here: the + module will be called input-leds. + config INPUT_FF_MEMLESS tristate "Support for memoryless force-feedback devices" help diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 5ca3f63..0c9302c 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o +obj-$(CONFIG_INPUT_LEDS) += input-leds.o obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c new file mode 100644 index 0000000..074a65e --- /dev/null +++ b/drivers/input/input-leds.c @@ -0,0 +1,212 @@ +/* + * LED support for the input layer + * + * Copyright 2010-2015 Samuel Thibault <samuel.thibault@ens-lyon.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/leds.h> +#include <linux/input.h> + +#if IS_ENABLED(CONFIG_VT) +#define VT_TRIGGER(_name) .trigger = _name +#else +#define VT_TRIGGER(_name) .trigger = NULL +#endif + +static const struct { + const char *name; + const char *trigger; +} input_led_info[LED_CNT] = { + [LED_NUML] = { "numlock", VT_TRIGGER("kbd-numlock") }, + [LED_CAPSL] = { "capslock", VT_TRIGGER("kbd-capslock") }, + [LED_SCROLLL] = { "scrolllock", VT_TRIGGER("kbd-scrolllock") }, + [LED_COMPOSE] = { "compose" }, + [LED_KANA] = { "kana", VT_TRIGGER("kbd-kanalock") }, + [LED_SLEEP] = { "sleep" } , + [LED_SUSPEND] = { "suspend" }, + [LED_MUTE] = { "mute" }, + [LED_MISC] = { "misc" }, + [LED_MAIL] = { "mail" }, + [LED_CHARGING] = { "charging" }, +}; + +struct input_led { + struct led_classdev cdev; + struct input_handle *handle; + unsigned int code; /* One of LED_* constants */ +}; + +struct input_leds { + struct input_handle handle; + unsigned int num_leds; + struct input_led leds[]; +}; + +static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev) +{ + struct input_led *led = container_of(cdev, struct input_led, cdev); + struct input_dev *input = led->handle->dev; + + return test_bit(led->code, input->led) ? cdev->max_brightness : 0; +} + +static void input_leds_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct input_led *led = container_of(cdev, struct input_led, cdev); + + input_inject_event(led->handle, EV_LED, led->code, !!brightness); +} + +static void input_leds_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ +} + +static int input_leds_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_leds *leds; + unsigned int num_leds; + unsigned int led_code; + int led_no; + int error; + + num_leds = bitmap_weight(dev->ledbit, LED_CNT); + if (!num_leds) + return -ENXIO; + + leds = kzalloc(sizeof(*leds) + num_leds * sizeof(*leds->leds), + GFP_KERNEL); + if (!leds) + return -ENOMEM; + + leds->num_leds = num_leds; + + leds->handle.dev = dev; + leds->handle.handler = handler; + leds->handle.name = "leds"; + leds->handle.private = leds; + + error = input_register_handle(&leds->handle); + if (error) + goto err_free_mem; + + error = input_open_device(&leds->handle); + if (error) + goto err_unregister_handle; + + led_no = 0; + for_each_set_bit(led_code, dev->ledbit, LED_CNT) { + struct input_led *led = &leds->leds[led_no]; + + led->handle = &leds->handle; + led->code = led_code; + + if (WARN_ON(!input_led_info[led_code].name)) + continue; + + led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", + dev_name(&dev->dev), + input_led_info[led_code].name); + if (!led->cdev.name) { + error = -ENOMEM; + goto err_unregister_leds; + } + + led->cdev.max_brightness = 1; + led->cdev.brightness_get = input_leds_brightness_get; + led->cdev.brightness_set = input_leds_brightness_set; + led->cdev.default_trigger = input_led_info[led_code].trigger; + + error = led_classdev_register(&dev->dev, &led->cdev); + if (error) { + dev_err(&dev->dev, "failed to register LED %s: %d\n", + led->cdev.name, error); + kfree(led->cdev.name); + goto err_unregister_leds; + } + + led_no++; + } + + return 0; + +err_unregister_leds: + while (--led_no >= 0) { + struct input_led *led = &leds->leds[led_no]; + + led_classdev_unregister(&led->cdev); + kfree(led->cdev.name); + } + + input_close_device(&leds->handle); + +err_unregister_handle: + input_unregister_handle(&leds->handle); + +err_free_mem: + kfree(leds); + return error; +} + +static void input_leds_disconnect(struct input_handle *handle) +{ + struct input_leds *leds = handle->private; + int i; + + for (i = 0; i < leds->num_leds; i++) { + struct input_led *led = &leds->leds[i]; + + led_classdev_unregister(&led->cdev); + kfree(led->cdev.name); + } + + input_close_device(handle); + input_unregister_handle(handle); + + kfree(leds); +} + +static const struct input_device_id input_leds_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_LED) }, + }, + { }, +}; +MODULE_DEVICE_TABLE(input, input_leds_ids); + +static struct input_handler input_leds_handler = { + .event = input_leds_event, + .connect = input_leds_connect, + .disconnect = input_leds_disconnect, + .name = "leds", + .id_table = input_leds_ids, +}; + +static int __init input_leds_init(void) +{ + return input_register_handler(&input_leds_handler); +} +module_init(input_leds_init); + +static void __exit input_leds_exit(void) +{ + input_unregister_handler(&input_leds_handler); +} +module_exit(input_leds_exit); + +MODULE_AUTHOR("Samuel Thibault <samuel.thibault@ens-lyon.org>"); +MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>"); +MODULE_DESCRIPTION("Input -> LEDs Bridge"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 966b960..4191614 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -11,9 +11,6 @@ menuconfig NEW_LEDS Say Y to enable Linux LED support. This allows control of supported LEDs from both userspace and optionally, by kernel events (triggers). - This is not related to standard keyboard LEDs which are controlled - via the input system. - if NEW_LEDS config LEDS_CLASS