PageRenderTime 29ms CodeModel.GetById 18ms app.highlight 8ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/input/power.c

https://bitbucket.org/abioy/linux
C | 174 lines | 115 code | 25 blank | 34 comment | 18 complexity | 197f75aadc4c82ef2ac3e173e0283b5c MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  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");