diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/input/mouse/vsxxxaa.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/input/mouse/vsxxxaa.c')
-rw-r--r-- | drivers/input/mouse/vsxxxaa.c | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c new file mode 100644 index 000000000000..b2cb101c8110 --- /dev/null +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) | ||
3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) | ||
4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) | ||
5 | * | ||
6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> | ||
7 | * | ||
8 | * The packet format was initially taken from a patch to GPM which is (C) 2001 | ||
9 | * by Karsten Merker <merker@linuxtag.org> | ||
10 | * and Maciej W. Rozycki <macro@ds2.pg.gda.pl> | ||
11 | * Later on, I had access to the device's documentation (referenced below). | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Building an adaptor to DE9 / DB25 RS232 | ||
32 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
33 | * | ||
34 | * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for | ||
35 | * anything if you break your mouse, your computer or whatever! | ||
36 | * | ||
37 | * In theory, this mouse is a simple RS232 device. In practice, it has got | ||
38 | * a quite uncommon plug and the requirement to additionally get a power | ||
39 | * supply at +5V and -12V. | ||
40 | * | ||
41 | * If you look at the socket/jack (_not_ at the plug), we use this pin | ||
42 | * numbering: | ||
43 | * _______ | ||
44 | * / 7 6 5 \ | ||
45 | * | 4 --- 3 | | ||
46 | * \ 2 1 / | ||
47 | * ------- | ||
48 | * | ||
49 | * DEC socket DE9 DB25 Note | ||
50 | * 1 (GND) 5 7 - | ||
51 | * 2 (RxD) 2 3 - | ||
52 | * 3 (TxD) 3 2 - | ||
53 | * 4 (-12V) - - Somewhere from the PSU. At ATX, it's | ||
54 | * the thin blue wire at pin 12 of the | ||
55 | * ATX power connector. Only required for | ||
56 | * VSXXX-AA/-GA mice. | ||
57 | * 5 (+5V) - - PSU (red wires of ATX power connector | ||
58 | * on pin 4, 6, 19 or 20) or HDD power | ||
59 | * connector (also red wire). | ||
60 | * 6 (+12V) - - HDD power connector, yellow wire. Only | ||
61 | * required for VSXXX-AB digitizer. | ||
62 | * 7 (dev. avail.) - - The mouse shorts this one to pin 1. | ||
63 | * This way, the host computer can detect | ||
64 | * the mouse. To use it with the adaptor, | ||
65 | * simply don't connect this pin. | ||
66 | * | ||
67 | * So to get a working adaptor, you need to connect the mouse with three | ||
68 | * wires to a RS232 port and two or three additional wires for +5V, +12V and | ||
69 | * -12V to the PSU. | ||
70 | * | ||
71 | * Flow specification for the link is 4800, 8o1. | ||
72 | * | ||
73 | * The mice and tablet are described in "VCB02 Video Subsystem - Technical | ||
74 | * Manual", DEC EK-104AA-TM-001. You'll find it at MANX, a search engine | ||
75 | * specific for DEC documentation. Try | ||
76 | * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1 | ||
77 | */ | ||
78 | |||
79 | #include <linux/delay.h> | ||
80 | #include <linux/module.h> | ||
81 | #include <linux/slab.h> | ||
82 | #include <linux/interrupt.h> | ||
83 | #include <linux/input.h> | ||
84 | #include <linux/config.h> | ||
85 | #include <linux/serio.h> | ||
86 | #include <linux/init.h> | ||
87 | |||
88 | #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet" | ||
89 | |||
90 | MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); | ||
91 | MODULE_DESCRIPTION (DRIVER_DESC); | ||
92 | MODULE_LICENSE ("GPL"); | ||
93 | |||
94 | #undef VSXXXAA_DEBUG | ||
95 | #ifdef VSXXXAA_DEBUG | ||
96 | #define DBG(x...) printk (x) | ||
97 | #else | ||
98 | #define DBG(x...) do {} while (0) | ||
99 | #endif | ||
100 | |||
101 | #define VSXXXAA_INTRO_MASK 0x80 | ||
102 | #define VSXXXAA_INTRO_HEAD 0x80 | ||
103 | #define IS_HDR_BYTE(x) (((x) & VSXXXAA_INTRO_MASK) \ | ||
104 | == VSXXXAA_INTRO_HEAD) | ||
105 | |||
106 | #define VSXXXAA_PACKET_MASK 0xe0 | ||
107 | #define VSXXXAA_PACKET_REL 0x80 | ||
108 | #define VSXXXAA_PACKET_ABS 0xc0 | ||
109 | #define VSXXXAA_PACKET_POR 0xa0 | ||
110 | #define MATCH_PACKET_TYPE(data, type) (((data) & VSXXXAA_PACKET_MASK) == (type)) | ||
111 | |||
112 | |||
113 | |||
114 | struct vsxxxaa { | ||
115 | struct input_dev dev; | ||
116 | struct serio *serio; | ||
117 | #define BUFLEN 15 /* At least 5 is needed for a full tablet packet */ | ||
118 | unsigned char buf[BUFLEN]; | ||
119 | unsigned char count; | ||
120 | unsigned char version; | ||
121 | unsigned char country; | ||
122 | unsigned char type; | ||
123 | char name[64]; | ||
124 | char phys[32]; | ||
125 | }; | ||
126 | |||
127 | static void | ||
128 | vsxxxaa_drop_bytes (struct vsxxxaa *mouse, int num) | ||
129 | { | ||
130 | if (num >= mouse->count) | ||
131 | mouse->count = 0; | ||
132 | else { | ||
133 | memmove (mouse->buf, mouse->buf + num - 1, BUFLEN - num); | ||
134 | mouse->count -= num; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void | ||
139 | vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte) | ||
140 | { | ||
141 | if (mouse->count == BUFLEN) { | ||
142 | printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n", | ||
143 | mouse->name, mouse->phys); | ||
144 | vsxxxaa_drop_bytes (mouse, 1); | ||
145 | } | ||
146 | DBG (KERN_INFO "Queueing byte 0x%02x\n", byte); | ||
147 | |||
148 | mouse->buf[mouse->count++] = byte; | ||
149 | } | ||
150 | |||
151 | static void | ||
152 | vsxxxaa_detection_done (struct vsxxxaa *mouse) | ||
153 | { | ||
154 | switch (mouse->type) { | ||
155 | case 0x02: | ||
156 | sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse"); | ||
157 | break; | ||
158 | |||
159 | case 0x04: | ||
160 | sprintf (mouse->name, "DEC VSXXX-AB digitizer"); | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | sprintf (mouse->name, "unknown DEC pointer device " | ||
165 | "(type = 0x%02x)", mouse->type); | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x " | ||
170 | "on port %s\n", mouse->name, mouse->version, | ||
171 | mouse->country, mouse->phys); | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Returns number of bytes to be dropped, 0 if packet is okay. | ||
176 | */ | ||
177 | static int | ||
178 | vsxxxaa_check_packet (struct vsxxxaa *mouse, int packet_len) | ||
179 | { | ||
180 | int i; | ||
181 | |||
182 | /* First byte must be a header byte */ | ||
183 | if (!IS_HDR_BYTE (mouse->buf[0])) { | ||
184 | DBG ("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]); | ||
185 | return 1; | ||
186 | } | ||
187 | |||
188 | /* Check all following bytes */ | ||
189 | if (packet_len > 1) { | ||
190 | for (i = 1; i < packet_len; i++) { | ||
191 | if (IS_HDR_BYTE (mouse->buf[i])) { | ||
192 | printk (KERN_ERR "Need to drop %d bytes " | ||
193 | "of a broken packet.\n", | ||
194 | i - 1); | ||
195 | DBG (KERN_INFO "check: len=%d, b[%d]=0x%02x\n", | ||
196 | packet_len, i, mouse->buf[i]); | ||
197 | return i - 1; | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static __inline__ int | ||
206 | vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t len) | ||
207 | { | ||
208 | return (mouse->count >= len) && MATCH_PACKET_TYPE (mouse->buf[0], type); | ||
209 | } | ||
210 | |||
211 | static void | ||
212 | vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs) | ||
213 | { | ||
214 | struct input_dev *dev = &mouse->dev; | ||
215 | unsigned char *buf = mouse->buf; | ||
216 | int left, middle, right; | ||
217 | int dx, dy; | ||
218 | |||
219 | /* | ||
220 | * Check for normal stream packets. This is three bytes, | ||
221 | * with the first byte's 3 MSB set to 100. | ||
222 | * | ||
223 | * [0]: 1 0 0 SignX SignY Left Middle Right | ||
224 | * [1]: 0 dx dx dx dx dx dx dx | ||
225 | * [2]: 0 dy dy dy dy dy dy dy | ||
226 | */ | ||
227 | |||
228 | /* | ||
229 | * Low 7 bit of byte 1 are abs(dx), bit 7 is | ||
230 | * 0, bit 4 of byte 0 is direction. | ||
231 | */ | ||
232 | dx = buf[1] & 0x7f; | ||
233 | dx *= ((buf[0] >> 4) & 0x01)? 1: -1; | ||
234 | |||
235 | /* | ||
236 | * Low 7 bit of byte 2 are abs(dy), bit 7 is | ||
237 | * 0, bit 3 of byte 0 is direction. | ||
238 | */ | ||
239 | dy = buf[2] & 0x7f; | ||
240 | dy *= ((buf[0] >> 3) & 0x01)? -1: 1; | ||
241 | |||
242 | /* | ||
243 | * Get button state. It's the low three bits | ||
244 | * (for three buttons) of byte 0. | ||
245 | */ | ||
246 | left = (buf[0] & 0x04)? 1: 0; | ||
247 | middle = (buf[0] & 0x02)? 1: 0; | ||
248 | right = (buf[0] & 0x01)? 1: 0; | ||
249 | |||
250 | vsxxxaa_drop_bytes (mouse, 3); | ||
251 | |||
252 | DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n", | ||
253 | mouse->name, mouse->phys, dx, dy, | ||
254 | left? "L": "l", middle? "M": "m", right? "R": "r"); | ||
255 | |||
256 | /* | ||
257 | * Report what we've found so far... | ||
258 | */ | ||
259 | input_regs (dev, regs); | ||
260 | input_report_key (dev, BTN_LEFT, left); | ||
261 | input_report_key (dev, BTN_MIDDLE, middle); | ||
262 | input_report_key (dev, BTN_RIGHT, right); | ||
263 | input_report_key (dev, BTN_TOUCH, 0); | ||
264 | input_report_rel (dev, REL_X, dx); | ||
265 | input_report_rel (dev, REL_Y, dy); | ||
266 | input_sync (dev); | ||
267 | } | ||
268 | |||
269 | static void | ||
270 | vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs) | ||
271 | { | ||
272 | struct input_dev *dev = &mouse->dev; | ||
273 | unsigned char *buf = mouse->buf; | ||
274 | int left, middle, right, touch; | ||
275 | int x, y; | ||
276 | |||
277 | /* | ||
278 | * Tablet position / button packet | ||
279 | * | ||
280 | * [0]: 1 1 0 B4 B3 B2 B1 Pr | ||
281 | * [1]: 0 0 X5 X4 X3 X2 X1 X0 | ||
282 | * [2]: 0 0 X11 X10 X9 X8 X7 X6 | ||
283 | * [3]: 0 0 Y5 Y4 Y3 Y2 Y1 Y0 | ||
284 | * [4]: 0 0 Y11 Y10 Y9 Y8 Y7 Y6 | ||
285 | */ | ||
286 | |||
287 | /* | ||
288 | * Get X/Y position. Y axis needs to be inverted since VSXXX-AB | ||
289 | * counts down->top while monitor counts top->bottom. | ||
290 | */ | ||
291 | x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f); | ||
292 | y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f); | ||
293 | y = 1023 - y; | ||
294 | |||
295 | /* | ||
296 | * Get button state. It's bits <4..1> of byte 0. | ||
297 | */ | ||
298 | left = (buf[0] & 0x02)? 1: 0; | ||
299 | middle = (buf[0] & 0x04)? 1: 0; | ||
300 | right = (buf[0] & 0x08)? 1: 0; | ||
301 | touch = (buf[0] & 0x10)? 1: 0; | ||
302 | |||
303 | vsxxxaa_drop_bytes (mouse, 5); | ||
304 | |||
305 | DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n", | ||
306 | mouse->name, mouse->phys, x, y, | ||
307 | left? "L": "l", middle? "M": "m", | ||
308 | right? "R": "r", touch? "T": "t"); | ||
309 | |||
310 | /* | ||
311 | * Report what we've found so far... | ||
312 | */ | ||
313 | input_regs (dev, regs); | ||
314 | input_report_key (dev, BTN_LEFT, left); | ||
315 | input_report_key (dev, BTN_MIDDLE, middle); | ||
316 | input_report_key (dev, BTN_RIGHT, right); | ||
317 | input_report_key (dev, BTN_TOUCH, touch); | ||
318 | input_report_abs (dev, ABS_X, x); | ||
319 | input_report_abs (dev, ABS_Y, y); | ||
320 | input_sync (dev); | ||
321 | } | ||
322 | |||
323 | static void | ||
324 | vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs) | ||
325 | { | ||
326 | struct input_dev *dev = &mouse->dev; | ||
327 | unsigned char *buf = mouse->buf; | ||
328 | int left, middle, right; | ||
329 | unsigned char error; | ||
330 | |||
331 | /* | ||
332 | * Check for Power-On-Reset packets. These are sent out | ||
333 | * after plugging the mouse in, or when explicitely | ||
334 | * requested by sending 'T'. | ||
335 | * | ||
336 | * [0]: 1 0 1 0 R3 R2 R1 R0 | ||
337 | * [1]: 0 M2 M1 M0 D3 D2 D1 D0 | ||
338 | * [2]: 0 E6 E5 E4 E3 E2 E1 E0 | ||
339 | * [3]: 0 0 0 0 0 Left Middle Right | ||
340 | * | ||
341 | * M: manufacturer location code | ||
342 | * R: revision code | ||
343 | * E: Error code. If it's in the range of 0x00..0x1f, only some | ||
344 | * minor problem occured. Errors >= 0x20 are considered bad | ||
345 | * and the device may not work properly... | ||
346 | * D: <0010> == mouse, <0100> == tablet | ||
347 | */ | ||
348 | |||
349 | mouse->version = buf[0] & 0x0f; | ||
350 | mouse->country = (buf[1] >> 4) & 0x07; | ||
351 | mouse->type = buf[1] & 0x0f; | ||
352 | error = buf[2] & 0x7f; | ||
353 | |||
354 | /* | ||
355 | * Get button state. It's the low three bits | ||
356 | * (for three buttons) of byte 0. Maybe even the bit <3> | ||
357 | * has some meaning if a tablet is attached. | ||
358 | */ | ||
359 | left = (buf[0] & 0x04)? 1: 0; | ||
360 | middle = (buf[0] & 0x02)? 1: 0; | ||
361 | right = (buf[0] & 0x01)? 1: 0; | ||
362 | |||
363 | vsxxxaa_drop_bytes (mouse, 4); | ||
364 | vsxxxaa_detection_done (mouse); | ||
365 | |||
366 | if (error <= 0x1f) { | ||
367 | /* No (serious) error. Report buttons */ | ||
368 | input_regs (dev, regs); | ||
369 | input_report_key (dev, BTN_LEFT, left); | ||
370 | input_report_key (dev, BTN_MIDDLE, middle); | ||
371 | input_report_key (dev, BTN_RIGHT, right); | ||
372 | input_report_key (dev, BTN_TOUCH, 0); | ||
373 | input_sync (dev); | ||
374 | |||
375 | if (error != 0) | ||
376 | printk (KERN_INFO "Your %s on %s reports error=0x%02x\n", | ||
377 | mouse->name, mouse->phys, error); | ||
378 | |||
379 | } | ||
380 | |||
381 | /* | ||
382 | * If the mouse was hot-plugged, we need to force differential mode | ||
383 | * now... However, give it a second to recover from it's reset. | ||
384 | */ | ||
385 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | ||
386 | "incremental streaming mode and 72 samples/sec\n", | ||
387 | mouse->name, mouse->phys); | ||
388 | mouse->serio->write (mouse->serio, 'S'); /* Standard format */ | ||
389 | mdelay (50); | ||
390 | mouse->serio->write (mouse->serio, 'R'); /* Incremental */ | ||
391 | mdelay (50); | ||
392 | mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */ | ||
393 | } | ||
394 | |||
395 | static void | ||
396 | vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs) | ||
397 | { | ||
398 | unsigned char *buf = mouse->buf; | ||
399 | int stray_bytes; | ||
400 | |||
401 | /* | ||
402 | * Parse buffer to death... | ||
403 | */ | ||
404 | do { | ||
405 | /* | ||
406 | * Out of sync? Throw away what we don't understand. Each | ||
407 | * packet starts with a byte whose bit 7 is set. Unhandled | ||
408 | * packets (ie. which we don't know about or simply b0rk3d | ||
409 | * data...) will get shifted out of the buffer after some | ||
410 | * activity on the mouse. | ||
411 | */ | ||
412 | while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) { | ||
413 | printk (KERN_ERR "%s on %s: Dropping a byte to regain " | ||
414 | "sync with mouse data stream...\n", | ||
415 | mouse->name, mouse->phys); | ||
416 | vsxxxaa_drop_bytes (mouse, 1); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Check for packets we know about. | ||
421 | */ | ||
422 | |||
423 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_REL, 3)) { | ||
424 | /* Check for broken packet */ | ||
425 | stray_bytes = vsxxxaa_check_packet (mouse, 3); | ||
426 | if (stray_bytes > 0) { | ||
427 | printk (KERN_ERR "Dropping %d bytes now...\n", | ||
428 | stray_bytes); | ||
429 | vsxxxaa_drop_bytes (mouse, stray_bytes); | ||
430 | continue; | ||
431 | } | ||
432 | |||
433 | vsxxxaa_handle_REL_packet (mouse, regs); | ||
434 | continue; /* More to parse? */ | ||
435 | } | ||
436 | |||
437 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_ABS, 5)) { | ||
438 | /* Check for broken packet */ | ||
439 | stray_bytes = vsxxxaa_check_packet (mouse, 5); | ||
440 | if (stray_bytes > 0) { | ||
441 | printk (KERN_ERR "Dropping %d bytes now...\n", | ||
442 | stray_bytes); | ||
443 | vsxxxaa_drop_bytes (mouse, stray_bytes); | ||
444 | continue; | ||
445 | } | ||
446 | |||
447 | vsxxxaa_handle_ABS_packet (mouse, regs); | ||
448 | continue; /* More to parse? */ | ||
449 | } | ||
450 | |||
451 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_POR, 4)) { | ||
452 | /* Check for broken packet */ | ||
453 | stray_bytes = vsxxxaa_check_packet (mouse, 4); | ||
454 | if (stray_bytes > 0) { | ||
455 | printk (KERN_ERR "Dropping %d bytes now...\n", | ||
456 | stray_bytes); | ||
457 | vsxxxaa_drop_bytes (mouse, stray_bytes); | ||
458 | continue; | ||
459 | } | ||
460 | |||
461 | vsxxxaa_handle_POR_packet (mouse, regs); | ||
462 | continue; /* More to parse? */ | ||
463 | } | ||
464 | |||
465 | break; /* No REL, ABS or POR packet found */ | ||
466 | } while (1); | ||
467 | } | ||
468 | |||
469 | static irqreturn_t | ||
470 | vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags, | ||
471 | struct pt_regs *regs) | ||
472 | { | ||
473 | struct vsxxxaa *mouse = serio_get_drvdata (serio); | ||
474 | |||
475 | vsxxxaa_queue_byte (mouse, data); | ||
476 | vsxxxaa_parse_buffer (mouse, regs); | ||
477 | |||
478 | return IRQ_HANDLED; | ||
479 | } | ||
480 | |||
481 | static void | ||
482 | vsxxxaa_disconnect (struct serio *serio) | ||
483 | { | ||
484 | struct vsxxxaa *mouse = serio_get_drvdata (serio); | ||
485 | |||
486 | input_unregister_device (&mouse->dev); | ||
487 | serio_close (serio); | ||
488 | serio_set_drvdata (serio, NULL); | ||
489 | kfree (mouse); | ||
490 | } | ||
491 | |||
492 | static int | ||
493 | vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | ||
494 | { | ||
495 | struct vsxxxaa *mouse; | ||
496 | int err; | ||
497 | |||
498 | if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL))) | ||
499 | return -ENOMEM; | ||
500 | |||
501 | memset (mouse, 0, sizeof (struct vsxxxaa)); | ||
502 | |||
503 | init_input_dev (&mouse->dev); | ||
504 | set_bit (EV_KEY, mouse->dev.evbit); /* We have buttons */ | ||
505 | set_bit (EV_REL, mouse->dev.evbit); | ||
506 | set_bit (EV_ABS, mouse->dev.evbit); | ||
507 | set_bit (BTN_LEFT, mouse->dev.keybit); /* We have 3 buttons */ | ||
508 | set_bit (BTN_MIDDLE, mouse->dev.keybit); | ||
509 | set_bit (BTN_RIGHT, mouse->dev.keybit); | ||
510 | set_bit (BTN_TOUCH, mouse->dev.keybit); /* ...and Tablet */ | ||
511 | set_bit (REL_X, mouse->dev.relbit); | ||
512 | set_bit (REL_Y, mouse->dev.relbit); | ||
513 | set_bit (ABS_X, mouse->dev.absbit); | ||
514 | set_bit (ABS_Y, mouse->dev.absbit); | ||
515 | |||
516 | mouse->dev.absmin[ABS_X] = 0; | ||
517 | mouse->dev.absmax[ABS_X] = 1023; | ||
518 | mouse->dev.absmin[ABS_Y] = 0; | ||
519 | mouse->dev.absmax[ABS_Y] = 1023; | ||
520 | |||
521 | mouse->dev.private = mouse; | ||
522 | |||
523 | sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer"); | ||
524 | sprintf (mouse->phys, "%s/input0", serio->phys); | ||
525 | mouse->dev.name = mouse->name; | ||
526 | mouse->dev.phys = mouse->phys; | ||
527 | mouse->dev.id.bustype = BUS_RS232; | ||
528 | mouse->dev.dev = &serio->dev; | ||
529 | mouse->serio = serio; | ||
530 | |||
531 | serio_set_drvdata (serio, mouse); | ||
532 | |||
533 | err = serio_open (serio, drv); | ||
534 | if (err) { | ||
535 | serio_set_drvdata (serio, NULL); | ||
536 | kfree (mouse); | ||
537 | return err; | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * Request selftest. Standard packet format and differential | ||
542 | * mode will be requested after the device ID'ed successfully. | ||
543 | */ | ||
544 | mouse->serio->write (mouse->serio, 'T'); /* Test */ | ||
545 | |||
546 | input_register_device (&mouse->dev); | ||
547 | |||
548 | printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys); | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static struct serio_device_id vsxxaa_serio_ids[] = { | ||
554 | { | ||
555 | .type = SERIO_RS232, | ||
556 | .proto = SERIO_VSXXXAA, | ||
557 | .id = SERIO_ANY, | ||
558 | .extra = SERIO_ANY, | ||
559 | }, | ||
560 | { 0 } | ||
561 | }; | ||
562 | |||
563 | MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids); | ||
564 | |||
565 | static struct serio_driver vsxxxaa_drv = { | ||
566 | .driver = { | ||
567 | .name = "vsxxxaa", | ||
568 | }, | ||
569 | .description = DRIVER_DESC, | ||
570 | .id_table = vsxxaa_serio_ids, | ||
571 | .connect = vsxxxaa_connect, | ||
572 | .interrupt = vsxxxaa_interrupt, | ||
573 | .disconnect = vsxxxaa_disconnect, | ||
574 | }; | ||
575 | |||
576 | static int __init | ||
577 | vsxxxaa_init (void) | ||
578 | { | ||
579 | serio_register_driver(&vsxxxaa_drv); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static void __exit | ||
584 | vsxxxaa_exit (void) | ||
585 | { | ||
586 | serio_unregister_driver(&vsxxxaa_drv); | ||
587 | } | ||
588 | |||
589 | module_init (vsxxxaa_init); | ||
590 | module_exit (vsxxxaa_exit); | ||
591 | |||