Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sermouse.c
Go to the documentation of this file.
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 <[email protected]>, 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 <[email protected]>");
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 
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) |
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 module_serio_driver(sermouse_drv);