OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [mousedev.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.