0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 #include <linux/delay.h>
0068 #include <linux/module.h>
0069 #include <linux/slab.h>
0070 #include <linux/interrupt.h>
0071 #include <linux/input.h>
0072 #include <linux/serio.h>
0073
0074 #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet"
0075
0076 MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
0077 MODULE_DESCRIPTION(DRIVER_DESC);
0078 MODULE_LICENSE("GPL");
0079
0080 #undef VSXXXAA_DEBUG
0081 #ifdef VSXXXAA_DEBUG
0082 #define DBG(x...) printk(x)
0083 #else
0084 #define DBG(x...) do {} while (0)
0085 #endif
0086
0087 #define VSXXXAA_INTRO_MASK 0x80
0088 #define VSXXXAA_INTRO_HEAD 0x80
0089 #define IS_HDR_BYTE(x) \
0090 (((x) & VSXXXAA_INTRO_MASK) == VSXXXAA_INTRO_HEAD)
0091
0092 #define VSXXXAA_PACKET_MASK 0xe0
0093 #define VSXXXAA_PACKET_REL 0x80
0094 #define VSXXXAA_PACKET_ABS 0xc0
0095 #define VSXXXAA_PACKET_POR 0xa0
0096 #define MATCH_PACKET_TYPE(data, type) \
0097 (((data) & VSXXXAA_PACKET_MASK) == (type))
0098
0099
0100
0101 struct vsxxxaa {
0102 struct input_dev *dev;
0103 struct serio *serio;
0104 #define BUFLEN 15
0105 unsigned char buf[BUFLEN];
0106 unsigned char count;
0107 unsigned char version;
0108 unsigned char country;
0109 unsigned char type;
0110 char name[64];
0111 char phys[32];
0112 };
0113
0114 static void vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num)
0115 {
0116 if (num >= mouse->count) {
0117 mouse->count = 0;
0118 } else {
0119 memmove(mouse->buf, mouse->buf + num, BUFLEN - num);
0120 mouse->count -= num;
0121 }
0122 }
0123
0124 static void vsxxxaa_queue_byte(struct vsxxxaa *mouse, unsigned char byte)
0125 {
0126 if (mouse->count == BUFLEN) {
0127 printk(KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
0128 mouse->name, mouse->phys);
0129 vsxxxaa_drop_bytes(mouse, 1);
0130 }
0131
0132 DBG(KERN_INFO "Queueing byte 0x%02x\n", byte);
0133
0134 mouse->buf[mouse->count++] = byte;
0135 }
0136
0137 static void vsxxxaa_detection_done(struct vsxxxaa *mouse)
0138 {
0139 switch (mouse->type) {
0140 case 0x02:
0141 strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse",
0142 sizeof(mouse->name));
0143 break;
0144
0145 case 0x04:
0146 strlcpy(mouse->name, "DEC VSXXX-AB digitizer",
0147 sizeof(mouse->name));
0148 break;
0149
0150 default:
0151 snprintf(mouse->name, sizeof(mouse->name),
0152 "unknown DEC pointer device (type = 0x%02x)",
0153 mouse->type);
0154 break;
0155 }
0156
0157 printk(KERN_INFO
0158 "Found %s version 0x%02x from country 0x%02x on port %s\n",
0159 mouse->name, mouse->version, mouse->country, mouse->phys);
0160 }
0161
0162
0163
0164
0165 static int vsxxxaa_check_packet(struct vsxxxaa *mouse, int packet_len)
0166 {
0167 int i;
0168
0169
0170 if (!IS_HDR_BYTE(mouse->buf[0])) {
0171 DBG("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]);
0172 return 1;
0173 }
0174
0175
0176 for (i = 1; i < packet_len; i++) {
0177 if (IS_HDR_BYTE(mouse->buf[i])) {
0178 printk(KERN_ERR
0179 "Need to drop %d bytes of a broken packet.\n",
0180 i - 1);
0181 DBG(KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
0182 packet_len, i, mouse->buf[i]);
0183 return i - 1;
0184 }
0185 }
0186
0187 return 0;
0188 }
0189
0190 static inline int vsxxxaa_smells_like_packet(struct vsxxxaa *mouse,
0191 unsigned char type, size_t len)
0192 {
0193 return mouse->count >= len && MATCH_PACKET_TYPE(mouse->buf[0], type);
0194 }
0195
0196 static void vsxxxaa_handle_REL_packet(struct vsxxxaa *mouse)
0197 {
0198 struct input_dev *dev = mouse->dev;
0199 unsigned char *buf = mouse->buf;
0200 int left, middle, right;
0201 int dx, dy;
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 dx = buf[1] & 0x7f;
0217 dx *= ((buf[0] >> 4) & 0x01) ? 1 : -1;
0218
0219
0220
0221
0222
0223 dy = buf[2] & 0x7f;
0224 dy *= ((buf[0] >> 3) & 0x01) ? -1 : 1;
0225
0226
0227
0228
0229
0230 left = buf[0] & 0x04;
0231 middle = buf[0] & 0x02;
0232 right = buf[0] & 0x01;
0233
0234 vsxxxaa_drop_bytes(mouse, 3);
0235
0236 DBG(KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
0237 mouse->name, mouse->phys, dx, dy,
0238 left ? "L" : "l", middle ? "M" : "m", right ? "R" : "r");
0239
0240
0241
0242
0243 input_report_key(dev, BTN_LEFT, left);
0244 input_report_key(dev, BTN_MIDDLE, middle);
0245 input_report_key(dev, BTN_RIGHT, right);
0246 input_report_key(dev, BTN_TOUCH, 0);
0247 input_report_rel(dev, REL_X, dx);
0248 input_report_rel(dev, REL_Y, dy);
0249 input_sync(dev);
0250 }
0251
0252 static void vsxxxaa_handle_ABS_packet(struct vsxxxaa *mouse)
0253 {
0254 struct input_dev *dev = mouse->dev;
0255 unsigned char *buf = mouse->buf;
0256 int left, middle, right, touch;
0257 int x, y;
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
0274 y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
0275 y = 1023 - y;
0276
0277
0278
0279
0280 left = buf[0] & 0x02;
0281 middle = buf[0] & 0x04;
0282 right = buf[0] & 0x08;
0283 touch = buf[0] & 0x10;
0284
0285 vsxxxaa_drop_bytes(mouse, 5);
0286
0287 DBG(KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
0288 mouse->name, mouse->phys, x, y,
0289 left ? "L" : "l", middle ? "M" : "m",
0290 right ? "R" : "r", touch ? "T" : "t");
0291
0292
0293
0294
0295 input_report_key(dev, BTN_LEFT, left);
0296 input_report_key(dev, BTN_MIDDLE, middle);
0297 input_report_key(dev, BTN_RIGHT, right);
0298 input_report_key(dev, BTN_TOUCH, touch);
0299 input_report_abs(dev, ABS_X, x);
0300 input_report_abs(dev, ABS_Y, y);
0301 input_sync(dev);
0302 }
0303
0304 static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse)
0305 {
0306 struct input_dev *dev = mouse->dev;
0307 unsigned char *buf = mouse->buf;
0308 int left, middle, right;
0309 unsigned char error;
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 mouse->version = buf[0] & 0x0f;
0330 mouse->country = (buf[1] >> 4) & 0x07;
0331 mouse->type = buf[1] & 0x0f;
0332 error = buf[2] & 0x7f;
0333
0334
0335
0336
0337
0338
0339 left = buf[0] & 0x04;
0340 middle = buf[0] & 0x02;
0341 right = buf[0] & 0x01;
0342
0343 vsxxxaa_drop_bytes(mouse, 4);
0344 vsxxxaa_detection_done(mouse);
0345
0346 if (error <= 0x1f) {
0347
0348 input_report_key(dev, BTN_LEFT, left);
0349 input_report_key(dev, BTN_MIDDLE, middle);
0350 input_report_key(dev, BTN_RIGHT, right);
0351 input_report_key(dev, BTN_TOUCH, 0);
0352 input_sync(dev);
0353
0354 if (error != 0)
0355 printk(KERN_INFO "Your %s on %s reports error=0x%02x\n",
0356 mouse->name, mouse->phys, error);
0357
0358 }
0359
0360
0361
0362
0363
0364 printk(KERN_NOTICE
0365 "%s on %s: Forcing standard packet format, "
0366 "incremental streaming mode and 72 samples/sec\n",
0367 mouse->name, mouse->phys);
0368 serio_write(mouse->serio, 'S');
0369 mdelay(50);
0370 serio_write(mouse->serio, 'R');
0371 mdelay(50);
0372 serio_write(mouse->serio, 'L');
0373 }
0374
0375 static void vsxxxaa_parse_buffer(struct vsxxxaa *mouse)
0376 {
0377 unsigned char *buf = mouse->buf;
0378 int stray_bytes;
0379
0380
0381
0382
0383 do {
0384
0385
0386
0387
0388
0389
0390
0391 while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
0392 printk(KERN_ERR "%s on %s: Dropping a byte to regain "
0393 "sync with mouse data stream...\n",
0394 mouse->name, mouse->phys);
0395 vsxxxaa_drop_bytes(mouse, 1);
0396 }
0397
0398
0399
0400
0401
0402 if (vsxxxaa_smells_like_packet(mouse, VSXXXAA_PACKET_REL, 3)) {
0403
0404 stray_bytes = vsxxxaa_check_packet(mouse, 3);
0405 if (!stray_bytes)
0406 vsxxxaa_handle_REL_packet(mouse);
0407
0408 } else if (vsxxxaa_smells_like_packet(mouse,
0409 VSXXXAA_PACKET_ABS, 5)) {
0410
0411 stray_bytes = vsxxxaa_check_packet(mouse, 5);
0412 if (!stray_bytes)
0413 vsxxxaa_handle_ABS_packet(mouse);
0414
0415 } else if (vsxxxaa_smells_like_packet(mouse,
0416 VSXXXAA_PACKET_POR, 4)) {
0417
0418 stray_bytes = vsxxxaa_check_packet(mouse, 4);
0419 if (!stray_bytes)
0420 vsxxxaa_handle_POR_packet(mouse);
0421
0422 } else {
0423 break;
0424 }
0425
0426 if (stray_bytes > 0) {
0427 printk(KERN_ERR "Dropping %d bytes now...\n",
0428 stray_bytes);
0429 vsxxxaa_drop_bytes(mouse, stray_bytes);
0430 }
0431
0432 } while (1);
0433 }
0434
0435 static irqreturn_t vsxxxaa_interrupt(struct serio *serio,
0436 unsigned char data, unsigned int flags)
0437 {
0438 struct vsxxxaa *mouse = serio_get_drvdata(serio);
0439
0440 vsxxxaa_queue_byte(mouse, data);
0441 vsxxxaa_parse_buffer(mouse);
0442
0443 return IRQ_HANDLED;
0444 }
0445
0446 static void vsxxxaa_disconnect(struct serio *serio)
0447 {
0448 struct vsxxxaa *mouse = serio_get_drvdata(serio);
0449
0450 serio_close(serio);
0451 serio_set_drvdata(serio, NULL);
0452 input_unregister_device(mouse->dev);
0453 kfree(mouse);
0454 }
0455
0456 static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv)
0457 {
0458 struct vsxxxaa *mouse;
0459 struct input_dev *input_dev;
0460 int err = -ENOMEM;
0461
0462 mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL);
0463 input_dev = input_allocate_device();
0464 if (!mouse || !input_dev)
0465 goto fail1;
0466
0467 mouse->dev = input_dev;
0468 mouse->serio = serio;
0469 strlcat(mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
0470 sizeof(mouse->name));
0471 snprintf(mouse->phys, sizeof(mouse->phys), "%s/input0", serio->phys);
0472
0473 input_dev->name = mouse->name;
0474 input_dev->phys = mouse->phys;
0475 input_dev->id.bustype = BUS_RS232;
0476 input_dev->dev.parent = &serio->dev;
0477
0478 __set_bit(EV_KEY, input_dev->evbit);
0479 __set_bit(EV_REL, input_dev->evbit);
0480 __set_bit(EV_ABS, input_dev->evbit);
0481 __set_bit(BTN_LEFT, input_dev->keybit);
0482 __set_bit(BTN_MIDDLE, input_dev->keybit);
0483 __set_bit(BTN_RIGHT, input_dev->keybit);
0484 __set_bit(BTN_TOUCH, input_dev->keybit);
0485 __set_bit(REL_X, input_dev->relbit);
0486 __set_bit(REL_Y, input_dev->relbit);
0487 input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
0488 input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
0489
0490 serio_set_drvdata(serio, mouse);
0491
0492 err = serio_open(serio, drv);
0493 if (err)
0494 goto fail2;
0495
0496
0497
0498
0499
0500 serio_write(serio, 'T');
0501
0502 err = input_register_device(input_dev);
0503 if (err)
0504 goto fail3;
0505
0506 return 0;
0507
0508 fail3: serio_close(serio);
0509 fail2: serio_set_drvdata(serio, NULL);
0510 fail1: input_free_device(input_dev);
0511 kfree(mouse);
0512 return err;
0513 }
0514
0515 static struct serio_device_id vsxxaa_serio_ids[] = {
0516 {
0517 .type = SERIO_RS232,
0518 .proto = SERIO_VSXXXAA,
0519 .id = SERIO_ANY,
0520 .extra = SERIO_ANY,
0521 },
0522 { 0 }
0523 };
0524
0525 MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
0526
0527 static struct serio_driver vsxxxaa_drv = {
0528 .driver = {
0529 .name = "vsxxxaa",
0530 },
0531 .description = DRIVER_DESC,
0532 .id_table = vsxxaa_serio_ids,
0533 .connect = vsxxxaa_connect,
0534 .interrupt = vsxxxaa_interrupt,
0535 .disconnect = vsxxxaa_disconnect,
0536 };
0537
0538 module_serio_driver(vsxxxaa_drv);