2
* polling.c -- scancode emulation for volume buttons
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation; either version 2, or (at your option) any
9
* This program is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* Written by Soós Péter <sp@osb.hu>, 2002-2004
15
* Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
20
#include <linux/workqueue.h>
21
#include <linux/jiffies.h>
24
* XE3GC type key_polling polling:
26
* Polling interval for keys (100 ms)
29
#define OMNIBOOK_POLL msecs_to_jiffies(100)
32
* workqueue manipulations are mutex protected and thus kept in sync with key_polling_enabled
34
static struct workqueue_struct *omnibook_wq;
35
static int key_polling_enabled;
36
static DEFINE_MUTEX(poll_mutex);
38
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
39
static void omnibook_key_poller(struct work_struct *work);
40
DECLARE_DELAYED_WORK(omnibook_poll_work, *omnibook_key_poller);
42
static void omnibook_key_poller(void *data);
43
DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, NULL);
46
static struct omnibook_feature key_polling_driver;
47
static struct input_dev *poll_input_dev;
49
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
50
static void omnibook_key_poller(struct work_struct *work)
52
static void omnibook_key_poller(void *data)
58
mutex_lock(&key_polling_driver.io_op->backend->mutex);
59
__backend_byte_read(key_polling_driver.io_op, &q0a);
60
__backend_byte_write(key_polling_driver.io_op, 0);
61
mutex_unlock(&key_polling_driver.io_op->backend->mutex);
63
#ifdef CONFIG_OMNIBOOK_DEBUG
64
if (unlikely(q0a & XE3GC_SLPB_MASK))
65
dprintk("Sleep button pressed.\n");
66
if (unlikely(q0a & XE3GC_F5_MASK))
67
dprintk("Fn-F5 - LCD/CRT switch pressed.\n");
68
if (unlikely(q0a & XE3GC_CNTR_MASK))
69
dprintk("Fn+F3/Fn+F4 - Contrast up or down pressed.\n");
70
if (unlikely(q0a & XE3GC_BRGT_MASK))
71
dprintk("Fn+F1/Fn+F2 - Brightness up or down pressed.\n");
75
* Volume button scancode emulaton
76
* It emulates a key press and a release without repeat as other OneTouch buttons do.
79
if (unlikely(q0a & XE3GC_VOLD_MASK)) {
80
dprintk("Fn-down arrow or Volume down pressed.\n");
81
omnibook_report_key(poll_input_dev, KEY_VOLUMEDOWN);
83
if (unlikely(q0a & XE3GC_VOLU_MASK)) {
84
dprintk("Fn-up arrow or Volume up pressed.\n");
85
omnibook_report_key(poll_input_dev, KEY_VOLUMEUP);
87
if (unlikely(q0a & XE3GC_MUTE_MASK)) {
88
dprintk("Fn+F7 - Volume mute pressed.\n");
89
omnibook_report_key(poll_input_dev, KEY_MUTE);
92
retval = queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
93
if(unlikely(!retval)) /* here non-zero on success */
94
printk(O_ERR "Key_poller failed to rearm.\n");
97
static int omnibook_key_polling_enable(void)
101
if(mutex_lock_interruptible(&poll_mutex))
104
if(key_polling_enabled)
107
retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
109
printk(O_ERR "Key_poller enabling failed.\n");
111
dprintk("Scancode emulation for volume buttons enabled.\n");
112
key_polling_enabled = 1;
116
mutex_unlock(&poll_mutex);
120
static int omnibook_key_polling_disable(void)
122
if(mutex_lock_interruptible(&poll_mutex))
125
if(!key_polling_enabled)
128
cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work);
129
dprintk("Scancode emulation for volume buttons disabled.\n");
130
key_polling_enabled = 0;
133
mutex_unlock(&poll_mutex);
138
static int omnibook_key_polling_read(char *buffer, struct omnibook_operation *io_op)
142
if(mutex_lock_interruptible(&poll_mutex))
145
len += sprintf(buffer + len, "Volume buttons polling is %s.\n",
146
(key_polling_enabled) ? "enabled" : "disabled");
147
#ifdef CONFIG_OMNIBOOK_DEBUG
148
if(key_polling_enabled)
149
len += sprintf(buffer + len, "Will poll in %i msec.\n",
150
jiffies_to_msecs(omnibook_poll_work.timer.expires - jiffies));
152
mutex_unlock(&poll_mutex);
156
static int omnibook_key_polling_write(char *buffer, struct omnibook_operation *io_op)
161
retval = omnibook_key_polling_disable();
164
retval = omnibook_key_polling_enable();
174
* Stop polling upon suspend an restore it upon resume
176
static int omnibook_key_polling_resume(struct omnibook_operation *io_op)
180
mutex_lock(&poll_mutex);
181
if(key_polling_enabled)
182
retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
183
mutex_unlock(&poll_mutex);
187
static int omnibook_key_polling_suspend(struct omnibook_operation *io_op)
189
mutex_lock(&poll_mutex);
190
if(key_polling_enabled)
191
cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work);
192
mutex_unlock(&poll_mutex);
196
static int __init omnibook_key_polling_init(struct omnibook_operation *io_op)
200
poll_input_dev = input_allocate_device();
201
if (!poll_input_dev) {
206
poll_input_dev->name = "Omnibook legacy laptop scancode generator";
207
poll_input_dev->phys = "omnibook/input0";
208
poll_input_dev->id.bustype = BUS_HOST;
210
/* this device has three keys */
211
set_bit(EV_KEY, poll_input_dev->evbit);
212
set_bit(KEY_VOLUMEDOWN, poll_input_dev->keybit);
213
set_bit(KEY_VOLUMEUP, poll_input_dev->keybit);
214
set_bit(KEY_MUTE, poll_input_dev->keybit);
216
retval = input_register_device(poll_input_dev);
218
input_free_device(poll_input_dev);
222
omnibook_wq = create_singlethread_workqueue("omnibook");
226
retval = omnibook_key_polling_enable();
232
static void __exit omnibook_key_polling_cleanup(struct omnibook_operation *io_op)
234
omnibook_key_polling_disable();
235
destroy_workqueue(omnibook_wq);
236
input_unregister_device(poll_input_dev);
239
static struct omnibook_tbl key_polling_table[] __initdata = {
240
{XE3GC, SIMPLE_BYTE(EC, XE3GC_Q0A, 0)},
244
static struct omnibook_feature __declared_feature key_polling_driver = {
245
.name = "key_polling",
246
.enabled = 0, /* dangerous */
247
.read = omnibook_key_polling_read,
248
.write = omnibook_key_polling_write,
249
.init = omnibook_key_polling_init,
250
.exit = omnibook_key_polling_cleanup,
251
.suspend = omnibook_key_polling_suspend,
252
.resume = omnibook_key_polling_resume,
254
.tbl = key_polling_table,
257
module_param_named(key_polling, key_polling_driver.enabled, int, S_IRUGO);
258
MODULE_PARM_DESC(key_polling, "Use 0 to disable, 1 to enable key polling");