diff options
Diffstat (limited to 'drivers/input/mouse/rpcmouse.c')
-rw-r--r-- | drivers/input/mouse/rpcmouse.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c new file mode 100644 index 000000000000..7280f68afcee --- /dev/null +++ b/drivers/input/mouse/rpcmouse.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Acorn RiscPC mouse driver for Linux/ARM | ||
3 | * | ||
4 | * Copyright (c) 2000-2002 Vojtech Pavlik | ||
5 | * Copyright (C) 1996-2002 Russell King | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published by | ||
12 | * the Free Software Foundation. | ||
13 | * | ||
14 | * This handles the Acorn RiscPCs mouse. We basically have a couple of | ||
15 | * hardware registers that track the sensor count for the X-Y movement and | ||
16 | * another register holding the button state. On every VSYNC interrupt we read | ||
17 | * the complete state and then work out if something has changed. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/ptrace.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/input.h> | ||
26 | |||
27 | #include <asm/hardware.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/hardware/iomd.h> | ||
31 | |||
32 | MODULE_AUTHOR("Vojtech Pavlik, Russell King"); | ||
33 | MODULE_DESCRIPTION("Acorn RiscPC mouse driver"); | ||
34 | MODULE_LICENSE("GPL"); | ||
35 | |||
36 | static short rpcmouse_lastx, rpcmouse_lasty; | ||
37 | |||
38 | static struct input_dev rpcmouse_dev = { | ||
39 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | ||
40 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) }, | ||
41 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, | ||
42 | .name = "Acorn RiscPC Mouse", | ||
43 | .phys = "rpcmouse/input0", | ||
44 | .id = { | ||
45 | .bustype = BUS_HOST, | ||
46 | .vendor = 0x0005, | ||
47 | .product = 0x0001, | ||
48 | .version = 0x0100, | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
53 | { | ||
54 | struct input_dev *dev = dev_id; | ||
55 | short x, y, dx, dy, b; | ||
56 | |||
57 | x = (short) iomd_readl(IOMD_MOUSEX); | ||
58 | y = (short) iomd_readl(IOMD_MOUSEY); | ||
59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); | ||
60 | |||
61 | dx = x - rpcmouse_lastx; | ||
62 | dy = y - rpcmouse_lasty; | ||
63 | |||
64 | rpcmouse_lastx = x; | ||
65 | rpcmouse_lasty = y; | ||
66 | |||
67 | input_regs(dev, regs); | ||
68 | |||
69 | input_report_rel(dev, REL_X, dx); | ||
70 | input_report_rel(dev, REL_Y, -dy); | ||
71 | |||
72 | input_report_key(dev, BTN_LEFT, b & 0x40); | ||
73 | input_report_key(dev, BTN_MIDDLE, b & 0x20); | ||
74 | input_report_key(dev, BTN_RIGHT, b & 0x10); | ||
75 | |||
76 | input_sync(dev); | ||
77 | |||
78 | return IRQ_HANDLED; | ||
79 | } | ||
80 | |||
81 | static int __init rpcmouse_init(void) | ||
82 | { | ||
83 | init_input_dev(&rpcmouse_dev); | ||
84 | |||
85 | rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX); | ||
86 | rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY); | ||
87 | |||
88 | if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) { | ||
89 | printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); | ||
90 | return -1; | ||
91 | } | ||
92 | |||
93 | input_register_device(&rpcmouse_dev); | ||
94 | |||
95 | printk(KERN_INFO "input: Acorn RiscPC mouse\n"); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void __exit rpcmouse_exit(void) | ||
101 | { | ||
102 | input_unregister_device(&rpcmouse_dev); | ||
103 | free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev); | ||
104 | } | ||
105 | |||
106 | module_init(rpcmouse_init); | ||
107 | module_exit(rpcmouse_exit); | ||