Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / drivers / input / mouse / sermouse.c
1 /*
2  *  Copyright (c) 1999-2001 Vojtech Pavlik
3  */
4
5 /*
6  *  Serial mouse driver for Linux
7  */
8
9 /*
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  *
24  * Should you need to contact me, the author, you can do so either by
25  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27  */
28
29 #include <linux/delay.h>
30 #include <linux/module.h>
31 #include <linux/slab.h>
32 #include <linux/interrupt.h>
33 #include <linux/input.h>
34 #include <linux/serio.h>
35 #include <linux/init.h>
36
37 #define DRIVER_DESC     "Serial mouse driver"
38
39 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40 MODULE_DESCRIPTION(DRIVER_DESC);
41 MODULE_LICENSE("GPL");
42
43 static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
44                                         "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
45                                         "Logitech MZ++ Mouse"};
46
47 struct sermouse {
48         struct input_dev *dev;
49         signed char buf[8];
50         unsigned char count;
51         unsigned char type;
52         unsigned long last;
53         char phys[32];
54 };
55
56 /*
57  * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
58  * applies some prediction to the data, resulting in 96 updates per
59  * second, which is as good as a PS/2 or USB mouse.
60  */
61
62 static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
63 {
64         struct input_dev *dev = sermouse->dev;
65         signed char *buf = sermouse->buf;
66
67         switch (sermouse->count) {
68
69                 case 0:
70                         if ((data & 0xf8) != 0x80)
71                                 return;
72                         input_report_key(dev, BTN_LEFT,   !(data & 4));
73                         input_report_key(dev, BTN_RIGHT,  !(data & 1));
74                         input_report_key(dev, BTN_MIDDLE, !(data & 2));
75                         break;
76
77                 case 1:
78                 case 3:
79                         input_report_rel(dev, REL_X, data / 2);
80                         input_report_rel(dev, REL_Y, -buf[1]);
81                         buf[0] = data - data / 2;
82                         break;
83
84                 case 2:
85                 case 4:
86                         input_report_rel(dev, REL_X, buf[0]);
87                         input_report_rel(dev, REL_Y, buf[1] - data);
88                         buf[1] = data / 2;
89                         break;
90         }
91
92         input_sync(dev);
93
94         if (++sermouse->count == 5)
95                 sermouse->count = 0;
96 }
97
98 /*
99  * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
100  * generates events. With prediction it gets 80 updates/sec, assuming
101  * standard 3-byte packets and 1200 bps.
102  */
103
104 static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
105 {
106         struct input_dev *dev = sermouse->dev;
107         signed char *buf = sermouse->buf;
108
109         if (data & 0x40)
110                 sermouse->count = 0;
111         else if (sermouse->count == 0)
112                 return;
113
114         switch (sermouse->count) {
115
116                 case 0:
117                         buf[1] = data;
118                         input_report_key(dev, BTN_LEFT,   (data >> 5) & 1);
119                         input_report_key(dev, BTN_RIGHT,  (data >> 4) & 1);
120                         break;
121
122                 case 1:
123                         buf[2] = data;
124                         data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
125                         input_report_rel(dev, REL_X, data / 2);
126                         input_report_rel(dev, REL_Y, buf[4]);
127                         buf[3] = data - data / 2;
128                         break;
129
130                 case 2:
131                         /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
132                         if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
133                                 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
134                         buf[0] = buf[1];
135
136                         data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
137                         input_report_rel(dev, REL_X, buf[3]);
138                         input_report_rel(dev, REL_Y, data - buf[4]);
139                         buf[4] = data / 2;
140                         break;
141
142                 case 3:
143
144                         switch (sermouse->type) {
145
146                                 case SERIO_MS:
147                                          sermouse->type = SERIO_MP;
148
149                                 case SERIO_MP:
150                                         if ((data >> 2) & 3) break;     /* M++ Wireless Extension packet. */
151                                         input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
152                                         input_report_key(dev, BTN_SIDE,   (data >> 4) & 1);
153                                         break;
154
155                                 case SERIO_MZP:
156                                 case SERIO_MZPP:
157                                         input_report_key(dev, BTN_SIDE,   (data >> 5) & 1);
158
159                                 case SERIO_MZ:
160                                         input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
161                                         input_report_rel(dev, REL_WHEEL,  (data & 8) - (data & 7));
162                                         break;
163                         }
164
165                         break;
166
167                 case 4:
168                 case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
169                         buf[1] = (data >> 2) & 0x0f;
170                         break;
171
172                 case 5:
173                 case 7: /* Ignore anything besides MZ++ */
174                         if (sermouse->type != SERIO_MZPP)
175                                 break;
176
177                         switch (buf[1]) {
178
179                                 case 1: /* Extra mouse info */
180
181                                         input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
182                                         input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
183                                         input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
184
185                                         break;
186
187                                 default: /* We don't decode anything else yet. */
188
189                                         printk(KERN_WARNING
190                                                 "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
191                                         break;
192                         }
193
194                         break;
195         }
196
197         input_sync(dev);
198
199         sermouse->count++;
200 }
201
202 /*
203  * sermouse_interrupt() handles incoming characters, either gathering them into
204  * packets or passing them to the command routine as command output.
205  */
206
207 static irqreturn_t sermouse_interrupt(struct serio *serio,
208                 unsigned char data, unsigned int flags)
209 {
210         struct sermouse *sermouse = serio_get_drvdata(serio);
211
212         if (time_after(jiffies, sermouse->last + HZ/10))
213                 sermouse->count = 0;
214
215         sermouse->last = jiffies;
216
217         if (sermouse->type > SERIO_SUN)
218                 sermouse_process_ms(sermouse, data);
219         else
220                 sermouse_process_msc(sermouse, data);
221
222         return IRQ_HANDLED;
223 }
224
225 /*
226  * sermouse_disconnect() cleans up after we don't want talk
227  * to the mouse anymore.
228  */
229
230 static void sermouse_disconnect(struct serio *serio)
231 {
232         struct sermouse *sermouse = serio_get_drvdata(serio);
233
234         serio_close(serio);
235         serio_set_drvdata(serio, NULL);
236         input_unregister_device(sermouse->dev);
237         kfree(sermouse);
238 }
239
240 /*
241  * sermouse_connect() is a callback form the serio module when
242  * an unhandled serio port is found.
243  */
244
245 static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
246 {
247         struct sermouse *sermouse;
248         struct input_dev *input_dev;
249         unsigned char c = serio->id.extra;
250         int err = -ENOMEM;
251
252         sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
253         input_dev = input_allocate_device();
254         if (!sermouse || !input_dev)
255                 goto fail1;
256
257         sermouse->dev = input_dev;
258         snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
259         sermouse->type = serio->id.proto;
260
261         input_dev->name = sermouse_protocols[sermouse->type];
262         input_dev->phys = sermouse->phys;
263         input_dev->id.bustype = BUS_RS232;
264         input_dev->id.vendor  = sermouse->type;
265         input_dev->id.product = c;
266         input_dev->id.version = 0x0100;
267         input_dev->dev.parent = &serio->dev;
268
269         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
270         input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
271                 BIT_MASK(BTN_RIGHT);
272         input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
273
274         if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
275         if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
276         if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
277         if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
278         if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
279
280         serio_set_drvdata(serio, sermouse);
281
282         err = serio_open(serio, drv);
283         if (err)
284                 goto fail2;
285
286         err = input_register_device(sermouse->dev);
287         if (err)
288                 goto fail3;
289
290         return 0;
291
292  fail3: serio_close(serio);
293  fail2: serio_set_drvdata(serio, NULL);
294  fail1: input_free_device(input_dev);
295         kfree(sermouse);
296         return err;
297 }
298
299 static struct serio_device_id sermouse_serio_ids[] = {
300         {
301                 .type   = SERIO_RS232,
302                 .proto  = SERIO_MSC,
303                 .id     = SERIO_ANY,
304                 .extra  = SERIO_ANY,
305         },
306         {
307                 .type   = SERIO_RS232,
308                 .proto  = SERIO_SUN,
309                 .id     = SERIO_ANY,
310                 .extra  = SERIO_ANY,
311         },
312         {
313                 .type   = SERIO_RS232,
314                 .proto  = SERIO_MS,
315                 .id     = SERIO_ANY,
316                 .extra  = SERIO_ANY,
317         },
318         {
319                 .type   = SERIO_RS232,
320                 .proto  = SERIO_MP,
321                 .id     = SERIO_ANY,
322                 .extra  = SERIO_ANY,
323         },
324         {
325                 .type   = SERIO_RS232,
326                 .proto  = SERIO_MZ,
327                 .id     = SERIO_ANY,
328                 .extra  = SERIO_ANY,
329         },
330         {
331                 .type   = SERIO_RS232,
332                 .proto  = SERIO_MZP,
333                 .id     = SERIO_ANY,
334                 .extra  = SERIO_ANY,
335         },
336         {
337                 .type   = SERIO_RS232,
338                 .proto  = SERIO_MZPP,
339                 .id     = SERIO_ANY,
340                 .extra  = SERIO_ANY,
341         },
342         { 0 }
343 };
344
345 MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
346
347 static struct serio_driver sermouse_drv = {
348         .driver         = {
349                 .name   = "sermouse",
350         },
351         .description    = DRIVER_DESC,
352         .id_table       = sermouse_serio_ids,
353         .interrupt      = sermouse_interrupt,
354         .connect        = sermouse_connect,
355         .disconnect     = sermouse_disconnect,
356 };
357
358 static int __init sermouse_init(void)
359 {
360         return serio_register_driver(&sermouse_drv);
361 }
362
363 static void __exit sermouse_exit(void)
364 {
365         serio_unregister_driver(&sermouse_drv);
366 }
367
368 module_init(sermouse_init);
369 module_exit(sermouse_exit);