Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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
36 #define DRIVER_DESC     "Serial mouse driver"
37
38 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
39 MODULE_DESCRIPTION(DRIVER_DESC);
40 MODULE_LICENSE("GPL");
41
42 static const char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
43                                         "Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
44                                         "Logitech MZ++ Mouse"};
45
46 struct sermouse {
47         struct input_dev *dev;
48         signed char buf[8];
49         unsigned char count;
50         unsigned char type;
51         unsigned long last;
52         char phys[32];
53 };
54
55 /*
56  * sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
57  * applies some prediction to the data, resulting in 96 updates per
58  * second, which is as good as a PS/2 or USB mouse.
59  */
60
61 static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
62 {
63         struct input_dev *dev = sermouse->dev;
64         signed char *buf = sermouse->buf;
65
66         switch (sermouse->count) {
67
68                 case 0:
69                         if ((data & 0xf8) != 0x80)
70                                 return;
71                         input_report_key(dev, BTN_LEFT,   !(data & 4));
72                         input_report_key(dev, BTN_RIGHT,  !(data & 1));
73                         input_report_key(dev, BTN_MIDDLE, !(data & 2));
74                         break;
75
76                 case 1:
77                 case 3:
78                         input_report_rel(dev, REL_X, data / 2);
79                         input_report_rel(dev, REL_Y, -buf[1]);
80                         buf[0] = data - data / 2;
81                         break;
82
83                 case 2:
84                 case 4:
85                         input_report_rel(dev, REL_X, buf[0]);
86                         input_report_rel(dev, REL_Y, buf[1] - data);
87                         buf[1] = data / 2;
88                         break;
89         }
90
91         input_sync(dev);
92
93         if (++sermouse->count == 5)
94                 sermouse->count = 0;
95 }
96
97 /*
98  * sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
99  * generates events. With prediction it gets 80 updates/sec, assuming
100  * standard 3-byte packets and 1200 bps.
101  */
102
103 static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
104 {
105         struct input_dev *dev = sermouse->dev;
106         signed char *buf = sermouse->buf;
107
108         if (data & 0x40)
109                 sermouse->count = 0;
110         else if (sermouse->count == 0)
111                 return;
112
113         switch (sermouse->count) {
114
115                 case 0:
116                         buf[1] = data;
117                         input_report_key(dev, BTN_LEFT,   (data >> 5) & 1);
118                         input_report_key(dev, BTN_RIGHT,  (data >> 4) & 1);
119                         break;
120
121                 case 1:
122                         buf[2] = data;
123                         data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
124                         input_report_rel(dev, REL_X, data / 2);
125                         input_report_rel(dev, REL_Y, buf[4]);
126                         buf[3] = data - data / 2;
127                         break;
128
129                 case 2:
130                         /* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
131                         if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
132                                 input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
133                         buf[0] = buf[1];
134
135                         data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
136                         input_report_rel(dev, REL_X, buf[3]);
137                         input_report_rel(dev, REL_Y, data - buf[4]);
138                         buf[4] = data / 2;
139                         break;
140
141                 case 3:
142
143                         switch (sermouse->type) {
144
145                                 case SERIO_MS:
146                                          sermouse->type = SERIO_MP;
147
148                                 case SERIO_MP:
149                                         if ((data >> 2) & 3) break;     /* M++ Wireless Extension packet. */
150                                         input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
151                                         input_report_key(dev, BTN_SIDE,   (data >> 4) & 1);
152                                         break;
153
154                                 case SERIO_MZP:
155                                 case SERIO_MZPP:
156                                         input_report_key(dev, BTN_SIDE,   (data >> 5) & 1);
157
158                                 case SERIO_MZ:
159                                         input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
160                                         input_report_rel(dev, REL_WHEEL,  (data & 8) - (data & 7));
161                                         break;
162                         }
163
164                         break;
165
166                 case 4:
167                 case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
168                         buf[1] = (data >> 2) & 0x0f;
169                         break;
170
171                 case 5:
172                 case 7: /* Ignore anything besides MZ++ */
173                         if (sermouse->type != SERIO_MZPP)
174                                 break;
175
176                         switch (buf[1]) {
177
178                                 case 1: /* Extra mouse info */
179
180                                         input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
181                                         input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
182                                         input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
183
184                                         break;
185
186                                 default: /* We don't decode anything else yet. */
187
188                                         printk(KERN_WARNING
189                                                 "sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
190                                         break;
191                         }
192
193                         break;
194         }
195
196         input_sync(dev);
197
198         sermouse->count++;
199 }
200
201 /*
202  * sermouse_interrupt() handles incoming characters, either gathering them into
203  * packets or passing them to the command routine as command output.
204  */
205
206 static irqreturn_t sermouse_interrupt(struct serio *serio,
207                 unsigned char data, unsigned int flags)
208 {
209         struct sermouse *sermouse = serio_get_drvdata(serio);
210
211         if (time_after(jiffies, sermouse->last + HZ/10))
212                 sermouse->count = 0;
213
214         sermouse->last = jiffies;
215
216         if (sermouse->type > SERIO_SUN)
217                 sermouse_process_ms(sermouse, data);
218         else
219                 sermouse_process_msc(sermouse, data);
220
221         return IRQ_HANDLED;
222 }
223
224 /*
225  * sermouse_disconnect() cleans up after we don't want talk
226  * to the mouse anymore.
227  */
228
229 static void sermouse_disconnect(struct serio *serio)
230 {
231         struct sermouse *sermouse = serio_get_drvdata(serio);
232
233         serio_close(serio);
234         serio_set_drvdata(serio, NULL);
235         input_unregister_device(sermouse->dev);
236         kfree(sermouse);
237 }
238
239 /*
240  * sermouse_connect() is a callback form the serio module when
241  * an unhandled serio port is found.
242  */
243
244 static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
245 {
246         struct sermouse *sermouse;
247         struct input_dev *input_dev;
248         unsigned char c = serio->id.extra;
249         int err = -ENOMEM;
250
251         sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
252         input_dev = input_allocate_device();
253         if (!sermouse || !input_dev)
254                 goto fail1;
255
256         sermouse->dev = input_dev;
257         snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
258         sermouse->type = serio->id.proto;
259
260         input_dev->name = sermouse_protocols[sermouse->type];
261         input_dev->phys = sermouse->phys;
262         input_dev->id.bustype = BUS_RS232;
263         input_dev->id.vendor  = sermouse->type;
264         input_dev->id.product = c;
265         input_dev->id.version = 0x0100;
266         input_dev->dev.parent = &serio->dev;
267
268         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
269         input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
270                 BIT_MASK(BTN_RIGHT);
271         input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
272
273         if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
274         if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
275         if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
276         if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
277         if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
278
279         serio_set_drvdata(serio, sermouse);
280
281         err = serio_open(serio, drv);
282         if (err)
283                 goto fail2;
284
285         err = input_register_device(sermouse->dev);
286         if (err)
287                 goto fail3;
288
289         return 0;
290
291  fail3: serio_close(serio);
292  fail2: serio_set_drvdata(serio, NULL);
293  fail1: input_free_device(input_dev);
294         kfree(sermouse);
295         return err;
296 }
297
298 static struct serio_device_id sermouse_serio_ids[] = {
299         {
300                 .type   = SERIO_RS232,
301                 .proto  = SERIO_MSC,
302                 .id     = SERIO_ANY,
303                 .extra  = SERIO_ANY,
304         },
305         {
306                 .type   = SERIO_RS232,
307                 .proto  = SERIO_SUN,
308                 .id     = SERIO_ANY,
309                 .extra  = SERIO_ANY,
310         },
311         {
312                 .type   = SERIO_RS232,
313                 .proto  = SERIO_MS,
314                 .id     = SERIO_ANY,
315                 .extra  = SERIO_ANY,
316         },
317         {
318                 .type   = SERIO_RS232,
319                 .proto  = SERIO_MP,
320                 .id     = SERIO_ANY,
321                 .extra  = SERIO_ANY,
322         },
323         {
324                 .type   = SERIO_RS232,
325                 .proto  = SERIO_MZ,
326                 .id     = SERIO_ANY,
327                 .extra  = SERIO_ANY,
328         },
329         {
330                 .type   = SERIO_RS232,
331                 .proto  = SERIO_MZP,
332                 .id     = SERIO_ANY,
333                 .extra  = SERIO_ANY,
334         },
335         {
336                 .type   = SERIO_RS232,
337                 .proto  = SERIO_MZPP,
338                 .id     = SERIO_ANY,
339                 .extra  = SERIO_ANY,
340         },
341         { 0 }
342 };
343
344 MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
345
346 static struct serio_driver sermouse_drv = {
347         .driver         = {
348                 .name   = "sermouse",
349         },
350         .description    = DRIVER_DESC,
351         .id_table       = sermouse_serio_ids,
352         .interrupt      = sermouse_interrupt,
353         .connect        = sermouse_connect,
354         .disconnect     = sermouse_disconnect,
355 };
356
357 module_serio_driver(sermouse_drv);