Messages in this thread | | | Date | Mon, 2 Jul 2007 09:43:59 -0400 | From | "Dmitry Torokhov" <> | Subject | Re: blink driver power saving |
| |
On 7/2/07, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > > I was thinking about something like the atached (untested and sorry > for using attachment). It shoudl blink just one led (numLock) on any > keyboard that has such LED (and allows to control it). >
Argh, bad one. This one shoudl be better.
-- Dmitry /* * Debug driver that continuosly blink LEDs on keyboards * * Copyright (c) 2007 Dmitry Torokhov */
/* * 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/input.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/init.h>
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); MODULE_DESCRIPTION("Blink driver"); MODULE_LICENSE("GPL");
struct blinker { struct delayed_work work; struct input_handle handle; int state; };
static void blink_task_handler(struct work_struct *work) { struct blinker *blinker = container_of(work, struct blinker, work.work);
blinker->state = !blinker->state; input_inject_event(&blinker->handle, EV_LED, LED_NUML, blinker->state); schedule_delayed_work(&blinker->work, msecs_to_jiffies(250)); }
static void blink_event(struct input_handle *handle, unsigned int type, unsigned int code, int down) { /* * This is a very rare handler that does not process any input * events; just injects them. */ }
static int blink_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct blinker *blinker; struct input_handle *handle; int error;
blinker = kzalloc(sizeof(struct blinker), GFP_KERNEL); if (!blinker) return -ENOMEM;
INIT_DELAYED_WORK(&blinker->work, blink_task_handler);
handle = &blinker->handle; handle->dev = dev; handle->handler = handler; handle->name = "blink"; handle->private = blinker;
error = input_register_handle(handle); if (error) goto err_free_handle;
error = input_open_device(handle); if (error) goto err_unregister_handle;
schedule_delayed_work(&blinker->work, 0);
return 0;
err_unregister_handle: input_unregister_handle(handle); err_free_handle: kfree(handle); return error; }
static void blink_disconnect(struct input_handle *handle) { struct blinker *blinker = handle->private;
cancel_rearming_delayed_work(&blinker->work); input_close_device(handle); input_unregister_handle(handle); kfree(blinker); }
static const struct input_device_id blink_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_LEDBIT, .evbit = { BIT(EV_LED) }, .ledbit = { [LONG(LED_NUML)] = BIT(LED_NUML) }, }, { } };
static struct input_handler blink_handler = { .event = blink_event, .connect = blink_connect, .disconnect = blink_disconnect, .name = "blink", .id_table = blink_ids, };
static int __init blink_handler_init(void) { return input_register_handler(&blink_handler); }
static void __exit blink_handler_exit(void) { input_unregister_handler(&blink_handler); flush_scheduled_work(); }
module_init(blink_handler_init); module_exit(blink_handler_exit);
| |