leds: reinstate Peter Korsgaard's awesome LED input trigger

This commit is contained in:
Matt Sealey
2011-02-16 00:57:35 -06:00
parent ac20d1afab
commit b2ae29b6a3
3 changed files with 174 additions and 10 deletions

View File

@@ -36,15 +36,6 @@ config LEDS_MC13892
tristate "LED Support for mc13892 pmic"
depends on LEDS_CLASS && MXC_MC13892_LIGHT
config LEDS_EFIKASB
tristate "LED Support for Efika MX Smartbook"
depends on LEDS_CLASS && MACH_MX51_EFIKASB
help
This option enable support for the LEDs on Efika MX Smartbook.
config LEDS_LOCOMO
tristate "LED Support for Locomo device"
depends on LEDS_CLASS && SHARP_LOCOMO
@@ -315,6 +306,13 @@ config LEDS_TRIGGER_DEFAULT_ON
This allows LEDs to be initialised in the ON state.
If unsure, say Y.
config LEDS_TRIGGER_INPUT
tristate "Input subsystem LEDs Trigger"
depends on LEDS_TRIGGERS && INPUT
help
This allows LEDs to be controlled by input subsystem LED
state (capslock/numlock/scrollock)
comment "iptables trigger is under Netfilter config (LED target)"
depends on LEDS_TRIGGERS

View File

@@ -8,7 +8,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
obj-$(CONFIG_LEDS_MC13892) += leds-mc13892.o
obj-$(CONFIG_LEDS_EFIKASB) += leds-efikasb.o
obj-$(CONFIG_LEDS_STMP378X) += leds-stmp378x-pwm.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
@@ -43,3 +42,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o

166
drivers/leds/ledtrig-input.c Executable file
View File

@@ -0,0 +1,166 @@
/*
* led trigger for input subsystem led states
*
* Peter Korsgaard <jacmet@sunsite.dk>
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include "leds.h"
struct input_trig {
int value; /* current value of input LED */
struct work_struct work;
struct led_trigger trig;
};
static int trig_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct input_handle *handle;
int error;
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
return -ENOMEM;
handle->dev = dev;
handle->handler = handler;
handle->name = "ledtrig-input";
error = input_register_handle(handle);
if (error)
goto err_free_handle;
error = input_open_device(handle);
if (error)
goto err_unregister_handle;
return 0;
err_unregister_handle:
input_unregister_handle(handle);
err_free_handle:
kfree(handle);
return error;
}
static void trig_disconnect(struct input_handle *handle)
{
input_close_device(handle);
input_unregister_handle(handle);
kfree(handle);
}
static void trig_activate(struct led_classdev *led_cdev)
{
struct input_trig *input = container_of(led_cdev->trigger,
struct input_trig, trig);
led_set_brightness(led_cdev, input->value ? LED_FULL : LED_OFF);
}
static struct input_trig trig[] = {
[LED_NUML] = {
.trig = {
.name = "numlock",
.activate = trig_activate,
},
},
[LED_CAPSL] = {
.trig = {
.name = "capslock",
.activate = trig_activate,
}
},
[LED_SCROLLL] = {
.trig = {
.name = "scrolllock",
.activate = trig_activate,
},
},
};
static void trig_event(struct input_handle *handle, unsigned int type,
unsigned int code, int value)
{
if (type == EV_LED && code < ARRAY_SIZE(trig)) {
if (value != trig[code].value) {
trig[code].value = value;
schedule_work(&trig[code].work);
}
}
}
static const struct input_device_id trig_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
.evbit = { BIT_MASK(EV_LED) },
},
{ }, /* Terminating zero entry */
};
MODULE_DEVICE_TABLE(input, trig_ids);
static struct input_handler trig_handler = {
.event = trig_event,
.connect = trig_connect,
.disconnect = trig_disconnect,
.name = "ledtrig-input",
.id_table = trig_ids,
};
static void trig_work(struct work_struct *work)
{
struct input_trig *input = container_of(work, struct input_trig, work);
led_trigger_event(&input->trig, input->value ? LED_FULL : LED_OFF);
}
static int __init trig_init(void)
{
int i, ret;
for (i=0; i<ARRAY_SIZE(trig); i++) {
INIT_WORK(&trig[i].work, trig_work);
ret = led_trigger_register(&trig[i].trig);
if (ret)
goto trig_reg_fail;
}
ret = input_register_handler(&trig_handler);
if (!ret)
return 0;
trig_reg_fail:
for (; i>0; i--)
led_trigger_unregister(&trig[i-1].trig);
return ret;
}
module_init(trig_init);
static void __exit trig_exit(void)
{
int i;
input_unregister_handler(&trig_handler);
for (i=0; i<ARRAY_SIZE(trig); i++) {
cancel_work_sync(&trig[i].work);
led_trigger_unregister(&trig[i].trig);
}
}
module_exit(trig_exit);
MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
MODULE_DESCRIPTION("LED trigger for input subsystem LEDs");
MODULE_LICENSE("GPL");