1 // SPDX-License-Identifier: GPL-2.0-only
3 * Input Events LED trigger
5 * Copyright (C) 2024 Hans de Goede <hansg@kernel.org>
8 #include <linux/input.h>
9 #include <linux/jiffies.h>
10 #include <linux/leds.h>
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/slab.h>
14 #include <linux/spinlock.h>
15 #include <linux/workqueue.h>
18 static unsigned long led_off_delay_ms
= 5000;
19 module_param(led_off_delay_ms
, ulong
, 0644);
20 MODULE_PARM_DESC(led_off_delay_ms
,
21 "Specify delay in ms for turning LEDs off after last input event");
23 static struct input_events_data
{
24 struct delayed_work work
;
26 /* To avoid repeatedly setting the brightness while there are events */
28 unsigned long led_off_time
;
31 static struct led_trigger
*input_events_led_trigger
;
33 static void led_input_events_work(struct work_struct
*work
)
35 struct input_events_data
*data
=
36 container_of(work
, struct input_events_data
, work
.work
);
38 spin_lock_irq(&data
->lock
);
41 * This time_after_eq() check avoids a race where this work starts
42 * running before a new event pushed led_off_time back.
44 if (time_after_eq(jiffies
, data
->led_off_time
)) {
45 led_trigger_event(input_events_led_trigger
, LED_OFF
);
49 spin_unlock_irq(&data
->lock
);
52 static void input_events_event(struct input_handle
*handle
, unsigned int type
,
53 unsigned int code
, int val
)
55 struct input_events_data
*data
= &input_events_data
;
56 unsigned long led_off_delay
= msecs_to_jiffies(led_off_delay_ms
);
59 spin_lock_irqsave(&data
->lock
, flags
);
62 led_trigger_event(input_events_led_trigger
, LED_FULL
);
65 data
->led_off_time
= jiffies
+ led_off_delay
;
67 spin_unlock_irqrestore(&data
->lock
, flags
);
69 mod_delayed_work(system_wq
, &data
->work
, led_off_delay
);
72 static int input_events_connect(struct input_handler
*handler
, struct input_dev
*dev
,
73 const struct input_device_id
*id
)
75 struct input_handle
*handle
;
78 handle
= kzalloc(sizeof(*handle
), GFP_KERNEL
);
83 handle
->handler
= handler
;
84 handle
->name
= KBUILD_MODNAME
;
86 ret
= input_register_handle(handle
);
90 ret
= input_open_device(handle
);
92 goto err_unregister_handle
;
96 err_unregister_handle
:
97 input_unregister_handle(handle
);
103 static void input_events_disconnect(struct input_handle
*handle
)
105 input_close_device(handle
);
106 input_unregister_handle(handle
);
110 static const struct input_device_id input_events_ids
[] = {
112 .flags
= INPUT_DEVICE_ID_MATCH_EVBIT
,
113 .evbit
= { BIT_MASK(EV_KEY
) },
116 .flags
= INPUT_DEVICE_ID_MATCH_EVBIT
,
117 .evbit
= { BIT_MASK(EV_REL
) },
120 .flags
= INPUT_DEVICE_ID_MATCH_EVBIT
,
121 .evbit
= { BIT_MASK(EV_ABS
) },
126 static struct input_handler input_events_handler
= {
127 .name
= KBUILD_MODNAME
,
128 .event
= input_events_event
,
129 .connect
= input_events_connect
,
130 .disconnect
= input_events_disconnect
,
131 .id_table
= input_events_ids
,
134 static int __init
input_events_init(void)
138 INIT_DELAYED_WORK(&input_events_data
.work
, led_input_events_work
);
139 spin_lock_init(&input_events_data
.lock
);
141 led_trigger_register_simple("input-events", &input_events_led_trigger
);
143 ret
= input_register_handler(&input_events_handler
);
145 led_trigger_unregister_simple(input_events_led_trigger
);
152 static void __exit
input_events_exit(void)
154 input_unregister_handler(&input_events_handler
);
155 cancel_delayed_work_sync(&input_events_data
.work
);
156 led_trigger_unregister_simple(input_events_led_trigger
);
159 module_init(input_events_init
);
160 module_exit(input_events_exit
);
162 MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>");
163 MODULE_DESCRIPTION("Input Events LED trigger");
164 MODULE_LICENSE("GPL");
165 MODULE_ALIAS("ledtrig:input-events");