linux/drivers/input/mousedev.c
<<
>>
Prefs
   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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13
  14#define MOUSEDEV_MINOR_BASE     32
  15#define MOUSEDEV_MINORS         31
  16#define MOUSEDEV_MIX            63
  17
  18#include <linux/sched.h>
  19#include <linux/slab.h>
  20#include <linux/poll.h>
  21#include <linux/module.h>
  22#include <linux/init.h>
  23#include <linux/input.h>
  24#include <linux/random.h>
  25#include <linux/major.h>
  26#include <linux/device.h>
  27#include <linux/cdev.h>
  28#include <linux/kernel.h>
  29
  30MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  31MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
  32MODULE_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
  41static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
  42module_param(xres, uint, 0644);
  43MODULE_PARM_DESC(xres, "Horizontal screen resolution");
  44
  45static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
  46module_param(yres, uint, 0644);
  47MODULE_PARM_DESC(yres, "Vertical screen resolution");
  48
  49static unsigned tap_time = 200;
  50module_param(tap_time, uint, 0644);
  51MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
  52
  53struct mousedev_hw_data {
  54        int dx, dy, dz;
  55        int x, y;
  56        int abs_event;
  57        unsigned long buttons;
  58};
  59
  60struct mousedev {
  61        int open;
  62        struct input_handle handle;
  63        wait_queue_head_t wait;
  64        struct list_head client_list;
  65        spinlock_t client_lock; /* protects client_list */
  66        struct mutex mutex;
  67        struct device dev;
  68        struct cdev cdev;
  69        bool exist;
  70        bool is_mixdev;
  71
  72        struct list_head mixdev_node;
  73        bool opened_by_mixdev;
  74
  75        struct mousedev_hw_data packet;
  76        unsigned int pkt_count;
  77        int old_x[4], old_y[4];
  78        int frac_dx, frac_dy;
  79        unsigned long touch;
  80};
  81
  82enum mousedev_emul {
  83        MOUSEDEV_EMUL_PS2,
  84        MOUSEDEV_EMUL_IMPS,
  85        MOUSEDEV_EMUL_EXPS
  86};
  87
  88struct mousedev_motion {
  89        int dx, dy, dz;
  90        unsigned long buttons;
  91};
  92
  93#define PACKET_QUEUE_LEN        16
  94struct mousedev_client {
  95        struct fasync_struct *fasync;
  96        struct mousedev *mousedev;
  97        struct list_head node;
  98
  99        struct mousedev_motion packets[PACKET_QUEUE_LEN];
 100        unsigned int head, tail;
 101        spinlock_t packet_lock;
 102        int pos_x, pos_y;
 103
 104        signed char ps2[6];
 105        unsigned char ready, buffer, bufsiz;
 106        unsigned char imexseq, impsseq;
 107        enum mousedev_emul mode;
 108        unsigned long last_buttons;
 109};
 110
 111#define MOUSEDEV_SEQ_LEN        6
 112
 113static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
 114static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
 115
 116static struct mousedev *mousedev_mix;
 117static LIST_HEAD(mousedev_mix_list);
 118
 119static void mixdev_open_devices(void);
 120static void mixdev_close_devices(void);
 121
 122#define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
 123#define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
 124
 125static void mousedev_touchpad_event(struct input_dev *dev,
 126                                    struct mousedev *mousedev,
 127                                    unsigned int code, int value)
 128{
 129        int size, tmp;
 130        enum { FRACTION_DENOM = 128 };
 131
 132        switch (code) {
 133
 134        case ABS_X:
 135
 136                fx(0) = value;
 137                if (mousedev->touch && mousedev->pkt_count >= 2) {
 138                        size = input_abs_get_max(dev, ABS_X) -
 139                                        input_abs_get_min(dev, ABS_X);
 140                        if (size == 0)
 141                                size = 256 * 2;
 142
 143                        tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size;
 144                        tmp += mousedev->frac_dx;
 145                        mousedev->packet.dx = tmp / FRACTION_DENOM;
 146                        mousedev->frac_dx =
 147                                tmp - mousedev->packet.dx * FRACTION_DENOM;
 148                }
 149                break;
 150
 151        case ABS_Y:
 152                fy(0) = value;
 153                if (mousedev->touch && mousedev->pkt_count >= 2) {
 154                        /* use X size for ABS_Y to keep the same scale */
 155                        size = input_abs_get_max(dev, ABS_X) -
 156                                        input_abs_get_min(dev, ABS_X);
 157                        if (size == 0)
 158                                size = 256 * 2;
 159
 160                        tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size;
 161                        tmp += mousedev->frac_dy;
 162                        mousedev->packet.dy = tmp / FRACTION_DENOM;
 163                        mousedev->frac_dy = tmp -
 164                                mousedev->packet.dy * FRACTION_DENOM;
 165                }
 166                break;
 167        }
 168}
 169
 170static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
 171                                unsigned int code, int value)
 172{
 173        int min, max, size;
 174
 175        switch (code) {
 176
 177        case ABS_X:
 178                min = input_abs_get_min(dev, ABS_X);
 179                max = input_abs_get_max(dev, ABS_X);
 180
 181                size = max - min;
 182                if (size == 0)
 183                        size = xres ? : 1;
 184
 185                value = clamp(value, min, max);
 186
 187                mousedev->packet.x = ((value - min) * xres) / size;
 188                mousedev->packet.abs_event = 1;
 189                break;
 190
 191        case ABS_Y:
 192                min = input_abs_get_min(dev, ABS_Y);
 193                max = input_abs_get_max(dev, ABS_Y);
 194
 195                size = max - min;
 196                if (size == 0)
 197                        size = yres ? : 1;
 198
 199                value = clamp(value, min, max);
 200
 201                mousedev->packet.y = yres - ((value - min) * yres) / size;
 202                mousedev->packet.abs_event = 1;
 203                break;
 204        }
 205}
 206
 207static void mousedev_rel_event(struct mousedev *mousedev,
 208                                unsigned int code, int value)
 209{
 210        switch (code) {
 211        case REL_X:
 212                mousedev->packet.dx += value;
 213                break;
 214
 215        case REL_Y:
 216                mousedev->packet.dy -= value;
 217                break;
 218
 219        case REL_WHEEL:
 220                mousedev->packet.dz -= value;
 221                break;
 222        }
 223}
 224
 225static void mousedev_key_event(struct mousedev *mousedev,
 226                                unsigned int code, int value)
 227{
 228        int index;
 229
 230        switch (code) {
 231
 232        case BTN_TOUCH:
 233        case BTN_0:
 234        case BTN_LEFT:          index = 0; break;
 235
 236        case BTN_STYLUS:
 237        case BTN_1:
 238        case BTN_RIGHT:         index = 1; break;
 239
 240        case BTN_2:
 241        case BTN_FORWARD:
 242        case BTN_STYLUS2:
 243        case BTN_MIDDLE:        index = 2; break;
 244
 245        case BTN_3:
 246        case BTN_BACK:
 247        case BTN_SIDE:          index = 3; break;
 248
 249        case BTN_4:
 250        case BTN_EXTRA:         index = 4; break;
 251
 252        default:                return;
 253        }
 254
 255        if (value) {
 256                set_bit(index, &mousedev->packet.buttons);
 257                set_bit(index, &mousedev_mix->packet.buttons);
 258        } else {
 259                clear_bit(index, &mousedev->packet.buttons);
 260                clear_bit(index, &mousedev_mix->packet.buttons);
 261        }
 262}
 263
 264static void mousedev_notify_readers(struct mousedev *mousedev,
 265                                    struct mousedev_hw_data *packet)
 266{
 267        struct mousedev_client *client;
 268        struct mousedev_motion *p;
 269        unsigned int new_head;
 270        int wake_readers = 0;
 271
 272        rcu_read_lock();
 273        list_for_each_entry_rcu(client, &mousedev->client_list, node) {
 274
 275                /* Just acquire the lock, interrupts already disabled */
 276                spin_lock(&client->packet_lock);
 277
 278                p = &client->packets[client->head];
 279                if (client->ready && p->buttons != mousedev->packet.buttons) {
 280                        new_head = (client->head + 1) % PACKET_QUEUE_LEN;
 281                        if (new_head != client->tail) {
 282                                p = &client->packets[client->head = new_head];
 283                                memset(p, 0, sizeof(struct mousedev_motion));
 284                        }
 285                }
 286
 287                if (packet->abs_event) {
 288                        p->dx += packet->x - client->pos_x;
 289                        p->dy += packet->y - client->pos_y;
 290                        client->pos_x = packet->x;
 291                        client->pos_y = packet->y;
 292                }
 293
 294                client->pos_x += packet->dx;
 295                client->pos_x = client->pos_x < 0 ?
 296                        0 : (client->pos_x >= xres ? xres : client->pos_x);
 297                client->pos_y += packet->dy;
 298                client->pos_y = client->pos_y < 0 ?
 299                        0 : (client->pos_y >= yres ? yres : client->pos_y);
 300
 301                p->dx += packet->dx;
 302                p->dy += packet->dy;
 303                p->dz += packet->dz;
 304                p->buttons = mousedev->packet.buttons;
 305
 306                if (p->dx || p->dy || p->dz ||
 307                    p->buttons != client->last_buttons)
 308                        client->ready = 1;
 309
 310                spin_unlock(&client->packet_lock);
 311
 312                if (client->ready) {
 313                        kill_fasync(&client->fasync, SIGIO, POLL_IN);
 314                        wake_readers = 1;
 315                }
 316        }
 317        rcu_read_unlock();
 318
 319        if (wake_readers)
 320                wake_up_interruptible(&mousedev->wait);
 321}
 322
 323static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
 324{
 325        if (!value) {
 326                if (mousedev->touch &&
 327                    time_before(jiffies,
 328                                mousedev->touch + msecs_to_jiffies(tap_time))) {
 329                        /*
 330                         * Toggle left button to emulate tap.
 331                         * We rely on the fact that mousedev_mix always has 0
 332                         * motion packet so we won't mess current position.
 333                         */
 334                        set_bit(0, &mousedev->packet.buttons);
 335                        set_bit(0, &mousedev_mix->packet.buttons);
 336                        mousedev_notify_readers(mousedev, &mousedev_mix->packet);
 337                        mousedev_notify_readers(mousedev_mix,
 338                                                &mousedev_mix->packet);
 339                        clear_bit(0, &mousedev->packet.buttons);
 340                        clear_bit(0, &mousedev_mix->packet.buttons);
 341                }
 342                mousedev->touch = mousedev->pkt_count = 0;
 343                mousedev->frac_dx = 0;
 344                mousedev->frac_dy = 0;
 345
 346        } else if (!mousedev->touch)
 347                mousedev->touch = jiffies;
 348}
 349
 350static void mousedev_event(struct input_handle *handle,
 351                           unsigned int type, unsigned int code, int value)
 352{
 353        struct mousedev *mousedev = handle->private;
 354
 355        switch (type) {
 356
 357        case EV_ABS:
 358                /* Ignore joysticks */
 359                if (test_bit(BTN_TRIGGER, handle->dev->keybit))
 360                        return;
 361
 362                if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
 363                        mousedev_touchpad_event(handle->dev,
 364                                                mousedev, code, value);
 365                else
 366                        mousedev_abs_event(handle->dev, mousedev, code, value);
 367
 368                break;
 369
 370        case EV_REL:
 371                mousedev_rel_event(mousedev, code, value);
 372                break;
 373
 374        case EV_KEY:
 375                if (value != 2) {
 376                        if (code == BTN_TOUCH &&
 377                            test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
 378                                mousedev_touchpad_touch(mousedev, value);
 379                        else
 380                                mousedev_key_event(mousedev, code, value);
 381                }
 382                break;
 383
 384        case EV_SYN:
 385                if (code == SYN_REPORT) {
 386                        if (mousedev->touch) {
 387                                mousedev->pkt_count++;
 388                                /*
 389                                 * Input system eats duplicate events,
 390                                 * but we need all of them to do correct
 391                                 * averaging so apply present one forward
 392                                 */
 393                                fx(0) = fx(1);
 394                                fy(0) = fy(1);
 395                        }
 396
 397                        mousedev_notify_readers(mousedev, &mousedev->packet);
 398                        mousedev_notify_readers(mousedev_mix, &mousedev->packet);
 399
 400                        mousedev->packet.dx = mousedev->packet.dy =
 401                                mousedev->packet.dz = 0;
 402                        mousedev->packet.abs_event = 0;
 403                }
 404                break;
 405        }
 406}
 407
 408static int mousedev_fasync(int fd, struct file *file, int on)
 409{
 410        struct mousedev_client *client = file->private_data;
 411
 412        return fasync_helper(fd, file, on, &client->fasync);
 413}
 414
 415static void mousedev_free(struct device *dev)
 416{
 417        struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
 418
 419        input_put_device(mousedev->handle.dev);
 420        kfree(mousedev);
 421}
 422
 423static int mousedev_open_device(struct mousedev *mousedev)
 424{
 425        int retval;
 426
 427        retval = mutex_lock_interruptible(&mousedev->mutex);
 428        if (retval)
 429                return retval;
 430
 431        if (mousedev->is_mixdev)
 432                mixdev_open_devices();
 433        else if (!mousedev->exist)
 434                retval = -ENODEV;
 435        else if (!mousedev->open++) {
 436                retval = input_open_device(&mousedev->handle);
 437                if (retval)
 438                        mousedev->open--;
 439        }
 440
 441        mutex_unlock(&mousedev->mutex);
 442        return retval;
 443}
 444
 445static void mousedev_close_device(struct mousedev *mousedev)
 446{
 447        mutex_lock(&mousedev->mutex);
 448
 449        if (mousedev->is_mixdev)
 450                mixdev_close_devices();
 451        else if (mousedev->exist && !--mousedev->open)
 452                input_close_device(&mousedev->handle);
 453
 454        mutex_unlock(&mousedev->mutex);
 455}
 456
 457/*
 458 * Open all available devices so they can all be multiplexed in one.
 459 * stream. Note that this function is called with mousedev_mix->mutex
 460 * held.
 461 */
 462static void mixdev_open_devices(void)
 463{
 464        struct mousedev *mousedev;
 465
 466        if (mousedev_mix->open++)
 467                return;
 468
 469        list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
 470                if (!mousedev->opened_by_mixdev) {
 471                        if (mousedev_open_device(mousedev))
 472                                continue;
 473
 474                        mousedev->opened_by_mixdev = true;
 475                }
 476        }
 477}
 478
 479/*
 480 * Close all devices that were opened as part of multiplexed
 481 * device. Note that this function is called with mousedev_mix->mutex
 482 * held.
 483 */
 484static void mixdev_close_devices(void)
 485{
 486        struct mousedev *mousedev;
 487
 488        if (--mousedev_mix->open)
 489                return;
 490
 491        list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
 492                if (mousedev->opened_by_mixdev) {
 493                        mousedev->opened_by_mixdev = false;
 494                        mousedev_close_device(mousedev);
 495                }
 496        }
 497}
 498
 499
 500static void mousedev_attach_client(struct mousedev *mousedev,
 501                                   struct mousedev_client *client)
 502{
 503        spin_lock(&mousedev->client_lock);
 504        list_add_tail_rcu(&client->node, &mousedev->client_list);
 505        spin_unlock(&mousedev->client_lock);
 506}
 507
 508static void mousedev_detach_client(struct mousedev *mousedev,
 509                                   struct mousedev_client *client)
 510{
 511        spin_lock(&mousedev->client_lock);
 512        list_del_rcu(&client->node);
 513        spin_unlock(&mousedev->client_lock);
 514        synchronize_rcu();
 515}
 516
 517static int mousedev_release(struct inode *inode, struct file *file)
 518{
 519        struct mousedev_client *client = file->private_data;
 520        struct mousedev *mousedev = client->mousedev;
 521
 522        mousedev_detach_client(mousedev, client);
 523        kfree(client);
 524
 525        mousedev_close_device(mousedev);
 526
 527        return 0;
 528}
 529
 530static int mousedev_open(struct inode *inode, struct file *file)
 531{
 532        struct mousedev_client *client;
 533        struct mousedev *mousedev;
 534        int error;
 535
 536#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 537        if (imajor(inode) == MISC_MAJOR)
 538                mousedev = mousedev_mix;
 539        else
 540#endif
 541                mousedev = container_of(inode->i_cdev, struct mousedev, cdev);
 542
 543        client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
 544        if (!client)
 545                return -ENOMEM;
 546
 547        spin_lock_init(&client->packet_lock);
 548        client->pos_x = xres / 2;
 549        client->pos_y = yres / 2;
 550        client->mousedev = mousedev;
 551        mousedev_attach_client(mousedev, client);
 552
 553        error = mousedev_open_device(mousedev);
 554        if (error)
 555                goto err_free_client;
 556
 557        file->private_data = client;
 558        nonseekable_open(inode, file);
 559
 560        return 0;
 561
 562 err_free_client:
 563        mousedev_detach_client(mousedev, client);
 564        kfree(client);
 565        return error;
 566}
 567
 568static inline int mousedev_limit_delta(int delta, int limit)
 569{
 570        return delta > limit ? limit : (delta < -limit ? -limit : delta);
 571}
 572
 573static void mousedev_packet(struct mousedev_client *client,
 574                            signed char *ps2_data)
 575{
 576        struct mousedev_motion *p = &client->packets[client->tail];
 577
 578        ps2_data[0] = 0x08 |
 579                ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
 580        ps2_data[1] = mousedev_limit_delta(p->dx, 127);
 581        ps2_data[2] = mousedev_limit_delta(p->dy, 127);
 582        p->dx -= ps2_data[1];
 583        p->dy -= ps2_data[2];
 584
 585        switch (client->mode) {
 586        case MOUSEDEV_EMUL_EXPS:
 587                ps2_data[3] = mousedev_limit_delta(p->dz, 7);
 588                p->dz -= ps2_data[3];
 589                ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
 590                client->bufsiz = 4;
 591                break;
 592
 593        case MOUSEDEV_EMUL_IMPS:
 594                ps2_data[0] |=
 595                        ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 596                ps2_data[3] = mousedev_limit_delta(p->dz, 127);
 597                p->dz -= ps2_data[3];
 598                client->bufsiz = 4;
 599                break;
 600
 601        case MOUSEDEV_EMUL_PS2:
 602        default:
 603                ps2_data[0] |=
 604                        ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 605                p->dz = 0;
 606                client->bufsiz = 3;
 607                break;
 608        }
 609
 610        if (!p->dx && !p->dy && !p->dz) {
 611                if (client->tail == client->head) {
 612                        client->ready = 0;
 613                        client->last_buttons = p->buttons;
 614                } else
 615                        client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
 616        }
 617}
 618
 619static void mousedev_generate_response(struct mousedev_client *client,
 620                                        int command)
 621{
 622        client->ps2[0] = 0xfa; /* ACK */
 623
 624        switch (command) {
 625
 626        case 0xeb: /* Poll */
 627                mousedev_packet(client, &client->ps2[1]);
 628                client->bufsiz++; /* account for leading ACK */
 629                break;
 630
 631        case 0xf2: /* Get ID */
 632                switch (client->mode) {
 633                case MOUSEDEV_EMUL_PS2:
 634                        client->ps2[1] = 0;
 635                        break;
 636                case MOUSEDEV_EMUL_IMPS:
 637                        client->ps2[1] = 3;
 638                        break;
 639                case MOUSEDEV_EMUL_EXPS:
 640                        client->ps2[1] = 4;
 641                        break;
 642                }
 643                client->bufsiz = 2;
 644                break;
 645
 646        case 0xe9: /* Get info */
 647                client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
 648                client->bufsiz = 4;
 649                break;
 650
 651        case 0xff: /* Reset */
 652                client->impsseq = client->imexseq = 0;
 653                client->mode = MOUSEDEV_EMUL_PS2;
 654                client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
 655                client->bufsiz = 3;
 656                break;
 657
 658        default:
 659                client->bufsiz = 1;
 660                break;
 661        }
 662        client->buffer = client->bufsiz;
 663}
 664
 665static ssize_t mousedev_write(struct file *file, const char __user *buffer,
 666                                size_t count, loff_t *ppos)
 667{
 668        struct mousedev_client *client = file->private_data;
 669        unsigned char c;
 670        unsigned int i;
 671
 672        for (i = 0; i < count; i++) {
 673
 674                if (get_user(c, buffer + i))
 675                        return -EFAULT;
 676
 677                spin_lock_irq(&client->packet_lock);
 678
 679                if (c == mousedev_imex_seq[client->imexseq]) {
 680                        if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
 681                                client->imexseq = 0;
 682                                client->mode = MOUSEDEV_EMUL_EXPS;
 683                        }
 684                } else
 685                        client->imexseq = 0;
 686
 687                if (c == mousedev_imps_seq[client->impsseq]) {
 688                        if (++client->impsseq == MOUSEDEV_SEQ_LEN) {
 689                                client->impsseq = 0;
 690                                client->mode = MOUSEDEV_EMUL_IMPS;
 691                        }
 692                } else
 693                        client->impsseq = 0;
 694
 695                mousedev_generate_response(client, c);
 696
 697                spin_unlock_irq(&client->packet_lock);
 698        }
 699
 700        kill_fasync(&client->fasync, SIGIO, POLL_IN);
 701        wake_up_interruptible(&client->mousedev->wait);
 702
 703        return count;
 704}
 705
 706static ssize_t mousedev_read(struct file *file, char __user *buffer,
 707                             size_t count, loff_t *ppos)
 708{
 709        struct mousedev_client *client = file->private_data;
 710        struct mousedev *mousedev = client->mousedev;
 711        signed char data[sizeof(client->ps2)];
 712        int retval = 0;
 713
 714        if (!client->ready && !client->buffer && mousedev->exist &&
 715            (file->f_flags & O_NONBLOCK))
 716                return -EAGAIN;
 717
 718        retval = wait_event_interruptible(mousedev->wait,
 719                        !mousedev->exist || client->ready || client->buffer);
 720        if (retval)
 721                return retval;
 722
 723        if (!mousedev->exist)
 724                return -ENODEV;
 725
 726        spin_lock_irq(&client->packet_lock);
 727
 728        if (!client->buffer && client->ready) {
 729                mousedev_packet(client, client->ps2);
 730                client->buffer = client->bufsiz;
 731        }
 732
 733        if (count > client->buffer)
 734                count = client->buffer;
 735
 736        memcpy(data, client->ps2 + client->bufsiz - client->buffer, count);
 737        client->buffer -= count;
 738
 739        spin_unlock_irq(&client->packet_lock);
 740
 741        if (copy_to_user(buffer, data, count))
 742                return -EFAULT;
 743
 744        return count;
 745}
 746
 747/* No kernel lock - fine */
 748static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 749{
 750        struct mousedev_client *client = file->private_data;
 751        struct mousedev *mousedev = client->mousedev;
 752        unsigned int mask;
 753
 754        poll_wait(file, &mousedev->wait, wait);
 755
 756        mask = mousedev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
 757        if (client->ready || client->buffer)
 758                mask |= POLLIN | POLLRDNORM;
 759
 760        return mask;
 761}
 762
 763static const struct file_operations mousedev_fops = {
 764        .owner          = THIS_MODULE,
 765        .read           = mousedev_read,
 766        .write          = mousedev_write,
 767        .poll           = mousedev_poll,
 768        .open           = mousedev_open,
 769        .release        = mousedev_release,
 770        .fasync         = mousedev_fasync,
 771        .llseek         = noop_llseek,
 772};
 773
 774/*
 775 * Mark device non-existent. This disables writes, ioctls and
 776 * prevents new users from opening the device. Already posted
 777 * blocking reads will stay, however new ones will fail.
 778 */
 779static void mousedev_mark_dead(struct mousedev *mousedev)
 780{
 781        mutex_lock(&mousedev->mutex);
 782        mousedev->exist = false;
 783        mutex_unlock(&mousedev->mutex);
 784}
 785
 786/*
 787 * Wake up users waiting for IO so they can disconnect from
 788 * dead device.
 789 */
 790static void mousedev_hangup(struct mousedev *mousedev)
 791{
 792        struct mousedev_client *client;
 793
 794        spin_lock(&mousedev->client_lock);
 795        list_for_each_entry(client, &mousedev->client_list, node)
 796                kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 797        spin_unlock(&mousedev->client_lock);
 798
 799        wake_up_interruptible(&mousedev->wait);
 800}
 801
 802static void mousedev_cleanup(struct mousedev *mousedev)
 803{
 804        struct input_handle *handle = &mousedev->handle;
 805
 806        mousedev_mark_dead(mousedev);
 807        mousedev_hangup(mousedev);
 808
 809        cdev_del(&mousedev->cdev);
 810
 811        /* mousedev is marked dead so no one else accesses mousedev->open */
 812        if (mousedev->open)
 813                input_close_device(handle);
 814}
 815
 816static int mousedev_reserve_minor(bool mixdev)
 817{
 818        int minor;
 819
 820        if (mixdev) {
 821                minor = input_get_new_minor(MOUSEDEV_MIX, 1, false);
 822                if (minor < 0)
 823                        pr_err("failed to reserve mixdev minor: %d\n", minor);
 824        } else {
 825                minor = input_get_new_minor(MOUSEDEV_MINOR_BASE,
 826                                            MOUSEDEV_MINORS, true);
 827                if (minor < 0)
 828                        pr_err("failed to reserve new minor: %d\n", minor);
 829        }
 830
 831        return minor;
 832}
 833
 834static struct mousedev *mousedev_create(struct input_dev *dev,
 835                                        struct input_handler *handler,
 836                                        bool mixdev)
 837{
 838        struct mousedev *mousedev;
 839        int minor;
 840        int error;
 841
 842        minor = mousedev_reserve_minor(mixdev);
 843        if (minor < 0) {
 844                error = minor;
 845                goto err_out;
 846        }
 847
 848        mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
 849        if (!mousedev) {
 850                error = -ENOMEM;
 851                goto err_free_minor;
 852        }
 853
 854        INIT_LIST_HEAD(&mousedev->client_list);
 855        INIT_LIST_HEAD(&mousedev->mixdev_node);
 856        spin_lock_init(&mousedev->client_lock);
 857        mutex_init(&mousedev->mutex);
 858        lockdep_set_subclass(&mousedev->mutex,
 859                             mixdev ? SINGLE_DEPTH_NESTING : 0);
 860        init_waitqueue_head(&mousedev->wait);
 861
 862        if (mixdev) {
 863                dev_set_name(&mousedev->dev, "mice");
 864        } else {
 865                int dev_no = minor;
 866                /* Normalize device number if it falls into legacy range */
 867                if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
 868                        dev_no -= MOUSEDEV_MINOR_BASE;
 869                dev_set_name(&mousedev->dev, "mouse%d", dev_no);
 870        }
 871
 872        mousedev->exist = true;
 873        mousedev->is_mixdev = mixdev;
 874        mousedev->handle.dev = input_get_device(dev);
 875        mousedev->handle.name = dev_name(&mousedev->dev);
 876        mousedev->handle.handler = handler;
 877        mousedev->handle.private = mousedev;
 878
 879        mousedev->dev.class = &input_class;
 880        if (dev)
 881                mousedev->dev.parent = &dev->dev;
 882        mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor);
 883        mousedev->dev.release = mousedev_free;
 884        device_initialize(&mousedev->dev);
 885
 886        if (!mixdev) {
 887                error = input_register_handle(&mousedev->handle);
 888                if (error)
 889                        goto err_free_mousedev;
 890        }
 891
 892        cdev_init(&mousedev->cdev, &mousedev_fops);
 893        mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
 894        error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
 895        if (error)
 896                goto err_unregister_handle;
 897
 898        error = device_add(&mousedev->dev);
 899        if (error)
 900                goto err_cleanup_mousedev;
 901
 902        return mousedev;
 903
 904 err_cleanup_mousedev:
 905        mousedev_cleanup(mousedev);
 906 err_unregister_handle:
 907        if (!mixdev)
 908                input_unregister_handle(&mousedev->handle);
 909 err_free_mousedev:
 910        put_device(&mousedev->dev);
 911 err_free_minor:
 912        input_free_minor(minor);
 913 err_out:
 914        return ERR_PTR(error);
 915}
 916
 917static void mousedev_destroy(struct mousedev *mousedev)
 918{
 919        device_del(&mousedev->dev);
 920        mousedev_cleanup(mousedev);
 921        input_free_minor(MINOR(mousedev->dev.devt));
 922        if (!mousedev->is_mixdev)
 923                input_unregister_handle(&mousedev->handle);
 924        put_device(&mousedev->dev);
 925}
 926
 927static int mixdev_add_device(struct mousedev *mousedev)
 928{
 929        int retval;
 930
 931        retval = mutex_lock_interruptible(&mousedev_mix->mutex);
 932        if (retval)
 933                return retval;
 934
 935        if (mousedev_mix->open) {
 936                retval = mousedev_open_device(mousedev);
 937                if (retval)
 938                        goto out;
 939
 940                mousedev->opened_by_mixdev = true;
 941        }
 942
 943        get_device(&mousedev->dev);
 944        list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
 945
 946 out:
 947        mutex_unlock(&mousedev_mix->mutex);
 948        return retval;
 949}
 950
 951static void mixdev_remove_device(struct mousedev *mousedev)
 952{
 953        mutex_lock(&mousedev_mix->mutex);
 954
 955        if (mousedev->opened_by_mixdev) {
 956                mousedev->opened_by_mixdev = false;
 957                mousedev_close_device(mousedev);
 958        }
 959
 960        list_del_init(&mousedev->mixdev_node);
 961        mutex_unlock(&mousedev_mix->mutex);
 962
 963        put_device(&mousedev->dev);
 964}
 965
 966static int mousedev_connect(struct input_handler *handler,
 967                            struct input_dev *dev,
 968                            const struct input_device_id *id)
 969{
 970        struct mousedev *mousedev;
 971        int error;
 972
 973        mousedev = mousedev_create(dev, handler, false);
 974        if (IS_ERR(mousedev))
 975                return PTR_ERR(mousedev);
 976
 977        error = mixdev_add_device(mousedev);
 978        if (error) {
 979                mousedev_destroy(mousedev);
 980                return error;
 981        }
 982
 983        return 0;
 984}
 985
 986static void mousedev_disconnect(struct input_handle *handle)
 987{
 988        struct mousedev *mousedev = handle->private;
 989
 990        mixdev_remove_device(mousedev);
 991        mousedev_destroy(mousedev);
 992}
 993
 994static const struct input_device_id mousedev_ids[] = {
 995        {
 996                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 997                                INPUT_DEVICE_ID_MATCH_KEYBIT |
 998                                INPUT_DEVICE_ID_MATCH_RELBIT,
 999                .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
1000                .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
1001                .relbit = { BIT_MASK(REL_X) | BIT_MASK(REL_Y) },
1002        },      /* A mouse like device, at least one button,
1003                   two relative axes */
1004        {
1005                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
1006                                INPUT_DEVICE_ID_MATCH_RELBIT,
1007                .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
1008                .relbit = { BIT_MASK(REL_WHEEL) },
1009        },      /* A separate scrollwheel */
1010        {
1011                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
1012                                INPUT_DEVICE_ID_MATCH_KEYBIT |
1013                                INPUT_DEVICE_ID_MATCH_ABSBIT,
1014                .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
1015                .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
1016                .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
1017        },      /* A tablet like device, at least touch detection,
1018                   two absolute axes */
1019        {
1020                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
1021                                INPUT_DEVICE_ID_MATCH_KEYBIT |
1022                                INPUT_DEVICE_ID_MATCH_ABSBIT,
1023                .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
1024                .keybit = { [BIT_WORD(BTN_TOOL_FINGER)] =
1025                                BIT_MASK(BTN_TOOL_FINGER) },
1026                .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
1027                                BIT_MASK(ABS_PRESSURE) |
1028                                BIT_MASK(ABS_TOOL_WIDTH) },
1029        },      /* A touchpad */
1030        {
1031                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
1032                        INPUT_DEVICE_ID_MATCH_KEYBIT |
1033                        INPUT_DEVICE_ID_MATCH_ABSBIT,
1034                .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
1035                .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
1036                .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
1037        },      /* Mouse-like device with absolute X and Y but ordinary
1038                   clicks, like hp ILO2 High Performance mouse */
1039
1040        { },    /* Terminating entry */
1041};
1042
1043MODULE_DEVICE_TABLE(input, mousedev_ids);
1044
1045static struct input_handler mousedev_handler = {
1046        .event          = mousedev_event,
1047        .connect        = mousedev_connect,
1048        .disconnect     = mousedev_disconnect,
1049        .legacy_minors  = true,
1050        .minor          = MOUSEDEV_MINOR_BASE,
1051        .name           = "mousedev",
1052        .id_table       = mousedev_ids,
1053};
1054
1055#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
1056#include <linux/miscdevice.h>
1057
1058static struct miscdevice psaux_mouse = {
1059        .minor  = PSMOUSE_MINOR,
1060        .name   = "psaux",
1061        .fops   = &mousedev_fops,
1062};
1063
1064static bool psaux_registered;
1065
1066static void __init mousedev_psaux_register(void)
1067{
1068        int error;
1069
1070        error = misc_register(&psaux_mouse);
1071        if (error)
1072                pr_warn("could not register psaux device, error: %d\n",
1073                           error);
1074        else
1075                psaux_registered = true;
1076}
1077
1078static void __exit mousedev_psaux_unregister(void)
1079{
1080        if (psaux_registered)
1081                misc_deregister(&psaux_mouse);
1082}
1083#else
1084static inline void mousedev_psaux_register(void) { }
1085static inline void mousedev_psaux_unregister(void) { }
1086#endif
1087
1088static int __init mousedev_init(void)
1089{
1090        int error;
1091
1092        mousedev_mix = mousedev_create(NULL, &mousedev_handler, true);
1093        if (IS_ERR(mousedev_mix))
1094                return PTR_ERR(mousedev_mix);
1095
1096        error = input_register_handler(&mousedev_handler);
1097        if (error) {
1098                mousedev_destroy(mousedev_mix);
1099                return error;
1100        }
1101
1102        mousedev_psaux_register();
1103
1104        pr_info("PS/2 mouse device common for all mice\n");
1105
1106        return 0;
1107}
1108
1109static void __exit mousedev_exit(void)
1110{
1111        mousedev_psaux_unregister();
1112        input_unregister_handler(&mousedev_handler);
1113        mousedev_destroy(mousedev_mix);
1114}
1115
1116module_init(mousedev_init);
1117module_exit(mousedev_exit);
1118
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.