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