Update DEP-5 uri
[debian/omnibook.git] / polling.c
1 /*
2  * polling.c -- scancode emulation for volume buttons
3  * 
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
7  * later version.
8  * 
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.
13  *
14  * Written by Soós Péter <sp@osb.hu>, 2002-2004
15  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
16  */
17
18 #include "omnibook.h"
19 #include "hardware.h"
20 #include <linux/workqueue.h>
21 #include <linux/jiffies.h>
22
23 /*
24  * XE3GC type key_polling polling:
25  *
26  * Polling interval for keys (100 ms)
27  */
28
29 #define OMNIBOOK_POLL   msecs_to_jiffies(100)
30
31 /*
32  * workqueue manipulations are mutex protected and thus kept in sync with key_polling_enabled
33  */
34 static struct workqueue_struct *omnibook_wq;  
35 static int key_polling_enabled;
36 static DEFINE_MUTEX(poll_mutex);
37
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);
41 #else
42 static void omnibook_key_poller(void *data);
43 DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, NULL);
44 #endif
45
46 static struct omnibook_feature key_polling_driver;
47 static struct input_dev *poll_input_dev;
48
49 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
50         static void omnibook_key_poller(struct work_struct *work)
51 #else
52         static void omnibook_key_poller(void *data)
53 #endif
54 {
55         u8 q0a;
56         int retval;
57
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);
62
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");
72 #endif
73
74         /*
75          * Volume button scancode emulaton
76          * It emulates a key press and a release without repeat as other OneTouch buttons do.
77          */
78
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);
82         }
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);
86         }
87         if (unlikely(q0a & XE3GC_MUTE_MASK)) {
88                 dprintk("Fn+F7 - Volume mute pressed.\n");
89                 omnibook_report_key(poll_input_dev, KEY_MUTE);
90         }
91
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");
95 }
96
97 static int omnibook_key_polling_enable(void)
98 {
99         int retval = 0;
100
101         if(mutex_lock_interruptible(&poll_mutex))
102                 return -ERESTARTSYS;
103
104         if(key_polling_enabled)
105                 goto out;
106
107         retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
108         if(retval)
109                 printk(O_ERR "Key_poller enabling failed.\n");
110         else {  
111                 dprintk("Scancode emulation for volume buttons enabled.\n");
112                 key_polling_enabled = 1;
113         }
114
115         out:
116         mutex_unlock(&poll_mutex);
117         return retval;
118 }
119         
120 static int omnibook_key_polling_disable(void)
121 {
122         if(mutex_lock_interruptible(&poll_mutex))
123                 return -ERESTARTSYS;
124
125         if(!key_polling_enabled)
126                 goto out;
127
128         cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work);
129         dprintk("Scancode emulation for volume buttons disabled.\n");
130         key_polling_enabled = 0;
131
132         out:
133         mutex_unlock(&poll_mutex);
134         return 0;
135 }
136
137
138 static int omnibook_key_polling_read(char *buffer, struct omnibook_operation *io_op)
139 {
140         int len = 0;
141         
142         if(mutex_lock_interruptible(&poll_mutex))
143                 return -ERESTARTSYS;
144
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));
151 #endif
152         mutex_unlock(&poll_mutex);
153         return len;
154 }
155
156 static int omnibook_key_polling_write(char *buffer, struct omnibook_operation *io_op)
157 {
158         int retval;
159         switch (*buffer) {
160         case '0':
161                 retval = omnibook_key_polling_disable();
162                 break;
163         case '1':
164                 retval = omnibook_key_polling_enable();
165                 break;
166         default:
167                 retval = -EINVAL;
168         }
169         return retval;
170 }
171
172
173 /*
174  * Stop polling upon suspend an restore it upon resume
175  */
176 static int omnibook_key_polling_resume(struct omnibook_operation *io_op)
177 {
178         int retval = 0;
179
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);
184         return retval;  
185 }
186
187 static int omnibook_key_polling_suspend(struct omnibook_operation *io_op)
188 {
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);
193         return 0;
194 }
195
196 static int __init omnibook_key_polling_init(struct omnibook_operation *io_op)
197 {
198         int retval = 0; 
199         
200         poll_input_dev = input_allocate_device();
201         if (!poll_input_dev) {
202                 retval = -ENOMEM;
203                 goto out;
204         }
205
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;
209         
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);
215
216         retval = input_register_device(poll_input_dev);
217         if (retval) {
218                 input_free_device(poll_input_dev);
219                 goto out;
220         }
221
222         omnibook_wq = create_singlethread_workqueue("omnibook");
223         if(!omnibook_wq)
224                 retval = -ENOMEM;
225         else
226                 retval = omnibook_key_polling_enable();
227
228 out:
229         return retval;
230 }
231
232 static void __exit omnibook_key_polling_cleanup(struct omnibook_operation *io_op)
233 {
234         omnibook_key_polling_disable(); 
235         destroy_workqueue(omnibook_wq);
236         input_unregister_device(poll_input_dev);
237 }
238
239 static struct omnibook_tbl key_polling_table[] __initdata = {
240         {XE3GC, SIMPLE_BYTE(EC, XE3GC_Q0A, 0)},
241         {0,}
242 };
243
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,
253         .ectypes = XE3GC,
254         .tbl = key_polling_table,
255 };
256
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");
259 /* End of file */