mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
usb_hid: mode led handling to shadow input-leds.c
The former implementation relied on input drvdata always pointing to struct hid_device, which is not true for Wacom touch devices (at least). Now, we implement the input handler for devices providing LEDs (evbit[EV_LED] set) only and use input_inject_event() to set the LED states.
This commit is contained in:
parent
d6d1b8e025
commit
092e4a001f
@ -113,7 +113,7 @@ install_config {
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="140">
|
||||
<start name="usb_hid_drv" caps="180">
|
||||
<resource name="RAM" quantum="11M"/>
|
||||
<config use_report="yes" capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
|
||||
<route>
|
||||
@ -132,23 +132,41 @@ install_config {
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides> <service name="ROM"/> </provides>
|
||||
<config verbose="no">
|
||||
<rom name="capslock">
|
||||
<inline> <capslock enabled="no"/> </inline>
|
||||
<sleep milliseconds="250" />
|
||||
<inline> <capslock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="250" />
|
||||
</rom>
|
||||
<rom name="numlock">
|
||||
<inline> <numlock enabled="no"/> </inline>
|
||||
<inline> <numlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <numlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <numlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <numlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <numlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
</rom>
|
||||
<rom name="capslock">
|
||||
<inline> <capslock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500"/>
|
||||
<inline> <capslock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <capslock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <capslock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <capslock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
</rom>
|
||||
<rom name="scrlock">
|
||||
<inline> <scrlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="1000" />
|
||||
<inline> <scrlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500"/>
|
||||
<inline> <scrlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <scrlock enabled="no"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <scrlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="1000" />
|
||||
<sleep milliseconds="500" />
|
||||
<inline> <scrlock enabled="yes"/> </inline>
|
||||
<sleep milliseconds="500" />
|
||||
</rom>
|
||||
</config>
|
||||
<route>
|
||||
|
@ -68,7 +68,7 @@ install_config {
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="140">
|
||||
<start name="usb_hid_drv" caps="180">
|
||||
<resource name="RAM" quantum="11M"/>
|
||||
<config use_report="yes" capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
|
||||
<route>
|
||||
|
@ -1,206 +0,0 @@
|
||||
/*
|
||||
* \brief Keyboard LED handling
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2023-06-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
struct keyboard
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
struct usb_interface *intf;
|
||||
struct usb_device *udev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
||||
enum Update_state { NONE, UPDATE, BLOCKED };
|
||||
|
||||
struct led_update
|
||||
{
|
||||
enum Update_state state;
|
||||
struct completion update;
|
||||
unsigned leds;
|
||||
};
|
||||
|
||||
|
||||
static LIST_HEAD(_keyboards);
|
||||
static struct led_update _led_update;
|
||||
|
||||
|
||||
static bool keyboard_match(struct keyboard *kbd, struct input_dev *input_dev)
|
||||
{
|
||||
return kbd->input_dev == input_dev;
|
||||
}
|
||||
|
||||
|
||||
static void keyboard_update(struct keyboard *kbd, unsigned leds)
|
||||
{
|
||||
usb_control_msg(kbd->udev, usb_sndctrlpipe(kbd->udev, 0),
|
||||
0x9, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x200,
|
||||
kbd->intf->cur_altsetting->desc.bInterfaceNumber,
|
||||
&leds, 1, 500);
|
||||
}
|
||||
|
||||
|
||||
void lx_led_state_update(bool capslock, bool numlock, bool scrlock)
|
||||
{
|
||||
|
||||
struct keyboard *kbd;
|
||||
unsigned leds = 0;
|
||||
|
||||
leds |= capslock ? 1u << LED_CAPSL : 0;
|
||||
leds |= numlock ? 1u << LED_NUML : 0;
|
||||
leds |= scrlock ? 1u << LED_SCROLLL : 0;
|
||||
|
||||
_led_update.leds = leds;
|
||||
_led_update.state = UPDATE;
|
||||
|
||||
/* udpdate keyboards */
|
||||
list_for_each_entry(kbd, &_keyboards, list) {
|
||||
keyboard_update(kbd, leds);
|
||||
}
|
||||
|
||||
if (_led_update.state == BLOCKED)
|
||||
complete(&_led_update.update);
|
||||
|
||||
_led_update.state = NONE;
|
||||
}
|
||||
|
||||
|
||||
static void wait_for_update(void)
|
||||
{
|
||||
if (_led_update.state == UPDATE) {
|
||||
_led_update.state = BLOCKED;
|
||||
wait_for_completion(&_led_update.update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int led_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
const struct input_device_id *id)
|
||||
{
|
||||
struct keyboard *kbd;
|
||||
struct input_handle *handle;
|
||||
|
||||
wait_for_update();
|
||||
|
||||
handle = (struct input_handle *)kzalloc(sizeof(*handle), 0);
|
||||
if (!handle) return -ENOMEM;
|
||||
handle->dev = input_get_device(dev);
|
||||
handle->handler = handler;
|
||||
|
||||
kbd = (struct keyboard *)kzalloc(sizeof(*kbd), GFP_KERNEL);
|
||||
if (!kbd) goto err;
|
||||
|
||||
kbd->input_dev = input_get_device(dev);
|
||||
kbd->intf = container_of(kbd->input_dev->dev.parent->parent, struct usb_interface, dev);
|
||||
kbd->udev = interface_to_usbdev(kbd->intf);
|
||||
|
||||
INIT_LIST_HEAD(&kbd->list);
|
||||
list_add_tail(&kbd->list, &_keyboards);
|
||||
|
||||
keyboard_update(kbd, _led_update.leds);
|
||||
|
||||
input_register_handle(handle);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(handle);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
static void led_disconnect(struct input_handle *handle)
|
||||
{
|
||||
struct input_dev *dev = handle->dev;
|
||||
struct keyboard *kbd, *temp;
|
||||
|
||||
wait_for_update();
|
||||
|
||||
list_for_each_entry_safe(kbd, temp, &_keyboards, list) {
|
||||
if (keyboard_match(kbd, dev)) {
|
||||
list_del(&kbd->list);
|
||||
kfree(kbd);
|
||||
}
|
||||
}
|
||||
input_unregister_handle(handle);
|
||||
input_put_device(dev);
|
||||
kfree(handle);
|
||||
}
|
||||
|
||||
|
||||
static bool led_match(struct input_handler *handler, struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = (struct hid_device *)input_get_drvdata(dev);
|
||||
struct hid_report *report;
|
||||
struct hid_usage *usage;
|
||||
unsigned i, j;
|
||||
|
||||
/* search report for keyboard entries */
|
||||
list_for_each_entry(report, &hid->report_enum[0].report_list, list) {
|
||||
|
||||
for (i = 0; i < report->maxfield; i++)
|
||||
for (j = 0; j < report->field[i]->maxusage; j++) {
|
||||
usage = report->field[i]->usage + j;
|
||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static struct input_device_id led_ids[] = {
|
||||
{ .driver_info = 1 }, /* match all */
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(input, led_ids);
|
||||
|
||||
static struct input_handler led_handler = {
|
||||
.name = "keyboard_led",
|
||||
.connect = led_connect,
|
||||
.disconnect = led_disconnect,
|
||||
.id_table = led_ids,
|
||||
.match = led_match,
|
||||
.id_table = led_ids,
|
||||
};
|
||||
|
||||
|
||||
static int __init input_leds_init(void)
|
||||
{
|
||||
_led_update.state = NONE;
|
||||
init_completion(&_led_update.update);
|
||||
|
||||
return input_register_handler(&led_handler);
|
||||
}
|
||||
|
||||
|
||||
static void __exit input_leds_exit(void)
|
||||
{
|
||||
input_unregister_handler(&led_handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let's hook into the input_leds initcall, so we do not need to register
|
||||
* an additional one
|
||||
*/
|
||||
module_init(input_leds_init);
|
||||
module_exit(input_leds_exit);
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <lx_emul/init.h>
|
||||
#include <lx_emul/task.h>
|
||||
#include <lx_emul/input_leds.h>
|
||||
#include <lx_kit/env.h>
|
||||
|
||||
#include <genode_c_api/event.h>
|
||||
@ -127,9 +128,9 @@ struct Leds
|
||||
while (true) {
|
||||
led.handle_config();
|
||||
|
||||
lx_led_state_update(led.capslock.enabled(),
|
||||
led.numlock.enabled(),
|
||||
led.scrlock.enabled());
|
||||
lx_emul_input_leds_update(led.capslock.enabled(),
|
||||
led.numlock.enabled(),
|
||||
led.scrlock.enabled());
|
||||
|
||||
led.led_task_handler.block_and_schedule();
|
||||
}
|
||||
|
@ -6,11 +6,11 @@ arch/arm/lib/strchr.S
|
||||
arch/arm/lib/testclearbit.S
|
||||
arch/arm/lib/testsetbit.S
|
||||
drivers/base/bus.c
|
||||
drivers/base/core.c
|
||||
drivers/base/class.c
|
||||
drivers/base/core.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/devres.c
|
||||
drivers/base/driver.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/property.c
|
||||
drivers/hid/hid-apple.c
|
||||
drivers/hid/hid-cherry.c
|
||||
@ -41,8 +41,8 @@ kernel/time/clocksource.c
|
||||
kernel/time/hrtimer.c
|
||||
kernel/time/jiffies.c
|
||||
kernel/time/ntp.c
|
||||
kernel/time/tick-broadcast.c
|
||||
kernel/time/tick-broadcast-hrtimer.c
|
||||
kernel/time/tick-broadcast.c
|
||||
kernel/time/tick-common.c
|
||||
kernel/time/tick-oneshot.c
|
||||
kernel/time/tick-sched.c
|
||||
@ -53,7 +53,6 @@ kernel/time/timekeeping.c
|
||||
kernel/time/timer.c
|
||||
kernel/time/timer_list.c
|
||||
kernel/workqueue.c
|
||||
mm/util.c
|
||||
lib/bitmap.c
|
||||
lib/ctype.c
|
||||
lib/find_bit.c
|
||||
@ -65,8 +64,9 @@ lib/klist.c
|
||||
lib/kobject.c
|
||||
lib/kstrtox.c
|
||||
lib/radix-tree.c
|
||||
lib/xarray.c
|
||||
lib/siphash.c
|
||||
lib/string.c
|
||||
lib/string_helpers.c
|
||||
lib/vsprintf.c
|
||||
lib/xarray.c
|
||||
mm/util.c
|
||||
|
@ -4,11 +4,11 @@ arch/arm64/lib/strcmp.S
|
||||
arch/arm64/lib/strlen.S
|
||||
arch/arm64/lib/strncmp.S
|
||||
drivers/base/bus.c
|
||||
drivers/base/core.c
|
||||
drivers/base/class.c
|
||||
drivers/base/core.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/devres.c
|
||||
drivers/base/driver.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/property.c
|
||||
drivers/hid/hid-apple.c
|
||||
drivers/hid/hid-cherry.c
|
||||
@ -39,8 +39,8 @@ kernel/time/clocksource.c
|
||||
kernel/time/hrtimer.c
|
||||
kernel/time/jiffies.c
|
||||
kernel/time/ntp.c
|
||||
kernel/time/tick-broadcast.c
|
||||
kernel/time/tick-broadcast-hrtimer.c
|
||||
kernel/time/tick-broadcast.c
|
||||
kernel/time/tick-common.c
|
||||
kernel/time/tick-oneshot.c
|
||||
kernel/time/tick-sched.c
|
||||
@ -51,7 +51,6 @@ kernel/time/timekeeping.c
|
||||
kernel/time/timer.c
|
||||
kernel/time/timer_list.c
|
||||
kernel/workqueue.c
|
||||
mm/util.c
|
||||
lib/bitmap.c
|
||||
lib/ctype.c
|
||||
lib/find_bit.c
|
||||
@ -63,8 +62,9 @@ lib/klist.c
|
||||
lib/kobject.c
|
||||
lib/kstrtox.c
|
||||
lib/radix-tree.c
|
||||
lib/xarray.c
|
||||
lib/siphash.c
|
||||
lib/string.c
|
||||
lib/string_helpers.c
|
||||
lib/vsprintf.c
|
||||
lib/xarray.c
|
||||
mm/util.c
|
||||
|
@ -1,10 +1,10 @@
|
||||
arch/x86/lib/hweight.S
|
||||
drivers/base/bus.c
|
||||
drivers/base/core.c
|
||||
drivers/base/class.c
|
||||
drivers/base/core.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/devres.c
|
||||
drivers/base/driver.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/property.c
|
||||
drivers/hid/hid-apple.c
|
||||
drivers/hid/hid-cherry.c
|
||||
@ -46,7 +46,6 @@ kernel/time/timekeeping.c
|
||||
kernel/time/timer.c
|
||||
kernel/time/timer_list.c
|
||||
kernel/workqueue.c
|
||||
mm/util.c
|
||||
lib/bitmap.c
|
||||
lib/ctype.c
|
||||
lib/find_bit.c
|
||||
@ -57,8 +56,9 @@ lib/klist.c
|
||||
lib/kobject.c
|
||||
lib/kstrtox.c
|
||||
lib/radix-tree.c
|
||||
lib/xarray.c
|
||||
lib/siphash.c
|
||||
lib/string.c
|
||||
lib/string_helpers.c
|
||||
lib/vsprintf.c
|
||||
lib/xarray.c
|
||||
mm/util.c
|
||||
|
@ -1,10 +1,10 @@
|
||||
arch/x86/lib/hweight.S
|
||||
drivers/base/bus.c
|
||||
drivers/base/core.c
|
||||
drivers/base/class.c
|
||||
drivers/base/core.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/devres.c
|
||||
drivers/base/driver.c
|
||||
drivers/base/dd.c
|
||||
drivers/base/property.c
|
||||
drivers/hid/hid-apple.c
|
||||
drivers/hid/hid-cherry.c
|
||||
@ -46,7 +46,6 @@ kernel/time/timekeeping.c
|
||||
kernel/time/timer.c
|
||||
kernel/time/timer_list.c
|
||||
kernel/workqueue.c
|
||||
mm/util.c
|
||||
lib/bitmap.c
|
||||
lib/ctype.c
|
||||
lib/find_bit.c
|
||||
@ -57,8 +56,9 @@ lib/klist.c
|
||||
lib/kobject.c
|
||||
lib/kstrtox.c
|
||||
lib/radix-tree.c
|
||||
lib/xarray.c
|
||||
lib/siphash.c
|
||||
lib/string.c
|
||||
lib/string_helpers.c
|
||||
lib/vsprintf.c
|
||||
lib/xarray.c
|
||||
mm/util.c
|
||||
|
@ -5,11 +5,11 @@ INC_DIR = $(PRG_DIR)/../.. $(REP_DIR)/src/lib/usb_client
|
||||
|
||||
SRC_C += dummies.c \
|
||||
generated_dummies.c \
|
||||
led.c \
|
||||
lx_emul.c \
|
||||
lx_user.c
|
||||
|
||||
SRC_C += lx_emul/shadow/drivers/input/evdev.c \
|
||||
lx_emul/shadow/drivers/input/input-leds.c \
|
||||
lx_emul/virt/shadow/drivers/usb/core/message.c \
|
||||
lx_emul/virt/shadow/drivers/usb/core/urb.c \
|
||||
lx_emul/virt/usb_client.c
|
||||
|
27
repos/dde_linux/src/include/lx_emul/input_leds.h
Normal file
27
repos/dde_linux/src/include/lx_emul/input_leds.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* \brief Lx_emul support for input leds
|
||||
* \author Christian Helmuth
|
||||
* \date 2024-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LX_EMUL__INPUT_LEDS_H_
|
||||
#define _LX_EMUL__INPUT_LEDS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void lx_emul_input_leds_update(bool capslock, bool numlock, bool scrolllock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LX_EMUL__INPUT_LEDS_H_ */
|
@ -311,6 +311,9 @@ static void evdev_event_generator(struct genode_event_generator_ctx *ctx,
|
||||
|
||||
bool processed = false;
|
||||
|
||||
/* filter injected EV_LED updates */
|
||||
if (v->type == EV_LED) continue;
|
||||
|
||||
/* filter input_repeat_key() */
|
||||
if ((v->type == EV_KEY) && (v->value > 1)) continue;
|
||||
|
||||
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* \brief Input LED handling
|
||||
* \author Sebastian Sumpf
|
||||
* \author Christian Helmuth
|
||||
* \date 2023-06-29
|
||||
*
|
||||
* This implementation is derived from drivers/input/input-leds.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <lx_emul/input_leds.h>
|
||||
|
||||
|
||||
struct led_handler
|
||||
{
|
||||
struct list_head list;
|
||||
struct input_handle handle;
|
||||
};
|
||||
|
||||
static LIST_HEAD(led_handlers);
|
||||
|
||||
|
||||
enum Update_state { NONE, UPDATE, BLOCKED };
|
||||
|
||||
struct led_update
|
||||
{
|
||||
enum Update_state state;
|
||||
struct completion update;
|
||||
|
||||
bool capsl, numl, scrolll;
|
||||
};
|
||||
|
||||
static struct led_update led_update;
|
||||
|
||||
|
||||
static void update_leds(struct led_handler *handler)
|
||||
{
|
||||
input_inject_event(&handler->handle, EV_LED, LED_CAPSL, led_update.capsl);
|
||||
input_inject_event(&handler->handle, EV_LED, LED_NUML, led_update.numl);
|
||||
input_inject_event(&handler->handle, EV_LED, LED_SCROLLL, led_update.scrolll);
|
||||
}
|
||||
|
||||
|
||||
void lx_emul_input_leds_update(bool capslock, bool numlock, bool scrolllock)
|
||||
{
|
||||
|
||||
struct led_handler *handler;
|
||||
|
||||
led_update.state = UPDATE;
|
||||
|
||||
led_update.capsl = capslock;
|
||||
led_update.numl = numlock;
|
||||
led_update.scrolll = scrolllock;
|
||||
|
||||
list_for_each_entry(handler, &led_handlers, list) {
|
||||
update_leds(handler);
|
||||
}
|
||||
|
||||
if (led_update.state == BLOCKED)
|
||||
complete(&led_update.update);
|
||||
|
||||
led_update.state = NONE;
|
||||
}
|
||||
|
||||
|
||||
static void wait_for_update(void)
|
||||
{
|
||||
if (led_update.state == UPDATE) {
|
||||
led_update.state = BLOCKED;
|
||||
wait_for_completion(&led_update.update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int input_leds_connect(struct input_handler *input_handler, struct input_dev *dev,
|
||||
const struct input_device_id *id)
|
||||
{
|
||||
struct led_handler *handler;
|
||||
|
||||
wait_for_update();
|
||||
|
||||
handler = (struct led_handler *)kzalloc(sizeof(*handler), GFP_KERNEL);
|
||||
if (!handler)
|
||||
return -ENOMEM;
|
||||
|
||||
handler->handle.dev = input_get_device(dev);
|
||||
handler->handle.handler = input_handler;
|
||||
handler->handle.name = "leds";
|
||||
handler->handle.private = handler;
|
||||
|
||||
INIT_LIST_HEAD(&handler->list);
|
||||
list_add_tail(&handler->list, &led_handlers);
|
||||
|
||||
update_leds(handler);
|
||||
|
||||
input_register_handle(&handler->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void input_leds_disconnect(struct input_handle *handle)
|
||||
{
|
||||
struct led_handler *handler = (struct led_handler *)handle->private;
|
||||
|
||||
wait_for_update();
|
||||
|
||||
list_del(&handler->list);
|
||||
input_unregister_handle(handle);
|
||||
input_put_device(handle->dev);
|
||||
kfree(handler);
|
||||
}
|
||||
|
||||
|
||||
static struct input_device_id input_leds_ids[] = {
|
||||
{
|
||||
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
||||
.evbit = { BIT_MASK(EV_LED) },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(input, led_ids);
|
||||
|
||||
static struct input_handler input_leds_handler = {
|
||||
.name = "input-leds",
|
||||
.connect = input_leds_connect,
|
||||
.disconnect = input_leds_disconnect,
|
||||
.id_table = input_leds_ids,
|
||||
};
|
||||
|
||||
|
||||
static int __init input_leds_init(void)
|
||||
{
|
||||
led_update.state = NONE;
|
||||
init_completion(&led_update.update);
|
||||
|
||||
return input_register_handler(&input_leds_handler);
|
||||
}
|
||||
|
||||
|
||||
static void __exit input_leds_exit(void)
|
||||
{
|
||||
input_unregister_handler(&input_leds_handler);
|
||||
}
|
||||
|
||||
|
||||
module_init(input_leds_init);
|
||||
module_exit(input_leds_exit);
|
@ -138,7 +138,7 @@
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="140">
|
||||
<start name="usb_hid_drv" caps="180">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<config use_report="yes"/>
|
||||
<route>
|
||||
|
Loading…
x
Reference in New Issue
Block a user