Re: blink driver power saving

From: Dmitry Torokhov
Date: Mon Jul 02 2007 - 09:44:18 EST


On 7/2/07, Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> 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@xxxxxxx>");
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);