linux-bk/drivers/input/power.c
<<
>>
Prefs
   1/*
   2 * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
   3 *
   4 *  Copyright (c) 2001 "Crazy" James Simmons
   5 *
   6 *  Input driver Power Management.
   7 *
   8 *  Sponsored by Transvirtual Technology.
   9 */
  10
  11/*
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25 *
  26 * Should you need to contact me, the author, you can do so by
  27 * e-mail - mail your message to <jsimmons@transvirtual.com>.
  28 */
  29
  30#include <linux/module.h>
  31#include <linux/config.h>
  32#include <linux/input.h>
  33#include <linux/slab.h>
  34#include <linux/init.h>
  35#include <linux/tty.h>
  36#include <linux/delay.h>
  37#include <linux/pm.h>
  38
  39static struct input_handler power_handler;
  40
  41/*
  42 * Power management can't be done in a interrupt context. So we have to
  43 * use keventd.
  44 */
  45static int suspend_button_pushed = 0;
  46static void suspend_button_task_handler(void *data)
  47{
  48        udelay(200); /* debounce */
  49        suspend_button_pushed = 0;
  50}
  51
  52static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL);
  53
  54static void power_event(struct input_handle *handle, unsigned int type,
  55                        unsigned int code, int down)
  56{
  57        struct input_dev *dev = handle->dev;
  58
  59        printk("Entering power_event\n");
  60
  61        if (type != EV_KEY || type != EV_PWR) return;
  62
  63        if (type == EV_PWR) {
  64                switch (code) {
  65                        case KEY_SUSPEND:
  66                                printk("Powering down entire device\n");
  67
  68                                if (!suspend_button_pushed) {
  69                                        suspend_button_pushed = 1;
  70                                        schedule_work(&suspend_button_task);
  71                                }
  72                                break;
  73                        case KEY_POWER:
  74                                /* Hum power down the machine. */
  75                                break;
  76                        default:
  77                                return;
  78                }
  79        } else {
  80                switch (code) {
  81                        case KEY_SUSPEND:
  82                                printk("Powering down input device\n");
  83                                /* This is risky. See pm.h for details. */
  84                                if (dev->state != PM_RESUME)
  85                                        dev->state = PM_RESUME;
  86                                else
  87                                        dev->state = PM_SUSPEND;
  88                                pm_send(dev->pm_dev, dev->state, dev);
  89                                break;
  90                        case KEY_POWER:
  91                                /* Turn the input device off completely ? */
  92                                break;
  93                        default:
  94                                return;
  95                }
  96        }
  97        return;
  98}
  99
 100static struct input_handle *power_connect(struct input_handler *handler,
 101                                          struct input_dev *dev,
 102                                          struct input_device_id *id)
 103{
 104        struct input_handle *handle;
 105
 106        if (!test_bit(EV_KEY, dev->evbit) || !test_bit(EV_PWR, dev->evbit))
 107                return NULL;
 108
 109        if (!test_bit(KEY_SUSPEND, dev->keybit) || (!test_bit(KEY_POWER, dev->keybit)))
 110                return NULL;
 111
 112        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
 113                return NULL;
 114        memset(handle, 0, sizeof(struct input_handle));
 115
 116        handle->dev = dev;
 117        handle->handler = handler;
 118
 119        input_open_device(handle);
 120
 121        printk(KERN_INFO "power.c: Adding power management to input layer\n");
 122        return handle;
 123}
 124
 125static void power_disconnect(struct input_handle *handle)
 126{
 127        input_close_device(handle);
 128        kfree(handle);
 129}
 130
 131static struct input_device_id power_ids[] = {
 132        {
 133                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 134                .evbit = { BIT(EV_KEY) },
 135                .keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
 136        },
 137        {
 138                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 139                .evbit = { BIT(EV_KEY) },
 140                .keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
 141        },
 142        {
 143                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
 144                .evbit = { BIT(EV_PWR) },
 145        },
 146        { },    /* Terminating entry */
 147};
 148
 149MODULE_DEVICE_TABLE(input, power_ids);
 150
 151static struct input_handler power_handler = {
 152        .event =        power_event,
 153        .connect =      power_connect,
 154        .disconnect =   power_disconnect,
 155        .name =         "power",
 156        .id_table =     power_ids,
 157};
 158
 159static int __init power_init(void)
 160{
 161        input_register_handler(&power_handler);
 162        return 0;
 163}
 164
 165static void __exit power_exit(void)
 166{
 167        input_unregister_handler(&power_handler);
 168}
 169
 170module_init(power_init);
 171module_exit(power_exit);
 172
 173MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
 174MODULE_DESCRIPTION("Input Power Management driver");
 175MODULE_LICENSE("GPL");
 176
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.