Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/mouse/vsxxxaa.c
15112 views
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 <[email protected]>
7
*
8
* The packet format was initially taken from a patch to GPM which is (C) 2001
9
* by Karsten Merker <[email protected]>
10
* and Maciej W. Rozycki <[email protected]>
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/serio.h>
85
#include <linux/init.h>
86
87
#define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
88
89
MODULE_AUTHOR("Jan-Benedict Glaw <[email protected]>");
90
MODULE_DESCRIPTION(DRIVER_DESC);
91
MODULE_LICENSE("GPL");
92
93
#undef VSXXXAA_DEBUG
94
#ifdef VSXXXAA_DEBUG
95
#define DBG(x...) printk(x)
96
#else
97
#define DBG(x...) do {} while (0)
98
#endif
99
100
#define VSXXXAA_INTRO_MASK 0x80
101
#define VSXXXAA_INTRO_HEAD 0x80
102
#define IS_HDR_BYTE(x) \
103
(((x) & VSXXXAA_INTRO_MASK) == VSXXXAA_INTRO_HEAD)
104
105
#define VSXXXAA_PACKET_MASK 0xe0
106
#define VSXXXAA_PACKET_REL 0x80
107
#define VSXXXAA_PACKET_ABS 0xc0
108
#define VSXXXAA_PACKET_POR 0xa0
109
#define MATCH_PACKET_TYPE(data, type) \
110
(((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 vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num)
128
{
129
if (num >= mouse->count) {
130
mouse->count = 0;
131
} else {
132
memmove(mouse->buf, mouse->buf + num - 1, BUFLEN - num);
133
mouse->count -= num;
134
}
135
}
136
137
static void vsxxxaa_queue_byte(struct vsxxxaa *mouse, unsigned char byte)
138
{
139
if (mouse->count == BUFLEN) {
140
printk(KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
141
mouse->name, mouse->phys);
142
vsxxxaa_drop_bytes(mouse, 1);
143
}
144
145
DBG(KERN_INFO "Queueing byte 0x%02x\n", byte);
146
147
mouse->buf[mouse->count++] = byte;
148
}
149
150
static void vsxxxaa_detection_done(struct vsxxxaa *mouse)
151
{
152
switch (mouse->type) {
153
case 0x02:
154
strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse",
155
sizeof(mouse->name));
156
break;
157
158
case 0x04:
159
strlcpy(mouse->name, "DEC VSXXX-AB digitizer",
160
sizeof(mouse->name));
161
break;
162
163
default:
164
snprintf(mouse->name, sizeof(mouse->name),
165
"unknown DEC pointer device (type = 0x%02x)",
166
mouse->type);
167
break;
168
}
169
170
printk(KERN_INFO
171
"Found %s version 0x%02x from country 0x%02x on port %s\n",
172
mouse->name, mouse->version, mouse->country, mouse->phys);
173
}
174
175
/*
176
* Returns number of bytes to be dropped, 0 if packet is okay.
177
*/
178
static int 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
for (i = 1; i < packet_len; i++) {
190
if (IS_HDR_BYTE(mouse->buf[i])) {
191
printk(KERN_ERR
192
"Need to drop %d bytes of a broken packet.\n",
193
i - 1);
194
DBG(KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
195
packet_len, i, mouse->buf[i]);
196
return i - 1;
197
}
198
}
199
200
return 0;
201
}
202
203
static inline int vsxxxaa_smells_like_packet(struct vsxxxaa *mouse,
204
unsigned char type, size_t len)
205
{
206
return mouse->count >= len && MATCH_PACKET_TYPE(mouse->buf[0], type);
207
}
208
209
static void vsxxxaa_handle_REL_packet(struct vsxxxaa *mouse)
210
{
211
struct input_dev *dev = mouse->dev;
212
unsigned char *buf = mouse->buf;
213
int left, middle, right;
214
int dx, dy;
215
216
/*
217
* Check for normal stream packets. This is three bytes,
218
* with the first byte's 3 MSB set to 100.
219
*
220
* [0]: 1 0 0 SignX SignY Left Middle Right
221
* [1]: 0 dx dx dx dx dx dx dx
222
* [2]: 0 dy dy dy dy dy dy dy
223
*/
224
225
/*
226
* Low 7 bit of byte 1 are abs(dx), bit 7 is
227
* 0, bit 4 of byte 0 is direction.
228
*/
229
dx = buf[1] & 0x7f;
230
dx *= ((buf[0] >> 4) & 0x01) ? 1 : -1;
231
232
/*
233
* Low 7 bit of byte 2 are abs(dy), bit 7 is
234
* 0, bit 3 of byte 0 is direction.
235
*/
236
dy = buf[2] & 0x7f;
237
dy *= ((buf[0] >> 3) & 0x01) ? -1 : 1;
238
239
/*
240
* Get button state. It's the low three bits
241
* (for three buttons) of byte 0.
242
*/
243
left = buf[0] & 0x04;
244
middle = buf[0] & 0x02;
245
right = buf[0] & 0x01;
246
247
vsxxxaa_drop_bytes(mouse, 3);
248
249
DBG(KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
250
mouse->name, mouse->phys, dx, dy,
251
left ? "L" : "l", middle ? "M" : "m", right ? "R" : "r");
252
253
/*
254
* Report what we've found so far...
255
*/
256
input_report_key(dev, BTN_LEFT, left);
257
input_report_key(dev, BTN_MIDDLE, middle);
258
input_report_key(dev, BTN_RIGHT, right);
259
input_report_key(dev, BTN_TOUCH, 0);
260
input_report_rel(dev, REL_X, dx);
261
input_report_rel(dev, REL_Y, dy);
262
input_sync(dev);
263
}
264
265
static void vsxxxaa_handle_ABS_packet(struct vsxxxaa *mouse)
266
{
267
struct input_dev *dev = mouse->dev;
268
unsigned char *buf = mouse->buf;
269
int left, middle, right, touch;
270
int x, y;
271
272
/*
273
* Tablet position / button packet
274
*
275
* [0]: 1 1 0 B4 B3 B2 B1 Pr
276
* [1]: 0 0 X5 X4 X3 X2 X1 X0
277
* [2]: 0 0 X11 X10 X9 X8 X7 X6
278
* [3]: 0 0 Y5 Y4 Y3 Y2 Y1 Y0
279
* [4]: 0 0 Y11 Y10 Y9 Y8 Y7 Y6
280
*/
281
282
/*
283
* Get X/Y position. Y axis needs to be inverted since VSXXX-AB
284
* counts down->top while monitor counts top->bottom.
285
*/
286
x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
287
y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
288
y = 1023 - y;
289
290
/*
291
* Get button state. It's bits <4..1> of byte 0.
292
*/
293
left = buf[0] & 0x02;
294
middle = buf[0] & 0x04;
295
right = buf[0] & 0x08;
296
touch = buf[0] & 0x10;
297
298
vsxxxaa_drop_bytes(mouse, 5);
299
300
DBG(KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
301
mouse->name, mouse->phys, x, y,
302
left ? "L" : "l", middle ? "M" : "m",
303
right ? "R" : "r", touch ? "T" : "t");
304
305
/*
306
* Report what we've found so far...
307
*/
308
input_report_key(dev, BTN_LEFT, left);
309
input_report_key(dev, BTN_MIDDLE, middle);
310
input_report_key(dev, BTN_RIGHT, right);
311
input_report_key(dev, BTN_TOUCH, touch);
312
input_report_abs(dev, ABS_X, x);
313
input_report_abs(dev, ABS_Y, y);
314
input_sync(dev);
315
}
316
317
static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse)
318
{
319
struct input_dev *dev = mouse->dev;
320
unsigned char *buf = mouse->buf;
321
int left, middle, right;
322
unsigned char error;
323
324
/*
325
* Check for Power-On-Reset packets. These are sent out
326
* after plugging the mouse in, or when explicitly
327
* requested by sending 'T'.
328
*
329
* [0]: 1 0 1 0 R3 R2 R1 R0
330
* [1]: 0 M2 M1 M0 D3 D2 D1 D0
331
* [2]: 0 E6 E5 E4 E3 E2 E1 E0
332
* [3]: 0 0 0 0 0 Left Middle Right
333
*
334
* M: manufacturer location code
335
* R: revision code
336
* E: Error code. If it's in the range of 0x00..0x1f, only some
337
* minor problem occurred. Errors >= 0x20 are considered bad
338
* and the device may not work properly...
339
* D: <0010> == mouse, <0100> == tablet
340
*/
341
342
mouse->version = buf[0] & 0x0f;
343
mouse->country = (buf[1] >> 4) & 0x07;
344
mouse->type = buf[1] & 0x0f;
345
error = buf[2] & 0x7f;
346
347
/*
348
* Get button state. It's the low three bits
349
* (for three buttons) of byte 0. Maybe even the bit <3>
350
* has some meaning if a tablet is attached.
351
*/
352
left = buf[0] & 0x04;
353
middle = buf[0] & 0x02;
354
right = buf[0] & 0x01;
355
356
vsxxxaa_drop_bytes(mouse, 4);
357
vsxxxaa_detection_done(mouse);
358
359
if (error <= 0x1f) {
360
/* No (serious) error. Report buttons */
361
input_report_key(dev, BTN_LEFT, left);
362
input_report_key(dev, BTN_MIDDLE, middle);
363
input_report_key(dev, BTN_RIGHT, right);
364
input_report_key(dev, BTN_TOUCH, 0);
365
input_sync(dev);
366
367
if (error != 0)
368
printk(KERN_INFO "Your %s on %s reports error=0x%02x\n",
369
mouse->name, mouse->phys, error);
370
371
}
372
373
/*
374
* If the mouse was hot-plugged, we need to force differential mode
375
* now... However, give it a second to recover from it's reset.
376
*/
377
printk(KERN_NOTICE
378
"%s on %s: Forcing standard packet format, "
379
"incremental streaming mode and 72 samples/sec\n",
380
mouse->name, mouse->phys);
381
serio_write(mouse->serio, 'S'); /* Standard format */
382
mdelay(50);
383
serio_write(mouse->serio, 'R'); /* Incremental */
384
mdelay(50);
385
serio_write(mouse->serio, 'L'); /* 72 samples/sec */
386
}
387
388
static void vsxxxaa_parse_buffer(struct vsxxxaa *mouse)
389
{
390
unsigned char *buf = mouse->buf;
391
int stray_bytes;
392
393
/*
394
* Parse buffer to death...
395
*/
396
do {
397
/*
398
* Out of sync? Throw away what we don't understand. Each
399
* packet starts with a byte whose bit 7 is set. Unhandled
400
* packets (ie. which we don't know about or simply b0rk3d
401
* data...) will get shifted out of the buffer after some
402
* activity on the mouse.
403
*/
404
while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
405
printk(KERN_ERR "%s on %s: Dropping a byte to regain "
406
"sync with mouse data stream...\n",
407
mouse->name, mouse->phys);
408
vsxxxaa_drop_bytes(mouse, 1);
409
}
410
411
/*
412
* Check for packets we know about.
413
*/
414
415
if (vsxxxaa_smells_like_packet(mouse, VSXXXAA_PACKET_REL, 3)) {
416
/* Check for broken packet */
417
stray_bytes = vsxxxaa_check_packet(mouse, 3);
418
if (!stray_bytes)
419
vsxxxaa_handle_REL_packet(mouse);
420
421
} else if (vsxxxaa_smells_like_packet(mouse,
422
VSXXXAA_PACKET_ABS, 5)) {
423
/* Check for broken packet */
424
stray_bytes = vsxxxaa_check_packet(mouse, 5);
425
if (!stray_bytes)
426
vsxxxaa_handle_ABS_packet(mouse);
427
428
} else if (vsxxxaa_smells_like_packet(mouse,
429
VSXXXAA_PACKET_POR, 4)) {
430
/* Check for broken packet */
431
stray_bytes = vsxxxaa_check_packet(mouse, 4);
432
if (!stray_bytes)
433
vsxxxaa_handle_POR_packet(mouse);
434
435
} else {
436
break; /* No REL, ABS or POR packet found */
437
}
438
439
if (stray_bytes > 0) {
440
printk(KERN_ERR "Dropping %d bytes now...\n",
441
stray_bytes);
442
vsxxxaa_drop_bytes(mouse, stray_bytes);
443
}
444
445
} while (1);
446
}
447
448
static irqreturn_t vsxxxaa_interrupt(struct serio *serio,
449
unsigned char data, unsigned int flags)
450
{
451
struct vsxxxaa *mouse = serio_get_drvdata(serio);
452
453
vsxxxaa_queue_byte(mouse, data);
454
vsxxxaa_parse_buffer(mouse);
455
456
return IRQ_HANDLED;
457
}
458
459
static void vsxxxaa_disconnect(struct serio *serio)
460
{
461
struct vsxxxaa *mouse = serio_get_drvdata(serio);
462
463
serio_close(serio);
464
serio_set_drvdata(serio, NULL);
465
input_unregister_device(mouse->dev);
466
kfree(mouse);
467
}
468
469
static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv)
470
{
471
struct vsxxxaa *mouse;
472
struct input_dev *input_dev;
473
int err = -ENOMEM;
474
475
mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL);
476
input_dev = input_allocate_device();
477
if (!mouse || !input_dev)
478
goto fail1;
479
480
mouse->dev = input_dev;
481
mouse->serio = serio;
482
strlcat(mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
483
sizeof(mouse->name));
484
snprintf(mouse->phys, sizeof(mouse->phys), "%s/input0", serio->phys);
485
486
input_dev->name = mouse->name;
487
input_dev->phys = mouse->phys;
488
input_dev->id.bustype = BUS_RS232;
489
input_dev->dev.parent = &serio->dev;
490
491
__set_bit(EV_KEY, input_dev->evbit); /* We have buttons */
492
__set_bit(EV_REL, input_dev->evbit);
493
__set_bit(EV_ABS, input_dev->evbit);
494
__set_bit(BTN_LEFT, input_dev->keybit); /* We have 3 buttons */
495
__set_bit(BTN_MIDDLE, input_dev->keybit);
496
__set_bit(BTN_RIGHT, input_dev->keybit);
497
__set_bit(BTN_TOUCH, input_dev->keybit); /* ...and Tablet */
498
__set_bit(REL_X, input_dev->relbit);
499
__set_bit(REL_Y, input_dev->relbit);
500
input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
501
input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
502
503
serio_set_drvdata(serio, mouse);
504
505
err = serio_open(serio, drv);
506
if (err)
507
goto fail2;
508
509
/*
510
* Request selftest. Standard packet format and differential
511
* mode will be requested after the device ID'ed successfully.
512
*/
513
serio_write(serio, 'T'); /* Test */
514
515
err = input_register_device(input_dev);
516
if (err)
517
goto fail3;
518
519
return 0;
520
521
fail3: serio_close(serio);
522
fail2: serio_set_drvdata(serio, NULL);
523
fail1: input_free_device(input_dev);
524
kfree(mouse);
525
return err;
526
}
527
528
static struct serio_device_id vsxxaa_serio_ids[] = {
529
{
530
.type = SERIO_RS232,
531
.proto = SERIO_VSXXXAA,
532
.id = SERIO_ANY,
533
.extra = SERIO_ANY,
534
},
535
{ 0 }
536
};
537
538
MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
539
540
static struct serio_driver vsxxxaa_drv = {
541
.driver = {
542
.name = "vsxxxaa",
543
},
544
.description = DRIVER_DESC,
545
.id_table = vsxxaa_serio_ids,
546
.connect = vsxxxaa_connect,
547
.interrupt = vsxxxaa_interrupt,
548
.disconnect = vsxxxaa_disconnect,
549
};
550
551
static int __init vsxxxaa_init(void)
552
{
553
return serio_register_driver(&vsxxxaa_drv);
554
}
555
556
static void __exit vsxxxaa_exit(void)
557
{
558
serio_unregister_driver(&vsxxxaa_drv);
559
}
560
561
module_init(vsxxxaa_init);
562
module_exit(vsxxxaa_exit);
563
564
565