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