1 /* 2 * Input driver to ExplorerPS/2 device driver module. 3 * 4 * Copyright (c) 1999-2002 Vojtech Pavlik 5 * Copyright (c) 2004 Dmitry Torokhov 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 */ 11 12 #define MOUSEDEV_MINOR_BASE 32 13 #define MOUSEDEV_MINORS 32 14 #define MOUSEDEV_MIX 31 15 16 #include <linux/slab.h> 17 #include <linux/poll.h> 18 #include <linux/module.h> 19 #include <linux/moduleparam.h> 20 #include <linux/init.h> 21 #include <linux/input.h> 22 #include <linux/config.h> 23 #include <linux/smp_lock.h> 24 #include <linux/random.h> 25 #include <linux/major.h> 26 #include <linux/device.h> 27 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 28 #include <linux/miscdevice.h> 29 #endif 30 31 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 32 MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces"); 33 MODULE_LICENSE("GPL"); 34 35 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X 36 #define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 37 #endif 38 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y 39 #define CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 40 #endif 41 42 static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; 43 module_param(xres, uint, 0644); 44 MODULE_PARM_DESC(xres, "Horizontal screen resolution"); 45 46 static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; 47 module_param(yres, uint, 0644); 48 MODULE_PARM_DESC(yres, "Vertical screen resolution"); 49 50 static unsigned tap_time = 200; 51 module_param(tap_time, uint, 0644); 52 MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)"); 53 54 struct mousedev_hw_data { 55 int dx, dy, dz; 56 int x, y; 57 int abs_event; 58 unsigned long buttons; 59 }; 60 61 struct mousedev { 62 int exist; 63 int open; 64 int minor; 65 char name[16]; 66 wait_queue_head_t wait; 67 struct list_head list; 68 struct input_handle handle; 69 70 struct mousedev_hw_data packet; 71 unsigned int pkt_count; 72 int old_x[4], old_y[4]; 73 int frac_dx, frac_dy; 74 unsigned long touch; 75 }; 76 77 enum mousedev_emul { 78 MOUSEDEV_EMUL_PS2, 79 MOUSEDEV_EMUL_IMPS, 80 MOUSEDEV_EMUL_EXPS 81 }; 82 83 struct mousedev_motion { 84 int dx, dy, dz; 85 unsigned long buttons; 86 }; 87 88 #define PACKET_QUEUE_LEN 16 89 struct mousedev_list { 90 struct fasync_struct *fasync; 91 struct mousedev *mousedev; 92 struct list_head node; 93 94 struct mousedev_motion packets[PACKET_QUEUE_LEN]; 95 unsigned int head, tail; 96 spinlock_t packet_lock; 97 int pos_x, pos_y; 98 99 signed char ps2[6]; 100 unsigned char ready, buffer, bufsiz; 101 unsigned char imexseq, impsseq; 102 enum mousedev_emul mode; 103 unsigned long last_buttons; 104 }; 105 106 #define MOUSEDEV_SEQ_LEN 6 107 108 static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; 109 static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; 110 111 static struct input_handler mousedev_handler; 112 113 static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; 114 static struct mousedev mousedev_mix; 115 116 #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) 117 #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) 118 119 static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) 120 { 121 int size, tmp; 122 enum { FRACTION_DENOM = 128 }; 123 124 if (mousedev->touch) { 125 size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; 126 if (size == 0) 127 size = 256 * 2; 128 129 switch (code) { 130 case ABS_X: 131 fx(0) = value; 132 if (mousedev->pkt_count >= 2) { 133 tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; 134 tmp += mousedev->frac_dx; 135 mousedev->packet.dx = tmp / FRACTION_DENOM; 136 mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; 137 } 138 break; 139 140 case ABS_Y: 141 fy(0) = value; 142 if (mousedev->pkt_count >= 2) { 143 tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; 144 tmp += mousedev->frac_dy; 145 mousedev->packet.dy = tmp / FRACTION_DENOM; 146 mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; 147 } 148 break; 149 } 150 } 151 } 152 153 static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) 154 { 155 int size; 156 157 switch (code) { 158 case ABS_X: 159 size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; 160 if (size == 0) 161 size = xres ? : 1; 162 if (value > dev->absmax[ABS_X]) 163 value = dev->absmax[ABS_X]; 164 if (value < dev->absmin[ABS_X]) 165 value = dev->absmin[ABS_X]; 166 mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; 167 mousedev->packet.abs_event = 1; 168 break; 169 170 case ABS_Y: 171 size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; 172 if (size == 0) 173 size = yres ? : 1; 174 if (value > dev->absmax[ABS_Y]) 175 value = dev->absmax[ABS_Y]; 176 if (value < dev->absmin[ABS_Y]) 177 value = dev->absmin[ABS_Y]; 178 mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; 179 mousedev->packet.abs_event = 1; 180 break; 181 } 182 } 183 184 static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value) 185 { 186 switch (code) { 187 case REL_X: mousedev->packet.dx += value; break; 188 case REL_Y: mousedev->packet.dy -= value; break; 189 case REL_WHEEL: mousedev->packet.dz -= value; break; 190 } 191 } 192 193 static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value) 194 { 195 int index; 196 197 switch (code) { 198 case BTN_TOUCH: 199 case BTN_0: 200 case BTN_FORWARD: 201 case BTN_LEFT: index = 0; break; 202 case BTN_STYLUS: 203 case BTN_1: 204 case BTN_RIGHT: index = 1; break; 205 case BTN_2: 206 case BTN_STYLUS2: 207 case BTN_MIDDLE: index = 2; break; 208 case BTN_3: 209 case BTN_BACK: 210 case BTN_SIDE: index = 3; break; 211 case BTN_4: 212 case BTN_EXTRA: index = 4; break; 213 default: return; 214 } 215 216 if (value) { 217 set_bit(index, &mousedev->packet.buttons); 218 set_bit(index, &mousedev_mix.packet.buttons); 219 } else { 220 clear_bit(index, &mousedev->packet.buttons); 221 clear_bit(index, &mousedev_mix.packet.buttons); 222 } 223 } 224 225 static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) 226 { 227 struct mousedev_list *list; 228 struct mousedev_motion *p; 229 unsigned long flags; 230 int wake_readers = 0; 231 232 list_for_each_entry(list, &mousedev->list, node) { 233 spin_lock_irqsave(&list->packet_lock, flags); 234 235 p = &list->packets[list->head]; 236 if (list->ready && p->buttons != mousedev->packet.buttons) { 237 unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN; 238 if (new_head != list->tail) { 239 p = &list->packets[list->head = new_head]; 240 memset(p, 0, sizeof(struct mousedev_motion)); 241 } 242 } 243 244 if (packet->abs_event) { 245 p->dx += packet->x - list->pos_x; 246 p->dy += packet->y - list->pos_y; 247 list->pos_x = packet->x; 248 list->pos_y = packet->y; 249 } 250 251 list->pos_x += packet->dx; 252 list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x); 253 list->pos_y += packet->dy; 254 list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y); 255 256 p->dx += packet->dx; 257 p->dy += packet->dy; 258 p->dz += packet->dz; 259 p->buttons = mousedev->packet.buttons; 260 261 if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons) 262 list->ready = 1; 263 264 spin_unlock_irqrestore(&list->packet_lock, flags); 265 266 if (list->ready) { 267 kill_fasync(&list->fasync, SIGIO, POLL_IN); 268 wake_readers = 1; 269 } 270 } 271 272 if (wake_readers) 273 wake_up_interruptible(&mousedev->wait); 274 } 275 276 static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) 277 { 278 if (!value) { 279 if (mousedev->touch && 280 time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) { 281 /* 282 * Toggle left button to emulate tap. 283 * We rely on the fact that mousedev_mix always has 0 284 * motion packet so we won't mess current position. 285 */ 286 set_bit(0, &mousedev->packet.buttons); 287 set_bit(0, &mousedev_mix.packet.buttons); 288 mousedev_notify_readers(mousedev, &mousedev_mix.packet); 289 mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet); 290 clear_bit(0, &mousedev->packet.buttons); 291 clear_bit(0, &mousedev_mix.packet.buttons); 292 } 293 mousedev->touch = mousedev->pkt_count = 0; 294 mousedev->frac_dx = 0; 295 mousedev->frac_dy = 0; 296 297 } else if (!mousedev->touch) 298 mousedev->touch = jiffies; 299 } 300 301 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) 302 { 303 struct mousedev *mousedev = handle->private; 304 305 switch (type) { 306 case EV_ABS: 307 /* Ignore joysticks */ 308 if (test_bit(BTN_TRIGGER, handle->dev->keybit)) 309 return; 310 311 if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) 312 mousedev_touchpad_event(handle->dev, mousedev, code, value); 313 else 314 mousedev_abs_event(handle->dev, mousedev, code, value); 315 316 break; 317 318 case EV_REL: 319 mousedev_rel_event(mousedev, code, value); 320 break; 321 322 case EV_KEY: 323 if (value != 2) { 324 if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) 325 mousedev_touchpad_touch(mousedev, value); 326 else 327 mousedev_key_event(mousedev, code, value); 328 } 329 break; 330 331 case EV_SYN: 332 if (code == SYN_REPORT) { 333 if (mousedev->touch) { 334 mousedev->pkt_count++; 335 /* Input system eats duplicate events, but we need all of them 336 * to do correct averaging so apply present one forward 337 */ 338 fx(0) = fx(1); 339 fy(0) = fy(1); 340 } 341 342 mousedev_notify_readers(mousedev, &mousedev->packet); 343 mousedev_notify_readers(&mousedev_mix, &mousedev->packet); 344 345 mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; 346 mousedev->packet.abs_event = 0; 347 } 348 break; 349 } 350 } 351 352 static int mousedev_fasync(int fd, struct file *file, int on) 353 { 354 int retval; 355 struct mousedev_list *list = file->private_data; 356 357 retval = fasync_helper(fd, file, on, &list->fasync); 358 359 return retval < 0 ? retval : 0; 360 } 361 362 static void mousedev_free(struct mousedev *mousedev) 363 { 364 mousedev_table[mousedev->minor] = NULL; 365 kfree(mousedev); 366 } 367 368 static void mixdev_release(void) 369 { 370 struct input_handle *handle; 371 372 list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { 373 struct mousedev *mousedev = handle->private; 374 375 if (!mousedev->open) { 376 if (mousedev->exist) 377 input_close_device(&mousedev->handle); 378 else 379 mousedev_free(mousedev); 380 } 381 } 382 } 383 384 static int mousedev_release(struct inode * inode, struct file * file) 385 { 386 struct mousedev_list *list = file->private_data; 387 388 mousedev_fasync(-1, file, 0); 389 390 list_del(&list->node); 391 392 if (!--list->mousedev->open) { 393 if (list->mousedev->minor == MOUSEDEV_MIX) 394 mixdev_release(); 395 else if (!mousedev_mix.open) { 396 if (list->mousedev->exist) 397 input_close_device(&list->mousedev->handle); 398 else 399 mousedev_free(list->mousedev); 400 } 401 } 402 403 kfree(list); 404 return 0; 405 } 406 407 static int mousedev_open(struct inode * inode, struct file * file) 408 { 409 struct mousedev_list *list; 410 struct input_handle *handle; 411 struct mousedev *mousedev; 412 int i; 413 414 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 415 if (imajor(inode) == MISC_MAJOR) 416 i = MOUSEDEV_MIX; 417 else 418 #endif 419 i = iminor(inode) - MOUSEDEV_MINOR_BASE; 420 421 if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) 422 return -ENODEV; 423 424 if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL))) 425 return -ENOMEM; 426 427 spin_lock_init(&list->packet_lock); 428 list->pos_x = xres / 2; 429 list->pos_y = yres / 2; 430 list->mousedev = mousedev_table[i]; 431 list_add_tail(&list->node, &mousedev_table[i]->list); 432 file->private_data = list; 433 434 if (!list->mousedev->open++) { 435 if (list->mousedev->minor == MOUSEDEV_MIX) { 436 list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { 437 mousedev = handle->private; 438 if (!mousedev->open && mousedev->exist) 439 input_open_device(handle); 440 } 441 } else 442 if (!mousedev_mix.open && list->mousedev->exist) 443 input_open_device(&list->mousedev->handle); 444 } 445 446 return 0; 447 } 448 449 static inline int mousedev_limit_delta(int delta, int limit) 450 { 451 return delta > limit ? limit : (delta < -limit ? -limit : delta); 452 } 453 454 static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) 455 { 456 struct mousedev_motion *p; 457 unsigned long flags; 458 459 spin_lock_irqsave(&list->packet_lock, flags); 460 p = &list->packets[list->tail]; 461 462 ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); 463 ps2_data[1] = mousedev_limit_delta(p->dx, 127); 464 ps2_data[2] = mousedev_limit_delta(p->dy, 127); 465 p->dx -= ps2_data[1]; 466 p->dy -= ps2_data[2]; 467 468 switch (list->mode) { 469 case MOUSEDEV_EMUL_EXPS: 470 ps2_data[3] = mousedev_limit_delta(p->dz, 7); 471 p->dz -= ps2_data[3]; 472 ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); 473 list->bufsiz = 4; 474 break; 475 476 case MOUSEDEV_EMUL_IMPS: 477 ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); 478 ps2_data[3] = mousedev_limit_delta(p->dz, 127); 479 p->dz -= ps2_data[3]; 480 list->bufsiz = 4; 481 break; 482 483 case MOUSEDEV_EMUL_PS2: 484 default: 485 ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); 486 p->dz = 0; 487 list->bufsiz = 3; 488 break; 489 } 490 491 if (!p->dx && !p->dy && !p->dz) { 492 if (list->tail == list->head) { 493 list->ready = 0; 494 list->last_buttons = p->buttons; 495 } else 496 list->tail = (list->tail + 1) % PACKET_QUEUE_LEN; 497 } 498 499 spin_unlock_irqrestore(&list->packet_lock, flags); 500 } 501 502 503 static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) 504 { 505 struct mousedev_list *list = file->private_data; 506 unsigned char c; 507 unsigned int i; 508 509 for (i = 0; i < count; i++) { 510 511 if (get_user(c, buffer + i)) 512 return -EFAULT; 513 514 if (c == mousedev_imex_seq[list->imexseq]) { 515 if (++list->imexseq == MOUSEDEV_SEQ_LEN) { 516 list->imexseq = 0; 517 list->mode = MOUSEDEV_EMUL_EXPS; 518 } 519 } else 520 list->imexseq = 0; 521 522 if (c == mousedev_imps_seq[list->impsseq]) { 523 if (++list->impsseq == MOUSEDEV_SEQ_LEN) { 524 list->impsseq = 0; 525 list->mode = MOUSEDEV_EMUL_IMPS; 526 } 527 } else 528 list->impsseq = 0; 529 530 list->ps2[0] = 0xfa; 531 532 switch (c) { 533 534 case 0xeb: /* Poll */ 535 mousedev_packet(list, &list->ps2[1]); 536 list->bufsiz++; /* account for leading ACK */ 537 break; 538 539 case 0xf2: /* Get ID */ 540 switch (list->mode) { 541 case MOUSEDEV_EMUL_PS2: list->ps2[1] = 0; break; 542 case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break; 543 case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break; 544 } 545 list->bufsiz = 2; 546 break; 547 548 case 0xe9: /* Get info */ 549 list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200; 550 list->bufsiz = 4; 551 break; 552 553 case 0xff: /* Reset */ 554 list->impsseq = list->imexseq = 0; 555 list->mode = MOUSEDEV_EMUL_PS2; 556 list->ps2[1] = 0xaa; list->ps2[2] = 0x00; 557 list->bufsiz = 3; 558 break; 559 560 default: 561 list->bufsiz = 1; 562 break; 563 } 564 565 list->buffer = list->bufsiz; 566 } 567 568 kill_fasync(&list->fasync, SIGIO, POLL_IN); 569 570 wake_up_interruptible(&list->mousedev->wait); 571 572 return count; 573 } 574 575 static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) 576 { 577 struct mousedev_list *list = file->private_data; 578 int retval = 0; 579 580 if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK)) 581 return -EAGAIN; 582 583 retval = wait_event_interruptible(list->mousedev->wait, 584 !list->mousedev->exist || list->ready || list->buffer); 585 586 if (retval) 587 return retval; 588 589 if (!list->mousedev->exist) 590 return -ENODEV; 591 592 if (!list->buffer && list->ready) { 593 mousedev_packet(list, list->ps2); 594 list->buffer = list->bufsiz; 595 } 596 597 if (count > list->buffer) 598 count = list->buffer; 599 600 list->buffer -= count; 601 602 if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count)) 603 return -EFAULT; 604 605 return count; 606 } 607 608 /* No kernel lock - fine */ 609 static unsigned int mousedev_poll(struct file *file, poll_table *wait) 610 { 611 struct mousedev_list *list = file->private_data; 612 613 poll_wait(file, &list->mousedev->wait, wait); 614 return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) | 615 (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); 616 } 617 618 static struct file_operations mousedev_fops = { 619 .owner = THIS_MODULE, 620 .read = mousedev_read, 621 .write = mousedev_write, 622 .poll = mousedev_poll, 623 .open = mousedev_open, 624 .release = mousedev_release, 625 .fasync = mousedev_fasync, 626 }; 627 628 static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id) 629 { 630 struct mousedev *mousedev; 631 struct class_device *cdev; 632 int minor = 0; 633 634 for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); 635 if (minor == MOUSEDEV_MINORS) { 636 printk(KERN_ERR "mousedev: no more free mousedev devices\n"); 637 return NULL; 638 } 639 640 if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) 641 return NULL; 642 643 INIT_LIST_HEAD(&mousedev->list); 644 init_waitqueue_head(&mousedev->wait); 645 646 mousedev->minor = minor; 647 mousedev->exist = 1; 648 mousedev->handle.dev = dev; 649 mousedev->handle.name = mousedev->name; 650 mousedev->handle.handler = handler; 651 mousedev->handle.private = mousedev; 652 sprintf(mousedev->name, "mouse%d", minor); 653 654 if (mousedev_mix.open) 655 input_open_device(&mousedev->handle); 656 657 mousedev_table[minor] = mousedev; 658 659 cdev = class_device_create(&input_class, &dev->cdev, 660 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), 661 dev->cdev.dev, mousedev->name); 662 663 /* temporary symlink to keep userspace happy */ 664 sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, 665 mousedev->name); 666 667 return &mousedev->handle; 668 } 669 670 static void mousedev_disconnect(struct input_handle *handle) 671 { 672 struct mousedev *mousedev = handle->private; 673 struct mousedev_list *list; 674 675 sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name); 676 class_device_destroy(&input_class, 677 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); 678 mousedev->exist = 0; 679 680 if (mousedev->open) { 681 input_close_device(handle); 682 wake_up_interruptible(&mousedev->wait); 683 list_for_each_entry(list, &mousedev->list, node) 684 kill_fasync(&list->fasync, SIGIO, POLL_HUP); 685 } else { 686 if (mousedev_mix.open) 687 input_close_device(handle); 688 mousedev_free(mousedev); 689 } 690 } 691 692 static struct input_device_id mousedev_ids[] = { 693 { 694 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, 695 .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, 696 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, 697 .relbit = { BIT(REL_X) | BIT(REL_Y) }, 698 }, /* A mouse like device, at least one button, two relative axes */ 699 { 700 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT, 701 .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, 702 .relbit = { BIT(REL_WHEEL) }, 703 }, /* A separate scrollwheel */ 704 { 705 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, 706 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, 707 .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, 708 .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, 709 }, /* A tablet like device, at least touch detection, two absolute axes */ 710 { 711 .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, 712 .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, 713 .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, 714 .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) }, 715 }, /* A touchpad */ 716 717 { }, /* Terminating entry */ 718 }; 719 720 MODULE_DEVICE_TABLE(input, mousedev_ids); 721 722 static struct input_handler mousedev_handler = { 723 .event = mousedev_event, 724 .connect = mousedev_connect, 725 .disconnect = mousedev_disconnect, 726 .fops = &mousedev_fops, 727 .minor = MOUSEDEV_MINOR_BASE, 728 .name = "mousedev", 729 .id_table = mousedev_ids, 730 }; 731 732 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 733 static struct miscdevice psaux_mouse = { 734 PSMOUSE_MINOR, "psaux", &mousedev_fops 735 }; 736 static int psaux_registered; 737 #endif 738 739 static int __init mousedev_init(void) 740 { 741 input_register_handler(&mousedev_handler); 742 743 memset(&mousedev_mix, 0, sizeof(struct mousedev)); 744 INIT_LIST_HEAD(&mousedev_mix.list); 745 init_waitqueue_head(&mousedev_mix.wait); 746 mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; 747 mousedev_mix.exist = 1; 748 mousedev_mix.minor = MOUSEDEV_MIX; 749 750 class_device_create(&input_class, NULL, 751 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice"); 752 753 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 754 if (!(psaux_registered = !misc_register(&psaux_mouse))) 755 printk(KERN_WARNING "mice: could not misc_register the device\n"); 756 #endif 757 758 printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n"); 759 760 return 0; 761 } 762 763 static void __exit mousedev_exit(void) 764 { 765 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX 766 if (psaux_registered) 767 misc_deregister(&psaux_mouse); 768 #endif 769 class_device_destroy(&input_class, 770 MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX)); 771 input_unregister_handler(&mousedev_handler); 772 } 773 774 module_init(mousedev_init); 775 module_exit(mousedev_exit); 776