]>
Commit | Line | Data |
---|---|---|
8422b624 | 1 | ChangeSet@1.1907, 2004-04-23 02:22:22-05:00, dtor_core@ameritech.net |
2 | ALPS driver | |
3 | ||
4 | Makefile | 2 | |
5 | alps.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
6 | alps.h | 17 +++++ | |
7 | psmouse-base.c | 19 +++++ | |
8 | psmouse.h | 3 | |
9 | 5 files changed, 224 insertions(+), 2 deletions(-) | |
10 | ||
11 | diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile | |
12 | --- a/drivers/input/mouse/Makefile Fri Apr 23 02:24:19 2004 | |
13 | +++ b/drivers/input/mouse/Makefile Fri Apr 23 02:24:19 2004 | |
14 | @@ -15,4 +15,4 @@ | |
15 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | |
16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | |
17 | ||
18 | -psmouse-objs := psmouse-base.o logips2pp.o synaptics.o | |
19 | +psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o | |
20 | diff -Nru a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c | |
21 | --- /dev/null Wed Dec 31 16:00:00 1969 | |
22 | +++ b/drivers/input/mouse/alps.c Fri Apr 23 02:24:19 2004 | |
23 | @@ -0,0 +1,185 @@ | |
24 | +/* | |
25 | + * ALPS touchpad PS/2 mouse driver | |
26 | + * | |
27 | + * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> | |
28 | + * Copyright (c) 2003 Peter Osterlund <petero2@telia.com> | |
29 | + * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | |
30 | + * | |
31 | + * This program is free software; you can redistribute it and/or modify it | |
32 | + * under the terms of the GNU General Public License version 2 as published by | |
33 | + * the Free Software Foundation. | |
34 | + */ | |
35 | + | |
36 | +#include <linux/input.h> | |
37 | +#include <linux/serio.h> | |
38 | + | |
39 | +#include "psmouse.h" | |
40 | +#include "alps.h" | |
41 | + | |
42 | +/* | |
43 | + * ALPS abolute Mode | |
44 | + * byte 0: 1 1 1 1 1 mid0 rig0 lef0 | |
45 | + * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | |
46 | + * byte 2: 0 x10 x9 x8 x7 up1 fin ges | |
47 | + * byte 3: 0 y9 y8 y7 1 mid1 rig1 lef1 | |
48 | + * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | |
49 | + * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | |
50 | + * | |
51 | + * On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad. | |
52 | + * We just 'or' them together for now. | |
53 | + * | |
54 | + * We used to send 'ges'tures as BTN_TOUCH but this made it impossible | |
55 | + * to disable tap events in the synaptics driver since the driver | |
56 | + * was unable to distinguish a gesture tap from an actual button click. | |
57 | + * A tap gesture now creates an emulated touch that the synaptics | |
58 | + * driver can interpret as a tap event, if MaxTapTime=0 and | |
59 | + * MaxTapMove=0 then the driver will ignore taps. | |
60 | + * | |
61 | + * The touchpad on an 'Acer Aspire' has 4 buttons: | |
62 | + * left,right,up,down. | |
63 | + * This device always sets {mid,rig,lef}0 to 1 and | |
64 | + * reflects left,right,down,up in lef1,rig1,mid1,up1. | |
65 | + */ | |
66 | + | |
67 | +static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |
68 | +{ | |
69 | + unsigned char *packet = psmouse->packet; | |
70 | + struct input_dev *dev = &psmouse->dev; | |
71 | + int x, y, z; | |
72 | + int left = 0, right = 0, middle = 0; | |
73 | + | |
74 | + input_regs(dev, regs); | |
75 | + | |
76 | + x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3)); | |
77 | + y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4)); | |
78 | + z = packet[5]; | |
79 | + | |
80 | + if (z > 30) input_report_key(dev, BTN_TOUCH, 1); | |
81 | + if (z < 25) input_report_key(dev, BTN_TOUCH, 0); | |
82 | + | |
83 | + if (z > 0) { | |
84 | + input_report_abs(dev, ABS_X, x); | |
85 | + input_report_abs(dev, ABS_Y, y); | |
86 | + } | |
87 | + input_report_abs(dev, ABS_PRESSURE, z); | |
88 | + input_report_key(dev, BTN_TOOL_FINGER, z > 0); | |
89 | + | |
90 | + left |= (packet[2] ) & 1; | |
91 | + left |= (packet[3] ) & 1; | |
92 | + right |= (packet[3] >> 1) & 1; | |
93 | + if (packet[0] == 0xff) { | |
94 | + int back = (packet[3] >> 2) & 1; | |
95 | + int forward = (packet[2] >> 2) & 1; | |
96 | + if (back && forward) { | |
97 | + middle = 1; | |
98 | + back = 0; | |
99 | + forward = 0; | |
100 | + } | |
101 | + input_report_key(dev, BTN_BACK, back); | |
102 | + input_report_key(dev, BTN_FORWARD, forward); | |
103 | + } else { | |
104 | + left |= (packet[0] ) & 1; | |
105 | + right |= (packet[0] >> 1) & 1; | |
106 | + middle |= (packet[0] >> 2) & 1; | |
107 | + middle |= (packet[3] >> 2) & 1; | |
108 | + } | |
109 | + | |
110 | + input_report_key(dev, BTN_LEFT, left); | |
111 | + input_report_key(dev, BTN_RIGHT, right); | |
112 | + input_report_key(dev, BTN_MIDDLE, middle); | |
113 | + | |
114 | + input_sync(dev); | |
115 | +} | |
116 | + | |
117 | +static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs) | |
118 | +{ | |
119 | + /* ALPS absolute mode packets start with 0b11111mrl */ | |
120 | + if ((psmouse->packet[0] & 0xf8) != 0xf8) | |
121 | + return PSMOUSE_BAD_DATA; | |
122 | + | |
123 | + /* Bytes 2 - 6 should have 0 in the highest bit */ | |
124 | + if (psmouse->pktcnt > 1 && psmouse->pktcnt <= 6 && | |
125 | + (psmouse->packet[psmouse->pktcnt] & 0x80)) | |
126 | + return PSMOUSE_BAD_DATA; | |
127 | + | |
128 | + if (psmouse->pktcnt == 6) { | |
129 | + alps_process_packet(psmouse, regs); | |
130 | + return PSMOUSE_FULL_PACKET; | |
131 | + } | |
132 | + | |
133 | + return PSMOUSE_GOOD_DATA; | |
134 | +} | |
135 | + | |
136 | +int alps_detect(struct psmouse *psmouse) | |
137 | +{ | |
138 | + unsigned char param[4]; | |
139 | + | |
140 | + /* First try "E6 report". ALPS should return 0x00 0x00 0x0a */ | |
141 | + param[0] = 0; | |
142 | + if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES) || | |
143 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11) || | |
144 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11) || | |
145 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) | |
146 | + return 0; | |
147 | + | |
148 | + param[0] = param[1] = param[2] = 0xff; | |
149 | + if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO)) | |
150 | + return 0; | |
151 | + | |
152 | + printk(KERN_INFO "alps.c: E6 report: %2.2x %2.2x %2.2x\n", | |
153 | + param[0], param[1], param[2]); | |
154 | + | |
155 | + if (param[0] != 0x00 || param[1] != 0x00 || param[2] != 0x0a) | |
156 | + return 0; | |
157 | + | |
158 | + /* Now try "E7 report". ALPS should return 0x33 in byte 1 */ | |
159 | + param[0] = 0; | |
160 | + if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES) || | |
161 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21) || | |
162 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21) || | |
163 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE21)) | |
164 | + return 0; | |
165 | + | |
166 | + param[0] = param[1] = param[2] = 0xff; | |
167 | + if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO)) | |
168 | + return 0; | |
169 | + | |
170 | + printk(KERN_INFO "alps.c: E7 report: %2.2x %2.2x %2.2x\n", | |
171 | + param[0], param[1], param[2]); | |
172 | + | |
173 | + return param[0] != 0x33; | |
174 | +} | |
175 | + | |
176 | +static void alps_disconnect(struct psmouse *psmouse) | |
177 | +{ | |
178 | + psmouse_reset(psmouse); | |
179 | +} | |
180 | + | |
181 | +int alps_init(struct psmouse *psmouse) | |
182 | +{ | |
183 | + /* Try ALPS magic knock */ | |
184 | + if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) || | |
185 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) || | |
186 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE) || | |
187 | + psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE)) | |
188 | + return -1; | |
189 | + | |
190 | + psmouse->dev.evbit[LONG(EV_REL)] &= ~BIT(EV_REL); | |
191 | + psmouse->dev.relbit[LONG(REL_X)] &= ~BIT(REL_X); | |
192 | + psmouse->dev.relbit[LONG(REL_X)] &= ~BIT(REL_X); | |
193 | + | |
194 | + psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS); | |
195 | + input_set_abs_params(&psmouse->dev, ABS_X, 0, 0, 0, 0); | |
196 | + input_set_abs_params(&psmouse->dev, ABS_Y, 0, 0, 0, 0); | |
197 | + input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0); | |
198 | + | |
199 | + psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); | |
200 | + psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER); | |
201 | + psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); | |
202 | + psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); | |
203 | + | |
204 | + psmouse->protocol_handler = alps_process_byte; | |
205 | + psmouse->disconnect = alps_disconnect; | |
206 | + | |
207 | + return 0; | |
208 | +} | |
209 | diff -Nru a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h | |
210 | --- /dev/null Wed Dec 31 16:00:00 1969 | |
211 | +++ b/drivers/input/mouse/alps.h Fri Apr 23 02:24:19 2004 | |
212 | @@ -0,0 +1,17 @@ | |
213 | +/* | |
214 | + * ALPS touchpad PS/2 mouse driver | |
215 | + * | |
216 | + * Copyright (c) 2003 Peter Osterlund <petero2@telia.com> | |
217 | + * | |
218 | + * This program is free software; you can redistribute it and/or modify it | |
219 | + * under the terms of the GNU General Public License version 2 as published by | |
220 | + * the Free Software Foundation. | |
221 | + */ | |
222 | + | |
223 | +#ifndef _ALPS_H | |
224 | +#define _ALPS_H | |
225 | + | |
226 | +int alps_detect(struct psmouse *psmouse); | |
227 | +int alps_init(struct psmouse *psmouse); | |
228 | + | |
229 | +#endif | |
230 | diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c | |
231 | --- a/drivers/input/mouse/psmouse-base.c Fri Apr 23 02:24:19 2004 | |
232 | +++ b/drivers/input/mouse/psmouse-base.c Fri Apr 23 02:24:19 2004 | |
233 | @@ -2,6 +2,7 @@ | |
234 | * PS/2 mouse driver | |
235 | * | |
236 | * Copyright (c) 1999-2002 Vojtech Pavlik | |
237 | + * Copyright (c) 2003-2004 Dmitry Torokhov | |
238 | */ | |
239 | ||
240 | /* | |
241 | @@ -21,6 +22,7 @@ | |
242 | #include "psmouse.h" | |
243 | #include "synaptics.h" | |
244 | #include "logips2pp.h" | |
245 | +#include "alps.h" | |
246 | ||
247 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |
248 | MODULE_DESCRIPTION("PS/2 mouse driver"); | |
249 | @@ -53,7 +55,7 @@ | |
250 | __obsolete_setup("psmouse_resetafter="); | |
251 | __obsolete_setup("psmouse_rate="); | |
252 | ||
253 | -static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"}; | |
254 | +static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; | |
255 | ||
256 | /* | |
257 | * psmouse_process_byte() analyzes the PS/2 data stream and reports | |
258 | @@ -440,6 +442,21 @@ | |
259 | * Make sure that touchpad is in relative mode, gestures (taps) are enabled | |
260 | */ | |
261 | synaptics_reset(psmouse); | |
262 | + } | |
263 | + | |
264 | +/* | |
265 | + * Try ALPS TouchPad | |
266 | + */ | |
267 | + if (max_proto > PSMOUSE_PS2 && alps_detect(psmouse)) { | |
268 | + | |
269 | + if (set_properties) { | |
270 | + psmouse->vendor = "ALPS"; | |
271 | + psmouse->name = "TouchPad"; | |
272 | + } | |
273 | + | |
274 | + if (max_proto > PSMOUSE_IMEX) | |
275 | + if (alps_detect(psmouse) == 0) | |
276 | + return PSMOUSE_ALPS; | |
277 | } | |
278 | ||
279 | if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { | |
280 | diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h | |
281 | --- a/drivers/input/mouse/psmouse.h Fri Apr 23 02:24:19 2004 | |
282 | +++ b/drivers/input/mouse/psmouse.h Fri Apr 23 02:24:19 2004 | |
283 | @@ -2,6 +2,7 @@ | |
284 | #define _PSMOUSE_H | |
285 | ||
286 | #define PSMOUSE_CMD_SETSCALE11 0x00e6 | |
287 | +#define PSMOUSE_CMD_SETSCALE21 0x00e7 | |
288 | #define PSMOUSE_CMD_SETRES 0x10e8 | |
289 | #define PSMOUSE_CMD_GETINFO 0x03e9 | |
290 | #define PSMOUSE_CMD_SETSTREAM 0x00ea | |
291 | @@ -9,6 +10,7 @@ | |
292 | #define PSMOUSE_CMD_GETID 0x02f2 | |
293 | #define PSMOUSE_CMD_SETRATE 0x10f3 | |
294 | #define PSMOUSE_CMD_ENABLE 0x00f4 | |
295 | +#define PSMOUSE_CMD_DISABLE 0x00f5 | |
296 | #define PSMOUSE_CMD_RESET_DIS 0x00f6 | |
297 | #define PSMOUSE_CMD_RESET_BAT 0x02ff | |
298 | ||
299 | @@ -72,6 +74,7 @@ | |
300 | #define PSMOUSE_IMPS 5 | |
301 | #define PSMOUSE_IMEX 6 | |
302 | #define PSMOUSE_SYNAPTICS 7 | |
303 | +#define PSMOUSE_ALPS 8 | |
304 | ||
305 | int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); | |
306 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | |
307 | - | |
308 | To unsubscribe from this list: send the line "unsubscribe linux-kernel" in | |
309 | the body of a message to majordomo@vger.kernel.org | |
310 | More majordomo info at http://vger.kernel.org/majordomo-info.html | |
311 | Please read the FAQ at http://www.tux.org/lkml/ | |
312 |