~ubuntu-branches/debian/lenny/wacom-tools/lenny

« back to all changes in this revision

Viewing changes to linuxwacom/src/2.6.10/mousedev.c

  • Committer: Bazaar Package Importer
  • Author(s): Ron Lee
  • Date: 2004-12-10 16:12:07 UTC
  • Revision ID: james.westby@ubuntu.com-20041210161207-cw8urijtjsqvk2e3
Tags: upstream-0.6.6
ImportĀ upstreamĀ versionĀ 0.6.6

Show diffs side-by-side

added added

removed removed

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