Root/drivers/input/mousedev.c

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

Archive Download this file



interactive