Branch data Line data Source code
1 : : /*
2 : : * ALPS touchpad PS/2 mouse driver
3 : : *
4 : : * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
5 : : * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
6 : : * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
7 : : * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
8 : : * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
9 : : *
10 : : * ALPS detection, tap switching and status querying info is taken from
11 : : * tpconfig utility (by C. Scott Ananian and Bruce Kall).
12 : : *
13 : : * This program is free software; you can redistribute it and/or modify it
14 : : * under the terms of the GNU General Public License version 2 as published by
15 : : * the Free Software Foundation.
16 : : */
17 : :
18 : : #include <linux/slab.h>
19 : : #include <linux/input.h>
20 : : #include <linux/input/mt.h>
21 : : #include <linux/serio.h>
22 : : #include <linux/libps2.h>
23 : :
24 : : #include "psmouse.h"
25 : : #include "alps.h"
26 : :
27 : : /*
28 : : * Definitions for ALPS version 3 and 4 command mode protocol
29 : : */
30 : : #define ALPS_CMD_NIBBLE_10 0x01f2
31 : :
32 : : #define ALPS_REG_BASE_RUSHMORE 0xc2c0
33 : : #define ALPS_REG_BASE_PINNACLE 0x0000
34 : :
35 : : static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
36 : : { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */
37 : : { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
38 : : { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
39 : : { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
40 : : { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
41 : : { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
42 : : { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
43 : : { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
44 : : { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
45 : : { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
46 : : { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
47 : : { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
48 : : { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
49 : : { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
50 : : { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
51 : : { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
52 : : };
53 : :
54 : : static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
55 : : { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
56 : : { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
57 : : { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
58 : : { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
59 : : { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
60 : : { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
61 : : { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
62 : : { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
63 : : { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
64 : : { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
65 : : { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
66 : : { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
67 : : { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
68 : : { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
69 : : { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
70 : : { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
71 : : };
72 : :
73 : : static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
74 : : { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
75 : : { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */
76 : : { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */
77 : : { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */
78 : : { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */
79 : : { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */
80 : : { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */
81 : : { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */
82 : : { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */
83 : : { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */
84 : : { PSMOUSE_CMD_SETRES, 0x00 }, /* a */
85 : : { PSMOUSE_CMD_SETRES, 0x01 }, /* b */
86 : : { PSMOUSE_CMD_SETRES, 0x02 }, /* c */
87 : : { PSMOUSE_CMD_SETRES, 0x03 }, /* d */
88 : : { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */
89 : : { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
90 : : };
91 : :
92 : :
93 : : #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
94 : : #define ALPS_PASS 0x04 /* device has a pass-through port */
95 : :
96 : : #define ALPS_WHEEL 0x08 /* hardware wheel present */
97 : : #define ALPS_FW_BK_1 0x10 /* front & back buttons present */
98 : : #define ALPS_FW_BK_2 0x20 /* front & back buttons present */
99 : : #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
100 : : #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
101 : : 6-byte ALPS packet */
102 : :
103 : : static const struct alps_model_info alps_model_data[] = {
104 : : { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
105 : : { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */
106 : : { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
107 : : { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
108 : : { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */
109 : : { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
110 : : { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
111 : : { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
112 : : { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
113 : : { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
114 : : { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
115 : : { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */
116 : : { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */
117 : : { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 },
118 : : { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
119 : : { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
120 : : { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
121 : : { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
122 : : /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
123 : : { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf,
124 : : ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
125 : : { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT }, /* Dell XT2 */
126 : : { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */
127 : : { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff,
128 : : ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */
129 : : { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 },
130 : : };
131 : :
132 : : static void alps_set_abs_params_st(struct alps_data *priv,
133 : : struct input_dev *dev1);
134 : : static void alps_set_abs_params_mt(struct alps_data *priv,
135 : : struct input_dev *dev1);
136 : :
137 : : /*
138 : : * XXX - this entry is suspicious. First byte has zero lower nibble,
139 : : * which is what a normal mouse would report. Also, the value 0x0e
140 : : * isn't valid per PS/2 spec.
141 : : */
142 : :
143 : : /* Packet formats are described in Documentation/input/alps.txt */
144 : :
145 : : static bool alps_is_valid_first_byte(struct alps_data *priv,
146 : : unsigned char data)
147 : : {
148 : 0 : return (data & priv->mask0) == priv->byte0;
149 : : }
150 : :
151 : 0 : static void alps_report_buttons(struct psmouse *psmouse,
152 : : struct input_dev *dev1, struct input_dev *dev2,
153 : : int left, int right, int middle)
154 : : {
155 : : struct input_dev *dev;
156 : :
157 : : /*
158 : : * If shared button has already been reported on the
159 : : * other device (dev2) then this event should be also
160 : : * sent through that device.
161 : : */
162 [ # # ]: 0 : dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1;
163 : : input_report_key(dev, BTN_LEFT, left);
164 : :
165 [ # # ]: 0 : dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1;
166 : : input_report_key(dev, BTN_RIGHT, right);
167 : :
168 [ # # ]: 0 : dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1;
169 : : input_report_key(dev, BTN_MIDDLE, middle);
170 : :
171 : : /*
172 : : * Sync the _other_ device now, we'll do the first
173 : : * device later once we report the rest of the events.
174 : : */
175 : : input_sync(dev2);
176 : 0 : }
177 : :
178 : 0 : static void alps_process_packet_v1_v2(struct psmouse *psmouse)
179 : : {
180 : 0 : struct alps_data *priv = psmouse->private;
181 : : unsigned char *packet = psmouse->packet;
182 : 0 : struct input_dev *dev = psmouse->dev;
183 : 0 : struct input_dev *dev2 = priv->dev2;
184 : : int x, y, z, ges, fin, left, right, middle;
185 : : int back = 0, forward = 0;
186 : :
187 [ # # ]: 0 : if (priv->proto_version == ALPS_PROTO_V1) {
188 : 0 : left = packet[2] & 0x10;
189 : 0 : right = packet[2] & 0x08;
190 : : middle = 0;
191 : 0 : x = packet[1] | ((packet[0] & 0x07) << 7);
192 : 0 : y = packet[4] | ((packet[3] & 0x07) << 7);
193 : 0 : z = packet[5];
194 : : } else {
195 : 0 : left = packet[3] & 1;
196 : 0 : right = packet[3] & 2;
197 : 0 : middle = packet[3] & 4;
198 : 0 : x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
199 : 0 : y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
200 : 0 : z = packet[5];
201 : : }
202 : :
203 [ # # ]: 0 : if (priv->flags & ALPS_FW_BK_1) {
204 : 0 : back = packet[0] & 0x10;
205 : 0 : forward = packet[2] & 4;
206 : : }
207 : :
208 [ # # ]: 0 : if (priv->flags & ALPS_FW_BK_2) {
209 : 0 : back = packet[3] & 4;
210 : 0 : forward = packet[2] & 4;
211 [ # # ]: 0 : if ((middle = forward && back))
212 : : forward = back = 0;
213 : : }
214 : :
215 : 0 : ges = packet[2] & 1;
216 : 0 : fin = packet[2] & 2;
217 : :
218 [ # # ][ # # ]: 0 : if ((priv->flags & ALPS_DUALPOINT) && z == 127) {
219 [ # # ]: 0 : input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
220 [ # # ]: 0 : input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
221 : :
222 : 0 : alps_report_buttons(psmouse, dev2, dev, left, right, middle);
223 : :
224 : : input_sync(dev2);
225 : 0 : return;
226 : : }
227 : :
228 : 0 : alps_report_buttons(psmouse, dev, dev2, left, right, middle);
229 : :
230 : : /* Convert hardware tap to a reasonable Z value */
231 [ # # ]: 0 : if (ges && !fin)
232 : : z = 40;
233 : :
234 : : /*
235 : : * A "tap and drag" operation is reported by the hardware as a transition
236 : : * from (!fin && ges) to (fin && ges). This should be translated to the
237 : : * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
238 : : */
239 [ # # ][ # # ]: 0 : if (ges && fin && !priv->prev_fin) {
240 : : input_report_abs(dev, ABS_X, x);
241 : : input_report_abs(dev, ABS_Y, y);
242 : : input_report_abs(dev, ABS_PRESSURE, 0);
243 : : input_report_key(dev, BTN_TOOL_FINGER, 0);
244 : : input_sync(dev);
245 : : }
246 : 0 : priv->prev_fin = fin;
247 : :
248 [ # # ]: 0 : if (z > 30)
249 : : input_report_key(dev, BTN_TOUCH, 1);
250 [ # # ]: 0 : if (z < 25)
251 : : input_report_key(dev, BTN_TOUCH, 0);
252 : :
253 [ # # ]: 0 : if (z > 0) {
254 : : input_report_abs(dev, ABS_X, x);
255 : : input_report_abs(dev, ABS_Y, y);
256 : : }
257 : :
258 : : input_report_abs(dev, ABS_PRESSURE, z);
259 : 0 : input_report_key(dev, BTN_TOOL_FINGER, z > 0);
260 : :
261 [ # # ]: 0 : if (priv->flags & ALPS_WHEEL)
262 : 0 : input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
263 : :
264 [ # # ]: 0 : if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
265 : : input_report_key(dev, BTN_FORWARD, forward);
266 : : input_report_key(dev, BTN_BACK, back);
267 : : }
268 : :
269 [ # # ]: 0 : if (priv->flags & ALPS_FOUR_BUTTONS) {
270 : 0 : input_report_key(dev, BTN_0, packet[2] & 4);
271 : 0 : input_report_key(dev, BTN_1, packet[0] & 0x10);
272 : 0 : input_report_key(dev, BTN_2, packet[3] & 4);
273 : 0 : input_report_key(dev, BTN_3, packet[0] & 0x20);
274 : : }
275 : :
276 : : input_sync(dev);
277 : : }
278 : :
279 : : /*
280 : : * Process bitmap data for V5 protocols. Return value is null.
281 : : *
282 : : * The bitmaps don't have enough data to track fingers, so this function
283 : : * only generates points representing a bounding box of at most two contacts.
284 : : * These two points are returned in x1, y1, x2, and y2.
285 : : */
286 : 0 : static void alps_process_bitmap_dolphin(struct alps_data *priv,
287 : : struct alps_fields *fields,
288 : : int *x1, int *y1, int *x2, int *y2)
289 : : {
290 : : int box_middle_x, box_middle_y;
291 : : unsigned int x_map, y_map;
292 : : unsigned char start_bit, end_bit;
293 : : unsigned char x_msb, x_lsb, y_msb, y_lsb;
294 : :
295 : 0 : x_map = fields->x_map;
296 : 0 : y_map = fields->y_map;
297 : :
298 [ # # ]: 0 : if (!x_map || !y_map)
299 : : return;
300 : :
301 : : /* Get Most-significant and Least-significant bit */
302 : 0 : x_msb = fls(x_map);
303 : 0 : x_lsb = ffs(x_map);
304 : 0 : y_msb = fls(y_map);
305 : 0 : y_lsb = ffs(y_map);
306 : :
307 : : /* Most-significant bit should never exceed max sensor line number */
308 [ # # ][ # # ]: 0 : if (x_msb > priv->x_bits || y_msb > priv->y_bits)
309 : : return;
310 : :
311 : 0 : *x1 = *y1 = *x2 = *y2 = 0;
312 : :
313 [ # # ]: 0 : if (fields->fingers > 1) {
314 : 0 : start_bit = priv->x_bits - x_msb;
315 : 0 : end_bit = priv->x_bits - x_lsb;
316 : 0 : box_middle_x = (priv->x_max * (start_bit + end_bit)) /
317 : 0 : (2 * (priv->x_bits - 1));
318 : :
319 : 0 : start_bit = y_lsb - 1;
320 : 0 : end_bit = y_msb - 1;
321 : 0 : box_middle_y = (priv->y_max * (start_bit + end_bit)) /
322 : 0 : (2 * (priv->y_bits - 1));
323 : 0 : *x1 = fields->x;
324 : 0 : *y1 = fields->y;
325 : 0 : *x2 = 2 * box_middle_x - *x1;
326 : 0 : *y2 = 2 * box_middle_y - *y1;
327 : : }
328 : : }
329 : :
330 : : /*
331 : : * Process bitmap data from v3 and v4 protocols. Returns the number of
332 : : * fingers detected. A return value of 0 means at least one of the
333 : : * bitmaps was empty.
334 : : *
335 : : * The bitmaps don't have enough data to track fingers, so this function
336 : : * only generates points representing a bounding box of all contacts.
337 : : * These points are returned in x1, y1, x2, and y2 when the return value
338 : : * is greater than 0.
339 : : */
340 : 0 : static int alps_process_bitmap(struct alps_data *priv,
341 : : unsigned int x_map, unsigned int y_map,
342 : : int *x1, int *y1, int *x2, int *y2)
343 : : {
344 : : struct alps_bitmap_point {
345 : : int start_bit;
346 : : int num_bits;
347 : : };
348 : :
349 : : int fingers_x = 0, fingers_y = 0, fingers;
350 : : int i, bit, prev_bit;
351 : 0 : struct alps_bitmap_point x_low = {0,}, x_high = {0,};
352 : 0 : struct alps_bitmap_point y_low = {0,}, y_high = {0,};
353 : : struct alps_bitmap_point *point;
354 : :
355 [ # # ]: 0 : if (!x_map || !y_map)
356 : : return 0;
357 : :
358 : 0 : *x1 = *y1 = *x2 = *y2 = 0;
359 : :
360 : : prev_bit = 0;
361 : : point = &x_low;
362 [ # # ]: 0 : for (i = 0; x_map != 0; i++, x_map >>= 1) {
363 : 0 : bit = x_map & 1;
364 [ # # ]: 0 : if (bit) {
365 [ # # ]: 0 : if (!prev_bit) {
366 : 0 : point->start_bit = i;
367 : 0 : fingers_x++;
368 : : }
369 : 0 : point->num_bits++;
370 : : } else {
371 [ # # ]: 0 : if (prev_bit)
372 : : point = &x_high;
373 : : else
374 : 0 : point->num_bits = 0;
375 : : }
376 : : prev_bit = bit;
377 : : }
378 : :
379 : : /*
380 : : * y bitmap is reversed for what we need (lower positions are in
381 : : * higher bits), so we process from the top end.
382 : : */
383 : 0 : y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits);
384 : : prev_bit = 0;
385 : : point = &y_low;
386 [ # # ]: 0 : for (i = 0; y_map != 0; i++, y_map <<= 1) {
387 : 0 : bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1));
388 [ # # ]: 0 : if (bit) {
389 [ # # ]: 0 : if (!prev_bit) {
390 : 0 : point->start_bit = i;
391 : 0 : fingers_y++;
392 : : }
393 : 0 : point->num_bits++;
394 : : } else {
395 [ # # ]: 0 : if (prev_bit)
396 : : point = &y_high;
397 : : else
398 : 0 : point->num_bits = 0;
399 : : }
400 : : prev_bit = bit;
401 : : }
402 : :
403 : : /*
404 : : * Fingers can overlap, so we use the maximum count of fingers
405 : : * on either axis as the finger count.
406 : : */
407 : 0 : fingers = max(fingers_x, fingers_y);
408 : :
409 : : /*
410 : : * If total fingers is > 1 but either axis reports only a single
411 : : * contact, we have overlapping or adjacent fingers. For the
412 : : * purposes of creating a bounding box, divide the single contact
413 : : * (roughly) equally between the two points.
414 : : */
415 [ # # ]: 0 : if (fingers > 1) {
416 [ # # ]: 0 : if (fingers_x == 1) {
417 : 0 : i = x_low.num_bits / 2;
418 : 0 : x_low.num_bits = x_low.num_bits - i;
419 : 0 : x_high.start_bit = x_low.start_bit + i;
420 : 0 : x_high.num_bits = max(i, 1);
421 [ # # ]: 0 : } else if (fingers_y == 1) {
422 : 0 : i = y_low.num_bits / 2;
423 : 0 : y_low.num_bits = y_low.num_bits - i;
424 : 0 : y_high.start_bit = y_low.start_bit + i;
425 : 0 : y_high.num_bits = max(i, 1);
426 : : }
427 : : }
428 : :
429 : 0 : *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
430 : 0 : (2 * (priv->x_bits - 1));
431 : 0 : *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
432 : 0 : (2 * (priv->y_bits - 1));
433 : :
434 [ # # ]: 0 : if (fingers > 1) {
435 : 0 : *x2 = (priv->x_max *
436 : 0 : (2 * x_high.start_bit + x_high.num_bits - 1)) /
437 : 0 : (2 * (priv->x_bits - 1));
438 : 0 : *y2 = (priv->y_max *
439 : 0 : (2 * y_high.start_bit + y_high.num_bits - 1)) /
440 : 0 : (2 * (priv->y_bits - 1));
441 : : }
442 : :
443 : 0 : return fingers;
444 : : }
445 : :
446 : 0 : static void alps_set_slot(struct input_dev *dev, int slot, bool active,
447 : : int x, int y)
448 : : {
449 : : input_mt_slot(dev, slot);
450 : 0 : input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
451 [ # # ]: 0 : if (active) {
452 : : input_report_abs(dev, ABS_MT_POSITION_X, x);
453 : : input_report_abs(dev, ABS_MT_POSITION_Y, y);
454 : : }
455 : 0 : }
456 : :
457 : 0 : static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers,
458 : : int x1, int y1, int x2, int y2)
459 : : {
460 : 0 : alps_set_slot(dev, 0, num_fingers != 0, x1, y1);
461 : 0 : alps_set_slot(dev, 1, num_fingers == 2, x2, y2);
462 : 0 : }
463 : :
464 : 0 : static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
465 : : {
466 : 0 : struct alps_data *priv = psmouse->private;
467 : : unsigned char *packet = psmouse->packet;
468 : 0 : struct input_dev *dev = priv->dev2;
469 : : int x, y, z, left, right, middle;
470 : :
471 : : /* Sanity check packet */
472 [ # # ]: 0 : if (!(packet[0] & 0x40)) {
473 : : psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n");
474 : : return;
475 : : }
476 : :
477 : : /*
478 : : * There's a special packet that seems to indicate the end
479 : : * of a stream of trackstick data. Filter these out.
480 : : */
481 [ # # ][ # # ]: 0 : if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f)
[ # # ]
482 : : return;
483 : :
484 : 0 : x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
485 : 0 : y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
486 : : z = (packet[4] & 0x7c) >> 2;
487 : :
488 : : /*
489 : : * The x and y values tend to be quite large, and when used
490 : : * alone the trackstick is difficult to use. Scale them down
491 : : * to compensate.
492 : : */
493 : 0 : x /= 8;
494 : 0 : y /= 8;
495 : :
496 : : input_report_rel(dev, REL_X, x);
497 : 0 : input_report_rel(dev, REL_Y, -y);
498 : :
499 : : /*
500 : : * Most ALPS models report the trackstick buttons in the touchpad
501 : : * packets, but a few report them here. No reliable way has been
502 : : * found to differentiate between the models upfront, so we enable
503 : : * the quirk in response to seeing a button press in the trackstick
504 : : * packet.
505 : : */
506 : 0 : left = packet[3] & 0x01;
507 : 0 : right = packet[3] & 0x02;
508 : 0 : middle = packet[3] & 0x04;
509 : :
510 [ # # ][ # # ]: 0 : if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) &&
511 : 0 : (left || right || middle))
512 : 0 : priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS;
513 : :
514 [ # # ]: 0 : if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) {
515 : : input_report_key(dev, BTN_LEFT, left);
516 : : input_report_key(dev, BTN_RIGHT, right);
517 : : input_report_key(dev, BTN_MIDDLE, middle);
518 : : }
519 : :
520 : : input_sync(dev);
521 : : return;
522 : : }
523 : :
524 : 0 : static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
525 : : {
526 : 0 : f->left = !!(p[3] & 0x01);
527 : 0 : f->right = !!(p[3] & 0x02);
528 : 0 : f->middle = !!(p[3] & 0x04);
529 : :
530 : 0 : f->ts_left = !!(p[3] & 0x10);
531 : 0 : f->ts_right = !!(p[3] & 0x20);
532 : 0 : f->ts_middle = !!(p[3] & 0x40);
533 : 0 : }
534 : :
535 : 0 : static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
536 : : struct psmouse *psmouse)
537 : : {
538 : 0 : f->first_mp = !!(p[4] & 0x40);
539 : 0 : f->is_mp = !!(p[0] & 0x40);
540 : :
541 : 0 : f->fingers = (p[5] & 0x3) + 1;
542 : 0 : f->x_map = ((p[4] & 0x7e) << 8) |
543 : 0 : ((p[1] & 0x7f) << 2) |
544 : 0 : ((p[0] & 0x30) >> 4);
545 : 0 : f->y_map = ((p[3] & 0x70) << 4) |
546 : 0 : ((p[2] & 0x7f) << 1) |
547 : 0 : (p[4] & 0x01);
548 : :
549 : 0 : f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
550 : 0 : ((p[0] & 0x30) >> 4);
551 : 0 : f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
552 : 0 : f->z = p[5] & 0x7f;
553 : :
554 : 0 : alps_decode_buttons_v3(f, p);
555 : 0 : }
556 : :
557 : 0 : static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
558 : : struct psmouse *psmouse)
559 : : {
560 : 0 : alps_decode_pinnacle(f, p, psmouse);
561 : :
562 : 0 : f->x_map |= (p[5] & 0x10) << 11;
563 : 0 : f->y_map |= (p[5] & 0x20) << 6;
564 : 0 : }
565 : :
566 : 0 : static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
567 : : struct psmouse *psmouse)
568 : : {
569 : : u64 palm_data = 0;
570 : 0 : struct alps_data *priv = psmouse->private;
571 : :
572 : 0 : f->first_mp = !!(p[0] & 0x02);
573 : 0 : f->is_mp = !!(p[0] & 0x20);
574 : :
575 [ # # ]: 0 : if (!f->is_mp) {
576 : 0 : f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
577 : 0 : f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
578 [ # # ]: 0 : f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
579 : 0 : alps_decode_buttons_v3(f, p);
580 : : } else {
581 : 0 : f->fingers = ((p[0] & 0x6) >> 1 |
582 : 0 : (p[0] & 0x10) >> 2);
583 : :
584 : 0 : palm_data = (p[1] & 0x7f) |
585 : 0 : ((p[2] & 0x7f) << 7) |
586 : 0 : ((p[4] & 0x7f) << 14) |
587 : 0 : ((p[5] & 0x7f) << 21) |
588 : 0 : ((p[3] & 0x07) << 28) |
589 : 0 : (((u64)p[3] & 0x70) << 27) |
590 : 0 : (((u64)p[0] & 0x01) << 34);
591 : :
592 : : /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */
593 : 0 : f->y_map = palm_data & (BIT(priv->y_bits) - 1);
594 : :
595 : : /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */
596 : 0 : f->x_map = (palm_data >> priv->y_bits) &
597 : 0 : (BIT(priv->x_bits) - 1);
598 : : }
599 : 0 : }
600 : :
601 : 0 : static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
602 : : {
603 : 0 : struct alps_data *priv = psmouse->private;
604 : 0 : unsigned char *packet = psmouse->packet;
605 : 0 : struct input_dev *dev = psmouse->dev;
606 : 0 : struct input_dev *dev2 = priv->dev2;
607 : 0 : int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
608 : : int fingers = 0, bmap_fn;
609 : 0 : struct alps_fields f = {0};
610 : :
611 : 0 : priv->decode_fields(&f, packet, psmouse);
612 : :
613 : : /*
614 : : * There's no single feature of touchpad position and bitmap packets
615 : : * that can be used to distinguish between them. We rely on the fact
616 : : * that a bitmap packet should always follow a position packet with
617 : : * bit 6 of packet[4] set.
618 : : */
619 [ # # ]: 0 : if (priv->multi_packet) {
620 : : /*
621 : : * Sometimes a position packet will indicate a multi-packet
622 : : * sequence, but then what follows is another position
623 : : * packet. Check for this, and when it happens process the
624 : : * position packet as usual.
625 : : */
626 [ # # ]: 0 : if (f.is_mp) {
627 : 0 : fingers = f.fingers;
628 [ # # ]: 0 : if (priv->proto_version == ALPS_PROTO_V3) {
629 : 0 : bmap_fn = alps_process_bitmap(priv, f.x_map,
630 : : f.y_map, &x1, &y1,
631 : : &x2, &y2);
632 : :
633 : : /*
634 : : * We shouldn't report more than one finger if
635 : : * we don't have two coordinates.
636 : : */
637 [ # # ]: 0 : if (fingers > 1 && bmap_fn < 2)
638 : : fingers = bmap_fn;
639 : :
640 : : /* Now process position packet */
641 : 0 : priv->decode_fields(&f, priv->multi_data,
642 : : psmouse);
643 : : } else {
644 : : /*
645 : : * Because Dolphin uses position packet's
646 : : * coordinate data as Pt1 and uses it to
647 : : * calculate Pt2, so we need to do position
648 : : * packet decode first.
649 : : */
650 : 0 : priv->decode_fields(&f, priv->multi_data,
651 : : psmouse);
652 : :
653 : : /*
654 : : * Since Dolphin's finger number is reliable,
655 : : * there is no need to compare with bmap_fn.
656 : : */
657 : 0 : alps_process_bitmap_dolphin(priv, &f, &x1, &y1,
658 : : &x2, &y2);
659 : : }
660 : : } else {
661 : 0 : priv->multi_packet = 0;
662 : : }
663 : : }
664 : :
665 : : /*
666 : : * Bit 6 of byte 0 is not usually set in position packets. The only
667 : : * times it seems to be set is in situations where the data is
668 : : * suspect anyway, e.g. a palm resting flat on the touchpad. Given
669 : : * this combined with the fact that this bit is useful for filtering
670 : : * out misidentified bitmap packets, we reject anything with this
671 : : * bit set.
672 : : */
673 [ # # ]: 0 : if (f.is_mp)
674 : 0 : return;
675 : :
676 [ # # ][ # # ]: 0 : if (!priv->multi_packet && f.first_mp) {
677 : 0 : priv->multi_packet = 1;
678 : 0 : memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
679 : 0 : return;
680 : : }
681 : :
682 : 0 : priv->multi_packet = 0;
683 : :
684 : : /*
685 : : * Sometimes the hardware sends a single packet with z = 0
686 : : * in the middle of a stream. Real releases generate packets
687 : : * with x, y, and z all zero, so these seem to be flukes.
688 : : * Ignore them.
689 : : */
690 [ # # ][ # # ]: 0 : if (f.x && f.y && !f.z)
[ # # ]
691 : : return;
692 : :
693 : : /*
694 : : * If we don't have MT data or the bitmaps were empty, we have
695 : : * to rely on ST data.
696 : : */
697 [ # # ]: 0 : if (!fingers) {
698 : 0 : x1 = f.x;
699 : 0 : y1 = f.y;
700 : 0 : fingers = f.z > 0 ? 1 : 0;
701 : : }
702 : :
703 [ # # ]: 0 : if (f.z >= 64)
704 : : input_report_key(dev, BTN_TOUCH, 1);
705 : : else
706 : : input_report_key(dev, BTN_TOUCH, 0);
707 : :
708 : 0 : alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
709 : :
710 : 0 : input_mt_report_finger_count(dev, fingers);
711 : :
712 : 0 : input_report_key(dev, BTN_LEFT, f.left);
713 : 0 : input_report_key(dev, BTN_RIGHT, f.right);
714 : 0 : input_report_key(dev, BTN_MIDDLE, f.middle);
715 : :
716 [ # # ]: 0 : if (f.z > 0) {
717 : 0 : input_report_abs(dev, ABS_X, f.x);
718 : 0 : input_report_abs(dev, ABS_Y, f.y);
719 : : }
720 : 0 : input_report_abs(dev, ABS_PRESSURE, f.z);
721 : :
722 : : input_sync(dev);
723 : :
724 [ # # ]: 0 : if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
725 : 0 : input_report_key(dev2, BTN_LEFT, f.ts_left);
726 : 0 : input_report_key(dev2, BTN_RIGHT, f.ts_right);
727 : 0 : input_report_key(dev2, BTN_MIDDLE, f.ts_middle);
728 : : input_sync(dev2);
729 : : }
730 : : }
731 : :
732 : 0 : static void alps_process_packet_v3(struct psmouse *psmouse)
733 : : {
734 : : unsigned char *packet = psmouse->packet;
735 : :
736 : : /*
737 : : * v3 protocol packets come in three types, two representing
738 : : * touchpad data and one representing trackstick data.
739 : : * Trackstick packets seem to be distinguished by always
740 : : * having 0x3f in the last byte. This value has never been
741 : : * observed in the last byte of either of the other types
742 : : * of packets.
743 : : */
744 [ # # ]: 0 : if (packet[5] == 0x3f) {
745 : 0 : alps_process_trackstick_packet_v3(psmouse);
746 : 0 : return;
747 : : }
748 : :
749 : 0 : alps_process_touchpad_packet_v3_v5(psmouse);
750 : : }
751 : :
752 : 0 : static void alps_process_packet_v6(struct psmouse *psmouse)
753 : : {
754 : 0 : struct alps_data *priv = psmouse->private;
755 : : unsigned char *packet = psmouse->packet;
756 : 0 : struct input_dev *dev = psmouse->dev;
757 : 0 : struct input_dev *dev2 = priv->dev2;
758 : : int x, y, z, left, right, middle;
759 : :
760 : : /*
761 : : * We can use Byte5 to distinguish if the packet is from Touchpad
762 : : * or Trackpoint.
763 : : * Touchpad: 0 - 0x7E
764 : : * Trackpoint: 0x7F
765 : : */
766 [ # # ]: 0 : if (packet[5] == 0x7F) {
767 : : /* It should be a DualPoint when received Trackpoint packet */
768 [ # # ]: 0 : if (!(priv->flags & ALPS_DUALPOINT))
769 : : return;
770 : :
771 : : /* Trackpoint packet */
772 : 0 : x = packet[1] | ((packet[3] & 0x20) << 2);
773 : 0 : y = packet[2] | ((packet[3] & 0x40) << 1);
774 : 0 : z = packet[4];
775 : 0 : left = packet[3] & 0x01;
776 : 0 : right = packet[3] & 0x02;
777 : 0 : middle = packet[3] & 0x04;
778 : :
779 : : /* To prevent the cursor jump when finger lifted */
780 [ # # ][ # # ]: 0 : if (x == 0x7F && y == 0x7F && z == 0x7F)
781 : : x = y = z = 0;
782 : :
783 : : /* Divide 4 since trackpoint's speed is too fast */
784 : 0 : input_report_rel(dev2, REL_X, (char)x / 4);
785 : 0 : input_report_rel(dev2, REL_Y, -((char)y / 4));
786 : :
787 : : input_report_key(dev2, BTN_LEFT, left);
788 : : input_report_key(dev2, BTN_RIGHT, right);
789 : : input_report_key(dev2, BTN_MIDDLE, middle);
790 : :
791 : : input_sync(dev2);
792 : : return;
793 : : }
794 : :
795 : : /* Touchpad packet */
796 : 0 : x = packet[1] | ((packet[3] & 0x78) << 4);
797 : 0 : y = packet[2] | ((packet[4] & 0x78) << 4);
798 : 0 : z = packet[5];
799 : 0 : left = packet[3] & 0x01;
800 : 0 : right = packet[3] & 0x02;
801 : :
802 [ # # ]: 0 : if (z > 30)
803 : : input_report_key(dev, BTN_TOUCH, 1);
804 [ # # ]: 0 : if (z < 25)
805 : : input_report_key(dev, BTN_TOUCH, 0);
806 : :
807 [ # # ]: 0 : if (z > 0) {
808 : : input_report_abs(dev, ABS_X, x);
809 : : input_report_abs(dev, ABS_Y, y);
810 : : }
811 : :
812 : : input_report_abs(dev, ABS_PRESSURE, z);
813 : 0 : input_report_key(dev, BTN_TOOL_FINGER, z > 0);
814 : :
815 : : /* v6 touchpad does not have middle button */
816 : : input_report_key(dev, BTN_LEFT, left);
817 : : input_report_key(dev, BTN_RIGHT, right);
818 : :
819 : : input_sync(dev);
820 : : }
821 : :
822 : 0 : static void alps_process_packet_v4(struct psmouse *psmouse)
823 : : {
824 : 0 : struct alps_data *priv = psmouse->private;
825 : : unsigned char *packet = psmouse->packet;
826 : 0 : struct input_dev *dev = psmouse->dev;
827 : : int offset;
828 : : int x, y, z;
829 : : int left, right;
830 : : int x1, y1, x2, y2;
831 : : int fingers = 0;
832 : : unsigned int x_bitmap, y_bitmap;
833 : :
834 : : /*
835 : : * v4 has a 6-byte encoding for bitmap data, but this data is
836 : : * broken up between 3 normal packets. Use priv->multi_packet to
837 : : * track our position in the bitmap packet.
838 : : */
839 [ # # ]: 0 : if (packet[6] & 0x40) {
840 : : /* sync, reset position */
841 : 0 : priv->multi_packet = 0;
842 : : }
843 : :
844 [ # # ][ # # ]: 0 : if (WARN_ON_ONCE(priv->multi_packet > 2))
[ # # ][ # # ]
845 : 0 : return;
846 : :
847 : 0 : offset = 2 * priv->multi_packet;
848 : 0 : priv->multi_data[offset] = packet[6];
849 : 0 : priv->multi_data[offset + 1] = packet[7];
850 : :
851 [ # # ]: 0 : if (++priv->multi_packet > 2) {
852 : 0 : priv->multi_packet = 0;
853 : :
854 : 0 : x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
855 : 0 : ((priv->multi_data[3] & 0x60) << 3) |
856 : 0 : ((priv->multi_data[0] & 0x3f) << 2) |
857 : 0 : ((priv->multi_data[1] & 0x60) >> 5);
858 : 0 : y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
859 : 0 : ((priv->multi_data[3] & 0x1f) << 5) |
860 : 0 : (priv->multi_data[1] & 0x1f);
861 : :
862 : 0 : fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap,
863 : : &x1, &y1, &x2, &y2);
864 : :
865 : : /* Store MT data.*/
866 : 0 : priv->fingers = fingers;
867 : 0 : priv->x1 = x1;
868 : 0 : priv->x2 = x2;
869 : 0 : priv->y1 = y1;
870 : 0 : priv->y2 = y2;
871 : : }
872 : :
873 : 0 : left = packet[4] & 0x01;
874 : 0 : right = packet[4] & 0x02;
875 : :
876 : 0 : x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
877 : 0 : ((packet[0] & 0x30) >> 4);
878 : 0 : y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
879 : 0 : z = packet[5] & 0x7f;
880 : :
881 : : /*
882 : : * If there were no contacts in the bitmap, use ST
883 : : * points in MT reports.
884 : : * If there were two contacts or more, report MT data.
885 : : */
886 [ # # ]: 0 : if (priv->fingers < 2) {
887 : 0 : x1 = x;
888 : 0 : y1 = y;
889 : 0 : fingers = z > 0 ? 1 : 0;
890 : : } else {
891 : : fingers = priv->fingers;
892 : 0 : x1 = priv->x1;
893 : 0 : x2 = priv->x2;
894 : 0 : y1 = priv->y1;
895 : 0 : y2 = priv->y2;
896 : : }
897 : :
898 [ # # ]: 0 : if (z >= 64)
899 : : input_report_key(dev, BTN_TOUCH, 1);
900 : : else
901 : : input_report_key(dev, BTN_TOUCH, 0);
902 : :
903 : 0 : alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
904 : :
905 : 0 : input_mt_report_finger_count(dev, fingers);
906 : :
907 : : input_report_key(dev, BTN_LEFT, left);
908 : : input_report_key(dev, BTN_RIGHT, right);
909 : :
910 [ # # ]: 0 : if (z > 0) {
911 : : input_report_abs(dev, ABS_X, x);
912 : : input_report_abs(dev, ABS_Y, y);
913 : : }
914 : : input_report_abs(dev, ABS_PRESSURE, z);
915 : :
916 : : input_sync(dev);
917 : : }
918 : :
919 : 0 : static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
920 : : unsigned char packet[],
921 : : bool report_buttons)
922 : : {
923 : 0 : struct alps_data *priv = psmouse->private;
924 : 0 : struct input_dev *dev2 = priv->dev2;
925 : :
926 [ # # ]: 0 : if (report_buttons)
927 : 0 : alps_report_buttons(psmouse, dev2, psmouse->dev,
928 : 0 : packet[0] & 1, packet[0] & 2, packet[0] & 4);
929 : :
930 [ # # ]: 0 : input_report_rel(dev2, REL_X,
931 : 0 : packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
932 [ # # ]: 0 : input_report_rel(dev2, REL_Y,
933 : 0 : packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
934 : :
935 : : input_sync(dev2);
936 : 0 : }
937 : :
938 : 0 : static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
939 : : {
940 : 0 : struct alps_data *priv = psmouse->private;
941 : :
942 [ # # ]: 0 : if (psmouse->pktcnt < 6)
943 : : return PSMOUSE_GOOD_DATA;
944 : :
945 [ # # ]: 0 : if (psmouse->pktcnt == 6) {
946 : : /*
947 : : * Start a timer to flush the packet if it ends up last
948 : : * 6-byte packet in the stream. Timer needs to fire
949 : : * psmouse core times out itself. 20 ms should be enough
950 : : * to decide if we are getting more data or not.
951 : : */
952 : 0 : mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
953 : 0 : return PSMOUSE_GOOD_DATA;
954 : : }
955 : :
956 : 0 : del_timer(&priv->timer);
957 : :
958 [ # # ]: 0 : if (psmouse->packet[6] & 0x80) {
959 : :
960 : : /*
961 : : * Highest bit is set - that means we either had
962 : : * complete ALPS packet and this is start of the
963 : : * next packet or we got garbage.
964 : : */
965 : :
966 [ # # ]: 0 : if (((psmouse->packet[3] |
967 : 0 : psmouse->packet[4] |
968 [ # # ]: 0 : psmouse->packet[5]) & 0x80) ||
969 : : (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) {
970 : : psmouse_dbg(psmouse,
971 : : "refusing packet %4ph (suspected interleaved ps/2)\n",
972 : : psmouse->packet + 3);
973 : : return PSMOUSE_BAD_DATA;
974 : : }
975 : :
976 : 0 : priv->process_packet(psmouse);
977 : :
978 : : /* Continue with the next packet */
979 : 0 : psmouse->packet[0] = psmouse->packet[6];
980 : 0 : psmouse->pktcnt = 1;
981 : :
982 : : } else {
983 : :
984 : : /*
985 : : * High bit is 0 - that means that we indeed got a PS/2
986 : : * packet in the middle of ALPS packet.
987 : : *
988 : : * There is also possibility that we got 6-byte ALPS
989 : : * packet followed by 3-byte packet from trackpoint. We
990 : : * can not distinguish between these 2 scenarios but
991 : : * because the latter is unlikely to happen in course of
992 : : * normal operation (user would need to press all
993 : : * buttons on the pad and start moving trackpoint
994 : : * without touching the pad surface) we assume former.
995 : : * Even if we are wrong the wost thing that would happen
996 : : * the cursor would jump but we should not get protocol
997 : : * de-synchronization.
998 : : */
999 : :
1000 : 0 : alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
1001 : : false);
1002 : :
1003 : : /*
1004 : : * Continue with the standard ALPS protocol handling,
1005 : : * but make sure we won't process it as an interleaved
1006 : : * packet again, which may happen if all buttons are
1007 : : * pressed. To avoid this let's reset the 4th bit which
1008 : : * is normally 1.
1009 : : */
1010 : 0 : psmouse->packet[3] = psmouse->packet[6] & 0xf7;
1011 : 0 : psmouse->pktcnt = 4;
1012 : : }
1013 : :
1014 : : return PSMOUSE_GOOD_DATA;
1015 : : }
1016 : :
1017 : 0 : static void alps_flush_packet(unsigned long data)
1018 : : {
1019 : 0 : struct psmouse *psmouse = (struct psmouse *)data;
1020 : 0 : struct alps_data *priv = psmouse->private;
1021 : :
1022 : 0 : serio_pause_rx(psmouse->ps2dev.serio);
1023 : :
1024 [ # # ]: 0 : if (psmouse->pktcnt == psmouse->pktsize) {
1025 : :
1026 : : /*
1027 : : * We did not any more data in reasonable amount of time.
1028 : : * Validate the last 3 bytes and process as a standard
1029 : : * ALPS packet.
1030 : : */
1031 [ # # ]: 0 : if ((psmouse->packet[3] |
1032 : 0 : psmouse->packet[4] |
1033 : 0 : psmouse->packet[5]) & 0x80) {
1034 : : psmouse_dbg(psmouse,
1035 : : "refusing packet %3ph (suspected interleaved ps/2)\n",
1036 : : psmouse->packet + 3);
1037 : : } else {
1038 : 0 : priv->process_packet(psmouse);
1039 : : }
1040 : 0 : psmouse->pktcnt = 0;
1041 : : }
1042 : :
1043 : 0 : serio_continue_rx(psmouse->ps2dev.serio);
1044 : 0 : }
1045 : :
1046 : 0 : static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
1047 : : {
1048 : 0 : struct alps_data *priv = psmouse->private;
1049 : :
1050 [ # # ]: 0 : if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
1051 [ # # ]: 0 : if (psmouse->pktcnt == 3) {
1052 : 0 : alps_report_bare_ps2_packet(psmouse, psmouse->packet,
1053 : : true);
1054 : 0 : return PSMOUSE_FULL_PACKET;
1055 : : }
1056 : : return PSMOUSE_GOOD_DATA;
1057 : : }
1058 : :
1059 : : /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
1060 : :
1061 [ # # ][ # # ]: 0 : if ((priv->flags & ALPS_PS2_INTERLEAVED) &&
1062 [ # # ]: 0 : psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
1063 : 0 : return alps_handle_interleaved_ps2(psmouse);
1064 : : }
1065 : :
1066 [ # # ]: 0 : if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) {
1067 : : psmouse_dbg(psmouse,
1068 : : "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
1069 : : psmouse->packet[0], priv->mask0, priv->byte0);
1070 : : return PSMOUSE_BAD_DATA;
1071 : : }
1072 : :
1073 : : /* Bytes 2 - pktsize should have 0 in the highest bit */
1074 [ # # ][ # # ]: 0 : if ((priv->proto_version < ALPS_PROTO_V5) &&
1075 [ # # ][ # # ]: 0 : psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
1076 : 0 : (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
1077 : : psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
1078 : : psmouse->pktcnt - 1,
1079 : : psmouse->packet[psmouse->pktcnt - 1]);
1080 : : return PSMOUSE_BAD_DATA;
1081 : : }
1082 : :
1083 [ # # ]: 0 : if (psmouse->pktcnt == psmouse->pktsize) {
1084 : 0 : priv->process_packet(psmouse);
1085 : 0 : return PSMOUSE_FULL_PACKET;
1086 : : }
1087 : :
1088 : : return PSMOUSE_GOOD_DATA;
1089 : : }
1090 : :
1091 : 0 : static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble)
1092 : : {
1093 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1094 : 0 : struct alps_data *priv = psmouse->private;
1095 : : int command;
1096 : : unsigned char *param;
1097 : : unsigned char dummy[4];
1098 : :
1099 [ # # ]: 0 : BUG_ON(nibble > 0xf);
1100 : :
1101 : 0 : command = priv->nibble_commands[nibble].command;
1102 : 0 : param = (command & 0x0f00) ?
1103 [ # # ]: 0 : dummy : (unsigned char *)&priv->nibble_commands[nibble].data;
1104 : :
1105 [ # # ]: 0 : if (ps2_command(ps2dev, param, command))
1106 : : return -1;
1107 : :
1108 : 0 : return 0;
1109 : : }
1110 : :
1111 : 0 : static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr)
1112 : : {
1113 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1114 : 0 : struct alps_data *priv = psmouse->private;
1115 : : int i, nibble;
1116 : :
1117 [ # # ]: 0 : if (ps2_command(ps2dev, NULL, priv->addr_command))
1118 : : return -1;
1119 : :
1120 [ # # ]: 0 : for (i = 12; i >= 0; i -= 4) {
1121 : 0 : nibble = (addr >> i) & 0xf;
1122 [ # # ]: 0 : if (alps_command_mode_send_nibble(psmouse, nibble))
1123 : : return -1;
1124 : : }
1125 : :
1126 : : return 0;
1127 : : }
1128 : :
1129 : 0 : static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
1130 : : {
1131 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1132 : : unsigned char param[4];
1133 : :
1134 [ # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
1135 : : return -1;
1136 : :
1137 : : /*
1138 : : * The address being read is returned in the first two bytes
1139 : : * of the result. Check that this address matches the expected
1140 : : * address.
1141 : : */
1142 [ # # ]: 0 : if (addr != ((param[0] << 8) | param[1]))
1143 : : return -1;
1144 : :
1145 : 0 : return param[2];
1146 : : }
1147 : :
1148 : 0 : static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
1149 : : {
1150 [ # # ]: 0 : if (alps_command_mode_set_addr(psmouse, addr))
1151 : : return -1;
1152 : 0 : return __alps_command_mode_read_reg(psmouse, addr);
1153 : : }
1154 : :
1155 : 0 : static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value)
1156 : : {
1157 [ # # ]: 0 : if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf))
1158 : : return -1;
1159 [ # # ]: 0 : if (alps_command_mode_send_nibble(psmouse, value & 0xf))
1160 : : return -1;
1161 : 0 : return 0;
1162 : : }
1163 : :
1164 : 0 : static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr,
1165 : : u8 value)
1166 : : {
1167 [ # # ]: 0 : if (alps_command_mode_set_addr(psmouse, addr))
1168 : : return -1;
1169 : 0 : return __alps_command_mode_write_reg(psmouse, value);
1170 : : }
1171 : :
1172 : 0 : static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
1173 : : int repeated_command, unsigned char *param)
1174 : : {
1175 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1176 : :
1177 : 0 : param[0] = 0;
1178 [ # # ][ # # ]: 0 : if (init_command && ps2_command(ps2dev, param, init_command))
1179 : : return -EIO;
1180 : :
1181 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, repeated_command) ||
1182 [ # # ]: 0 : ps2_command(ps2dev, NULL, repeated_command) ||
1183 : 0 : ps2_command(ps2dev, NULL, repeated_command))
1184 : : return -EIO;
1185 : :
1186 : 0 : param[0] = param[1] = param[2] = 0xff;
1187 [ # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
1188 : : return -EIO;
1189 : :
1190 : : psmouse_dbg(psmouse, "%2.2X report: %3ph\n",
1191 : : repeated_command, param);
1192 : 0 : return 0;
1193 : : }
1194 : :
1195 : 0 : static int alps_enter_command_mode(struct psmouse *psmouse)
1196 : : {
1197 : : unsigned char param[4];
1198 : :
1199 [ # # ]: 0 : if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) {
1200 : 0 : psmouse_err(psmouse, "failed to enter command mode\n");
1201 : 0 : return -1;
1202 : : }
1203 : :
1204 [ # # ][ # # ]: 0 : if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
[ # # ]
1205 : : param[0] != 0x73) {
1206 : : psmouse_dbg(psmouse,
1207 : : "unknown response while entering command mode\n");
1208 : : return -1;
1209 : : }
1210 : 0 : return 0;
1211 : : }
1212 : :
1213 : : static inline int alps_exit_command_mode(struct psmouse *psmouse)
1214 : : {
1215 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1216 [ # # ][ # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM))
[ # # ][ # # ]
1217 : : return -1;
1218 : : return 0;
1219 : : }
1220 : :
1221 : : /*
1222 : : * For DualPoint devices select the device that should respond to
1223 : : * subsequent commands. It looks like glidepad is behind stickpointer,
1224 : : * I'd thought it would be other way around...
1225 : : */
1226 : 0 : static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable)
1227 : : {
1228 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1229 [ # # ]: 0 : int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
1230 : :
1231 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, cmd) ||
1232 [ # # ]: 0 : ps2_command(ps2dev, NULL, cmd) ||
1233 [ # # ]: 0 : ps2_command(ps2dev, NULL, cmd) ||
1234 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
1235 : : return -1;
1236 : :
1237 : : /* we may get 3 more bytes, just ignore them */
1238 : 0 : ps2_drain(ps2dev, 3, 100);
1239 : :
1240 : 0 : return 0;
1241 : : }
1242 : :
1243 : 0 : static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
1244 : : {
1245 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1246 : :
1247 : : /* Try ALPS magic knock - 4 disable before enable */
1248 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1249 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1250 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1251 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1252 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
1253 : : return -1;
1254 : :
1255 : : /*
1256 : : * Switch mouse to poll (remote) mode so motion data will not
1257 : : * get in our way
1258 : : */
1259 : 0 : return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
1260 : : }
1261 : :
1262 : 0 : static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
1263 : : {
1264 : : int i, nibble;
1265 : :
1266 : : /*
1267 : : * b0-b11 are valid bits, send sequence is inverse.
1268 : : * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
1269 : : */
1270 [ # # ]: 0 : for (i = 0; i <= 8; i += 4) {
1271 : 0 : nibble = (word >> i) & 0xf;
1272 [ # # ]: 0 : if (alps_command_mode_send_nibble(psmouse, nibble))
1273 : : return -1;
1274 : : }
1275 : :
1276 : : return 0;
1277 : : }
1278 : :
1279 : 0 : static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
1280 : : u16 addr, u16 value)
1281 : : {
1282 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1283 : :
1284 : : /* 0x0A0 is the command to write the word */
1285 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
1286 [ # # ]: 0 : alps_monitor_mode_send_word(psmouse, 0x0A0) ||
1287 [ # # ]: 0 : alps_monitor_mode_send_word(psmouse, addr) ||
1288 [ # # ]: 0 : alps_monitor_mode_send_word(psmouse, value) ||
1289 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
1290 : : return -1;
1291 : :
1292 : : return 0;
1293 : : }
1294 : :
1295 : 0 : static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
1296 : : {
1297 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1298 : :
1299 [ # # ]: 0 : if (enable) {
1300 : : /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
1301 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
1302 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
1303 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1304 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1305 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1306 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1307 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1308 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
1309 : : return -1;
1310 : : } else {
1311 : : /* EC to exit monitor mode */
1312 [ # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
1313 : : return -1;
1314 : : }
1315 : :
1316 : : return 0;
1317 : : }
1318 : :
1319 : 0 : static int alps_absolute_mode_v6(struct psmouse *psmouse)
1320 : : {
1321 : : u16 reg_val = 0x181;
1322 : : int ret = -1;
1323 : :
1324 : : /* enter monitor mode, to write the register */
1325 [ # # ]: 0 : if (alps_monitor_mode(psmouse, true))
1326 : : return -1;
1327 : :
1328 : 0 : ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
1329 : :
1330 [ # # ]: 0 : if (alps_monitor_mode(psmouse, false))
1331 : : ret = -1;
1332 : :
1333 : 0 : return ret;
1334 : : }
1335 : :
1336 : : static int alps_get_status(struct psmouse *psmouse, char *param)
1337 : : {
1338 : : /* Get status: 0xF5 0xF5 0xF5 0xE9 */
1339 [ # # ]: 0 : if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param))
1340 : : return -1;
1341 : :
1342 : : return 0;
1343 : : }
1344 : :
1345 : : /*
1346 : : * Turn touchpad tapping on or off. The sequences are:
1347 : : * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
1348 : : * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
1349 : : * My guess that 0xE9 (GetInfo) is here as a sync point.
1350 : : * For models that also have stickpointer (DualPoints) its tapping
1351 : : * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
1352 : : * we don't fiddle with it.
1353 : : */
1354 : 0 : static int alps_tap_mode(struct psmouse *psmouse, int enable)
1355 : : {
1356 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1357 [ # # ]: 0 : int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
1358 [ # # ]: 0 : unsigned char tap_arg = enable ? 0x0A : 0x00;
1359 : : unsigned char param[4];
1360 : :
1361 [ # # # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) ||
1362 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1363 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1364 : 0 : ps2_command(ps2dev, &tap_arg, cmd))
1365 : : return -1;
1366 : :
1367 [ # # ]: 0 : if (alps_get_status(psmouse, param))
1368 : : return -1;
1369 : :
1370 : 0 : return 0;
1371 : : }
1372 : :
1373 : : /*
1374 : : * alps_poll() - poll the touchpad for current motion packet.
1375 : : * Used in resync.
1376 : : */
1377 : 0 : static int alps_poll(struct psmouse *psmouse)
1378 : : {
1379 : 0 : struct alps_data *priv = psmouse->private;
1380 : : unsigned char buf[sizeof(psmouse->packet)];
1381 : : bool poll_failed;
1382 : :
1383 [ # # ]: 0 : if (priv->flags & ALPS_PASS)
1384 : 0 : alps_passthrough_mode_v2(psmouse, true);
1385 : :
1386 : 0 : poll_failed = ps2_command(&psmouse->ps2dev, buf,
1387 : 0 : PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
1388 : :
1389 [ # # ]: 0 : if (priv->flags & ALPS_PASS)
1390 : 0 : alps_passthrough_mode_v2(psmouse, false);
1391 : :
1392 [ # # ][ # # ]: 0 : if (poll_failed || (buf[0] & priv->mask0) != priv->byte0)
1393 : : return -1;
1394 : :
1395 [ # # ]: 0 : if ((psmouse->badbyte & 0xc8) == 0x08) {
1396 : : /*
1397 : : * Poll the track stick ...
1398 : : */
1399 [ # # ]: 0 : if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
1400 : : return -1;
1401 : : }
1402 : :
1403 : 0 : memcpy(psmouse->packet, buf, sizeof(buf));
1404 : 0 : return 0;
1405 : : }
1406 : :
1407 : 0 : static int alps_hw_init_v1_v2(struct psmouse *psmouse)
1408 : : {
1409 : 0 : struct alps_data *priv = psmouse->private;
1410 : :
1411 [ # # # # ]: 0 : if ((priv->flags & ALPS_PASS) &&
1412 : 0 : alps_passthrough_mode_v2(psmouse, true)) {
1413 : : return -1;
1414 : : }
1415 : :
1416 [ # # ]: 0 : if (alps_tap_mode(psmouse, true)) {
1417 : 0 : psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
1418 : 0 : return -1;
1419 : : }
1420 : :
1421 [ # # ]: 0 : if (alps_absolute_mode_v1_v2(psmouse)) {
1422 : 0 : psmouse_err(psmouse, "Failed to enable absolute mode\n");
1423 : 0 : return -1;
1424 : : }
1425 : :
1426 [ # # # # ]: 0 : if ((priv->flags & ALPS_PASS) &&
1427 : 0 : alps_passthrough_mode_v2(psmouse, false)) {
1428 : : return -1;
1429 : : }
1430 : :
1431 : : /* ALPS needs stream mode, otherwise it won't report any data */
1432 [ # # ]: 0 : if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
1433 : 0 : psmouse_err(psmouse, "Failed to enable stream mode\n");
1434 : 0 : return -1;
1435 : : }
1436 : :
1437 : : return 0;
1438 : : }
1439 : :
1440 : 0 : static int alps_hw_init_v6(struct psmouse *psmouse)
1441 : : {
1442 : 0 : unsigned char param[2] = {0xC8, 0x14};
1443 : :
1444 : : /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
1445 [ # # ]: 0 : if (alps_passthrough_mode_v2(psmouse, true))
1446 : : return -1;
1447 : :
1448 [ # # # # ]: 0 : if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1449 [ # # ]: 0 : ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1450 [ # # ]: 0 : ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1451 [ # # ]: 0 : ps2_command(&psmouse->ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
1452 : 0 : ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE))
1453 : : return -1;
1454 : :
1455 [ # # ]: 0 : if (alps_passthrough_mode_v2(psmouse, false))
1456 : : return -1;
1457 : :
1458 [ # # ]: 0 : if (alps_absolute_mode_v6(psmouse)) {
1459 : 0 : psmouse_err(psmouse, "Failed to enable absolute mode\n");
1460 : 0 : return -1;
1461 : : }
1462 : :
1463 : : return 0;
1464 : : }
1465 : :
1466 : : /*
1467 : : * Enable or disable passthrough mode to the trackstick.
1468 : : */
1469 : 0 : static int alps_passthrough_mode_v3(struct psmouse *psmouse,
1470 : : int reg_base, bool enable)
1471 : : {
1472 : : int reg_val, ret = -1;
1473 : :
1474 [ # # ]: 0 : if (alps_enter_command_mode(psmouse))
1475 : : return -1;
1476 : :
1477 : 0 : reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
1478 [ # # ]: 0 : if (reg_val == -1)
1479 : : goto error;
1480 : :
1481 [ # # ]: 0 : if (enable)
1482 : 0 : reg_val |= 0x01;
1483 : : else
1484 : 0 : reg_val &= ~0x01;
1485 : :
1486 : 0 : ret = __alps_command_mode_write_reg(psmouse, reg_val);
1487 : :
1488 : : error:
1489 [ # # ]: 0 : if (alps_exit_command_mode(psmouse))
1490 : : ret = -1;
1491 : 0 : return ret;
1492 : : }
1493 : :
1494 : : /* Must be in command mode when calling this function */
1495 : 0 : static int alps_absolute_mode_v3(struct psmouse *psmouse)
1496 : : {
1497 : : int reg_val;
1498 : :
1499 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
1500 [ # # ]: 0 : if (reg_val == -1)
1501 : : return -1;
1502 : :
1503 : 0 : reg_val |= 0x06;
1504 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val))
1505 : : return -1;
1506 : :
1507 : 0 : return 0;
1508 : : }
1509 : :
1510 : 0 : static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
1511 : : {
1512 : : int ret = -EIO, reg_val;
1513 : :
1514 [ # # ]: 0 : if (alps_enter_command_mode(psmouse))
1515 : : goto error;
1516 : :
1517 : 0 : reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
1518 [ # # ]: 0 : if (reg_val == -1)
1519 : : goto error;
1520 : :
1521 : : /* bit 7: trackstick is present */
1522 [ # # ]: 0 : ret = reg_val & 0x80 ? 0 : -ENODEV;
1523 : :
1524 : : error:
1525 : : alps_exit_command_mode(psmouse);
1526 : 0 : return ret;
1527 : : }
1528 : :
1529 : 0 : static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
1530 : : {
1531 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1532 : : int ret = 0;
1533 : : unsigned char param[4];
1534 : :
1535 [ # # ]: 0 : if (alps_passthrough_mode_v3(psmouse, reg_base, true))
1536 : : return -EIO;
1537 : :
1538 : : /*
1539 : : * E7 report for the trackstick
1540 : : *
1541 : : * There have been reports of failures to seem to trace back
1542 : : * to the above trackstick check failing. When these occur
1543 : : * this E7 report fails, so when that happens we continue
1544 : : * with the assumption that there isn't a trackstick after
1545 : : * all.
1546 : : */
1547 [ # # ]: 0 : if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
1548 : 0 : psmouse_warn(psmouse, "trackstick E7 report failed\n");
1549 : : ret = -ENODEV;
1550 : : } else {
1551 : : psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
1552 : :
1553 : : /*
1554 : : * Not sure what this does, but it is absolutely
1555 : : * essential. Without it, the touchpad does not
1556 : : * work at all and the trackstick just emits normal
1557 : : * PS/2 packets.
1558 : : */
1559 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1560 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1561 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1562 [ # # ]: 0 : alps_command_mode_send_nibble(psmouse, 0x9) ||
1563 : 0 : alps_command_mode_send_nibble(psmouse, 0x4)) {
1564 : 0 : psmouse_err(psmouse,
1565 : : "Error sending magic E6 sequence\n");
1566 : : ret = -EIO;
1567 : 0 : goto error;
1568 : : }
1569 : :
1570 : : /*
1571 : : * This ensures the trackstick packets are in the format
1572 : : * supported by this driver. If bit 1 isn't set the packet
1573 : : * format is different.
1574 : : */
1575 [ # # # # ]: 0 : if (alps_enter_command_mode(psmouse) ||
1576 : 0 : alps_command_mode_write_reg(psmouse,
1577 [ # # ]: 0 : reg_base + 0x08, 0x82) ||
1578 : : alps_exit_command_mode(psmouse))
1579 : : ret = -EIO;
1580 : : }
1581 : :
1582 : : error:
1583 [ # # ]: 0 : if (alps_passthrough_mode_v3(psmouse, reg_base, false))
1584 : : ret = -EIO;
1585 : :
1586 : 0 : return ret;
1587 : : }
1588 : :
1589 : 0 : static int alps_hw_init_v3(struct psmouse *psmouse)
1590 : : {
1591 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1592 : : int reg_val;
1593 : : unsigned char param[4];
1594 : :
1595 : 0 : reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE);
1596 [ # # ]: 0 : if (reg_val == -EIO)
1597 : : goto error;
1598 : :
1599 [ # # # # ]: 0 : if (reg_val == 0 &&
1600 : 0 : alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
1601 : : goto error;
1602 : :
1603 [ # # # # ]: 0 : if (alps_enter_command_mode(psmouse) ||
1604 : 0 : alps_absolute_mode_v3(psmouse)) {
1605 : 0 : psmouse_err(psmouse, "Failed to enter absolute mode\n");
1606 : 0 : goto error;
1607 : : }
1608 : :
1609 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0x0006);
1610 [ # # ]: 0 : if (reg_val == -1)
1611 : : goto error;
1612 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
1613 : : goto error;
1614 : :
1615 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0x0007);
1616 [ # # ]: 0 : if (reg_val == -1)
1617 : : goto error;
1618 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
1619 : : goto error;
1620 : :
1621 [ # # ]: 0 : if (alps_command_mode_read_reg(psmouse, 0x0144) == -1)
1622 : : goto error;
1623 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, 0x04))
1624 : : goto error;
1625 : :
1626 [ # # ]: 0 : if (alps_command_mode_read_reg(psmouse, 0x0159) == -1)
1627 : : goto error;
1628 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, 0x03))
1629 : : goto error;
1630 : :
1631 [ # # ]: 0 : if (alps_command_mode_read_reg(psmouse, 0x0163) == -1)
1632 : : goto error;
1633 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03))
1634 : : goto error;
1635 : :
1636 [ # # ]: 0 : if (alps_command_mode_read_reg(psmouse, 0x0162) == -1)
1637 : : goto error;
1638 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04))
1639 : : goto error;
1640 : :
1641 : : alps_exit_command_mode(psmouse);
1642 : :
1643 : : /* Set rate and enable data reporting */
1644 : 0 : param[0] = 0x64;
1645 [ # # # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
1646 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
1647 : 0 : psmouse_err(psmouse, "Failed to enable data reporting\n");
1648 : 0 : return -1;
1649 : : }
1650 : :
1651 : : return 0;
1652 : :
1653 : : error:
1654 : : /*
1655 : : * Leaving the touchpad in command mode will essentially render
1656 : : * it unusable until the machine reboots, so exit it here just
1657 : : * to be safe
1658 : : */
1659 : : alps_exit_command_mode(psmouse);
1660 : : return -1;
1661 : : }
1662 : :
1663 : 0 : static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
1664 : : {
1665 : 0 : struct alps_data *priv = psmouse->private;
1666 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1667 : : int reg_val, ret = -1;
1668 : :
1669 [ # # ]: 0 : if (priv->flags & ALPS_DUALPOINT) {
1670 : 0 : reg_val = alps_setup_trackstick_v3(psmouse,
1671 : : ALPS_REG_BASE_RUSHMORE);
1672 [ # # ]: 0 : if (reg_val == -EIO)
1673 : : goto error;
1674 [ # # ]: 0 : if (reg_val == -ENODEV)
1675 : 0 : priv->flags &= ~ALPS_DUALPOINT;
1676 : : }
1677 : :
1678 [ # # # # ]: 0 : if (alps_enter_command_mode(psmouse) ||
1679 [ # # ]: 0 : alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
1680 : 0 : alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
1681 : : goto error;
1682 : :
1683 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
1684 [ # # ]: 0 : if (reg_val == -1)
1685 : : goto error;
1686 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd))
1687 : : goto error;
1688 : :
1689 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
1690 : : goto error;
1691 : :
1692 : : /* enter absolute mode */
1693 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
1694 [ # # ]: 0 : if (reg_val == -1)
1695 : : goto error;
1696 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
1697 : : goto error;
1698 : :
1699 : : alps_exit_command_mode(psmouse);
1700 : 0 : return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
1701 : :
1702 : : error:
1703 : : alps_exit_command_mode(psmouse);
1704 : : return ret;
1705 : : }
1706 : :
1707 : : /* Must be in command mode when calling this function */
1708 : 0 : static int alps_absolute_mode_v4(struct psmouse *psmouse)
1709 : : {
1710 : : int reg_val;
1711 : :
1712 : 0 : reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
1713 [ # # ]: 0 : if (reg_val == -1)
1714 : : return -1;
1715 : :
1716 : 0 : reg_val |= 0x02;
1717 [ # # ]: 0 : if (__alps_command_mode_write_reg(psmouse, reg_val))
1718 : : return -1;
1719 : :
1720 : 0 : return 0;
1721 : : }
1722 : :
1723 : 0 : static int alps_hw_init_v4(struct psmouse *psmouse)
1724 : : {
1725 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1726 : : unsigned char param[4];
1727 : :
1728 [ # # ]: 0 : if (alps_enter_command_mode(psmouse))
1729 : : goto error;
1730 : :
1731 [ # # ]: 0 : if (alps_absolute_mode_v4(psmouse)) {
1732 : 0 : psmouse_err(psmouse, "Failed to enter absolute mode\n");
1733 : 0 : goto error;
1734 : : }
1735 : :
1736 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c))
1737 : : goto error;
1738 : :
1739 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03))
1740 : : goto error;
1741 : :
1742 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03))
1743 : : goto error;
1744 : :
1745 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15))
1746 : : goto error;
1747 : :
1748 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01))
1749 : : goto error;
1750 : :
1751 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03))
1752 : : goto error;
1753 : :
1754 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03))
1755 : : goto error;
1756 : :
1757 [ # # ]: 0 : if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03))
1758 : : goto error;
1759 : :
1760 : : alps_exit_command_mode(psmouse);
1761 : :
1762 : : /*
1763 : : * This sequence changes the output from a 9-byte to an
1764 : : * 8-byte format. All the same data seems to be present,
1765 : : * just in a more compact format.
1766 : : */
1767 : 0 : param[0] = 0xc8;
1768 : 0 : param[1] = 0x64;
1769 : 0 : param[2] = 0x50;
1770 [ # # # # ]: 0 : if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
1771 [ # # ]: 0 : ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) ||
1772 [ # # ]: 0 : ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) ||
1773 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
1774 : : return -1;
1775 : :
1776 : : /* Set rate and enable data reporting */
1777 : 0 : param[0] = 0x64;
1778 [ # # # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
1779 : 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
1780 : 0 : psmouse_err(psmouse, "Failed to enable data reporting\n");
1781 : 0 : return -1;
1782 : : }
1783 : :
1784 : : return 0;
1785 : :
1786 : : error:
1787 : : /*
1788 : : * Leaving the touchpad in command mode will essentially render
1789 : : * it unusable until the machine reboots, so exit it here just
1790 : : * to be safe
1791 : : */
1792 : : alps_exit_command_mode(psmouse);
1793 : : return -1;
1794 : : }
1795 : :
1796 : 0 : static int alps_dolphin_get_device_area(struct psmouse *psmouse,
1797 : : struct alps_data *priv)
1798 : : {
1799 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1800 : 0 : unsigned char param[4] = {0};
1801 : : int num_x_electrode, num_y_electrode;
1802 : :
1803 [ # # ]: 0 : if (alps_enter_command_mode(psmouse))
1804 : : return -1;
1805 : :
1806 : 0 : param[0] = 0x0a;
1807 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
1808 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
1809 [ # # ]: 0 : ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
1810 [ # # ]: 0 : ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
1811 : 0 : ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE))
1812 : : return -1;
1813 : :
1814 [ # # ]: 0 : if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
1815 : : return -1;
1816 : :
1817 : : /*
1818 : : * Dolphin's sensor line number is not fixed. It can be calculated
1819 : : * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET.
1820 : : * Further more, we can get device's x_max and y_max by multiplying
1821 : : * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE.
1822 : : *
1823 : : * e.g. When we get register's sensor_x = 11 & sensor_y = 8,
1824 : : * real sensor line number X = 11 + 8 = 19, and
1825 : : * real sensor line number Y = 8 + 1 = 9.
1826 : : * So, x_max = (19 - 1) * 64 = 1152, and
1827 : : * y_max = (9 - 1) * 64 = 512.
1828 : : */
1829 : 0 : num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F);
1830 : 0 : num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F);
1831 : 0 : priv->x_bits = num_x_electrode;
1832 : 0 : priv->y_bits = num_y_electrode;
1833 : 0 : priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
1834 : 0 : priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
1835 : :
1836 [ # # ]: 0 : if (alps_exit_command_mode(psmouse))
1837 : : return -1;
1838 : :
1839 : 0 : return 0;
1840 : : }
1841 : :
1842 : 0 : static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
1843 : : {
1844 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
1845 : : unsigned char param[2];
1846 : :
1847 : : /* This is dolphin "v1" as empirically defined by florin9doi */
1848 : 0 : param[0] = 0x64;
1849 : 0 : param[1] = 0x28;
1850 : :
1851 [ # # # # ]: 0 : if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
1852 [ # # ]: 0 : ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
1853 : 0 : ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE))
1854 : : return -1;
1855 : :
1856 : : return 0;
1857 : : }
1858 : :
1859 : 0 : static void alps_set_defaults(struct alps_data *priv)
1860 : : {
1861 : 0 : priv->byte0 = 0x8f;
1862 : 0 : priv->mask0 = 0x8f;
1863 : 0 : priv->flags = ALPS_DUALPOINT;
1864 : :
1865 : 0 : priv->x_max = 2000;
1866 : 0 : priv->y_max = 1400;
1867 : 0 : priv->x_bits = 15;
1868 : 0 : priv->y_bits = 11;
1869 : :
1870 [ # # # # : 0 : switch (priv->proto_version) {
# # ]
1871 : : case ALPS_PROTO_V1:
1872 : : case ALPS_PROTO_V2:
1873 : 0 : priv->hw_init = alps_hw_init_v1_v2;
1874 : 0 : priv->process_packet = alps_process_packet_v1_v2;
1875 : 0 : priv->set_abs_params = alps_set_abs_params_st;
1876 : 0 : priv->x_max = 1023;
1877 : 0 : priv->y_max = 767;
1878 : 0 : break;
1879 : : case ALPS_PROTO_V3:
1880 : 0 : priv->hw_init = alps_hw_init_v3;
1881 : 0 : priv->process_packet = alps_process_packet_v3;
1882 : 0 : priv->set_abs_params = alps_set_abs_params_mt;
1883 : 0 : priv->decode_fields = alps_decode_pinnacle;
1884 : 0 : priv->nibble_commands = alps_v3_nibble_commands;
1885 : 0 : priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
1886 : 0 : break;
1887 : : case ALPS_PROTO_V4:
1888 : 0 : priv->hw_init = alps_hw_init_v4;
1889 : 0 : priv->process_packet = alps_process_packet_v4;
1890 : 0 : priv->set_abs_params = alps_set_abs_params_mt;
1891 : 0 : priv->nibble_commands = alps_v4_nibble_commands;
1892 : 0 : priv->addr_command = PSMOUSE_CMD_DISABLE;
1893 : 0 : break;
1894 : : case ALPS_PROTO_V5:
1895 : 0 : priv->hw_init = alps_hw_init_dolphin_v1;
1896 : 0 : priv->process_packet = alps_process_touchpad_packet_v3_v5;
1897 : 0 : priv->decode_fields = alps_decode_dolphin;
1898 : 0 : priv->set_abs_params = alps_set_abs_params_mt;
1899 : 0 : priv->nibble_commands = alps_v3_nibble_commands;
1900 : 0 : priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
1901 : 0 : priv->byte0 = 0xc8;
1902 : 0 : priv->mask0 = 0xd8;
1903 : 0 : priv->flags = 0;
1904 : 0 : priv->x_max = 1360;
1905 : 0 : priv->y_max = 660;
1906 : 0 : priv->x_bits = 23;
1907 : 0 : priv->y_bits = 12;
1908 : 0 : break;
1909 : : case ALPS_PROTO_V6:
1910 : 0 : priv->hw_init = alps_hw_init_v6;
1911 : 0 : priv->process_packet = alps_process_packet_v6;
1912 : 0 : priv->set_abs_params = alps_set_abs_params_st;
1913 : 0 : priv->nibble_commands = alps_v6_nibble_commands;
1914 : 0 : priv->x_max = 2047;
1915 : 0 : priv->y_max = 1535;
1916 : 0 : break;
1917 : : }
1918 : 0 : }
1919 : :
1920 : 0 : static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv,
1921 : : unsigned char *e7, unsigned char *ec)
1922 : : {
1923 : : const struct alps_model_info *model;
1924 : : int i;
1925 : :
1926 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
1927 : 0 : model = &alps_model_data[i];
1928 : :
1929 [ # # ][ # # ]: 0 : if (!memcmp(e7, model->signature, sizeof(model->signature)) &&
1930 [ # # ]: 0 : (!model->command_mode_resp ||
1931 : 0 : model->command_mode_resp == ec[2])) {
1932 : :
1933 : 0 : priv->proto_version = model->proto_version;
1934 : 0 : alps_set_defaults(priv);
1935 : :
1936 : 0 : priv->flags = model->flags;
1937 : 0 : priv->byte0 = model->byte0;
1938 : 0 : priv->mask0 = model->mask0;
1939 : :
1940 : : return 0;
1941 : : }
1942 : : }
1943 : :
1944 : : return -EINVAL;
1945 : : }
1946 : :
1947 : 0 : static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
1948 : : {
1949 : : unsigned char e6[4], e7[4], ec[4];
1950 : :
1951 : : /*
1952 : : * First try "E6 report".
1953 : : * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
1954 : : * The bits 0-2 of the first byte will be 1s if some buttons are
1955 : : * pressed.
1956 : : */
1957 [ # # ]: 0 : if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1958 : : PSMOUSE_CMD_SETSCALE11, e6))
1959 : : return -EIO;
1960 : :
1961 [ # # ][ # # ]: 0 : if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
[ # # ]
1962 : : return -EINVAL;
1963 : :
1964 : : /*
1965 : : * Now get the "E7" and "EC" reports. These will uniquely identify
1966 : : * most ALPS touchpads.
1967 : : */
1968 [ # # ]: 0 : if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1969 [ # # ]: 0 : PSMOUSE_CMD_SETSCALE21, e7) ||
1970 : 0 : alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
1971 [ # # ]: 0 : PSMOUSE_CMD_RESET_WRAP, ec) ||
1972 : : alps_exit_command_mode(psmouse))
1973 : : return -EIO;
1974 : :
1975 [ # # ]: 0 : if (alps_match_table(psmouse, priv, e7, ec) == 0) {
1976 : : return 0;
1977 [ # # ][ # # ]: 0 : } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
[ # # ][ # # ]
1978 [ # # ]: 0 : ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
1979 : 0 : priv->proto_version = ALPS_PROTO_V5;
1980 : 0 : alps_set_defaults(priv);
1981 [ # # ]: 0 : if (alps_dolphin_get_device_area(psmouse, priv))
1982 : : return -EIO;
1983 : : else
1984 : 0 : return 0;
1985 [ # # ][ # # ]: 0 : } else if (ec[0] == 0x88 && ec[1] == 0x08) {
1986 : 0 : priv->proto_version = ALPS_PROTO_V3;
1987 : 0 : alps_set_defaults(priv);
1988 : :
1989 : 0 : priv->hw_init = alps_hw_init_rushmore_v3;
1990 : 0 : priv->decode_fields = alps_decode_rushmore;
1991 : 0 : priv->x_bits = 16;
1992 : 0 : priv->y_bits = 12;
1993 : :
1994 : : /* hack to make addr_command, nibble_command available */
1995 : 0 : psmouse->private = priv;
1996 : :
1997 [ # # ]: 0 : if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE))
1998 : 0 : priv->flags &= ~ALPS_DUALPOINT;
1999 : :
2000 : : return 0;
2001 [ # # ][ # # ]: 0 : } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
[ # # ]
2002 [ # # ]: 0 : ec[2] >= 0x90 && ec[2] <= 0x9d) {
2003 : 0 : priv->proto_version = ALPS_PROTO_V3;
2004 : 0 : alps_set_defaults(priv);
2005 : :
2006 : 0 : return 0;
2007 : : }
2008 : :
2009 : 0 : psmouse_info(psmouse,
2010 : : "Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
2011 : :
2012 : 0 : return -EINVAL;
2013 : : }
2014 : :
2015 : 0 : static int alps_reconnect(struct psmouse *psmouse)
2016 : : {
2017 : 0 : struct alps_data *priv = psmouse->private;
2018 : :
2019 : 0 : psmouse_reset(psmouse);
2020 : :
2021 [ # # ]: 0 : if (alps_identify(psmouse, priv) < 0)
2022 : : return -1;
2023 : :
2024 : 0 : return priv->hw_init(psmouse);
2025 : : }
2026 : :
2027 : 0 : static void alps_disconnect(struct psmouse *psmouse)
2028 : : {
2029 : 0 : struct alps_data *priv = psmouse->private;
2030 : :
2031 : 0 : psmouse_reset(psmouse);
2032 : 0 : del_timer_sync(&priv->timer);
2033 : 0 : input_unregister_device(priv->dev2);
2034 : 0 : kfree(priv);
2035 : 0 : }
2036 : :
2037 : 0 : static void alps_set_abs_params_st(struct alps_data *priv,
2038 : : struct input_dev *dev1)
2039 : : {
2040 : 0 : input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
2041 : 0 : input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
2042 : 0 : }
2043 : :
2044 : 0 : static void alps_set_abs_params_mt(struct alps_data *priv,
2045 : : struct input_dev *dev1)
2046 : : {
2047 : 0 : set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
2048 : 0 : input_mt_init_slots(dev1, 2, 0);
2049 : 0 : input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
2050 : 0 : input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
2051 : :
2052 : 0 : set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
2053 : 0 : set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
2054 : 0 : set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
2055 : :
2056 : 0 : input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
2057 : 0 : input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
2058 : 0 : }
2059 : :
2060 : 0 : int alps_init(struct psmouse *psmouse)
2061 : : {
2062 : : struct alps_data *priv;
2063 : 0 : struct input_dev *dev1 = psmouse->dev, *dev2;
2064 : :
2065 : : priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
2066 : 0 : dev2 = input_allocate_device();
2067 [ # # ]: 0 : if (!priv || !dev2)
2068 : : goto init_fail;
2069 : :
2070 : 0 : priv->dev2 = dev2;
2071 : 0 : setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
2072 : :
2073 : 0 : psmouse->private = priv;
2074 : :
2075 : 0 : psmouse_reset(psmouse);
2076 : :
2077 [ # # ]: 0 : if (alps_identify(psmouse, priv) < 0)
2078 : : goto init_fail;
2079 : :
2080 [ # # ]: 0 : if (priv->hw_init(psmouse))
2081 : : goto init_fail;
2082 : :
2083 : : /*
2084 : : * Undo part of setup done for us by psmouse core since touchpad
2085 : : * is not a relative device.
2086 : : */
2087 : : __clear_bit(EV_REL, dev1->evbit);
2088 : : __clear_bit(REL_X, dev1->relbit);
2089 : : __clear_bit(REL_Y, dev1->relbit);
2090 : :
2091 : : /*
2092 : : * Now set up our capabilities.
2093 : : */
2094 : 0 : dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
2095 : 0 : dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
2096 : 0 : dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
2097 : 0 : dev1->keybit[BIT_WORD(BTN_LEFT)] |=
2098 : : BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
2099 : :
2100 : 0 : dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
2101 : :
2102 : 0 : priv->set_abs_params(priv, dev1);
2103 : 0 : input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
2104 : :
2105 [ # # ]: 0 : if (priv->flags & ALPS_WHEEL) {
2106 : 0 : dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
2107 : 0 : dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
2108 : : }
2109 : :
2110 [ # # ]: 0 : if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
2111 : 0 : dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
2112 : 0 : dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
2113 : : }
2114 : :
2115 [ # # ]: 0 : if (priv->flags & ALPS_FOUR_BUTTONS) {
2116 : 0 : dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
2117 : 0 : dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
2118 : 0 : dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
2119 : 0 : dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
2120 : : } else {
2121 : 0 : dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
2122 : : }
2123 : :
2124 : 0 : snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
2125 : 0 : dev2->phys = priv->phys;
2126 : 0 : dev2->name = (priv->flags & ALPS_DUALPOINT) ?
2127 [ # # ]: 0 : "DualPoint Stick" : "ALPS PS/2 Device";
2128 : 0 : dev2->id.bustype = BUS_I8042;
2129 : 0 : dev2->id.vendor = 0x0002;
2130 : 0 : dev2->id.product = PSMOUSE_ALPS;
2131 : 0 : dev2->id.version = 0x0000;
2132 : 0 : dev2->dev.parent = &psmouse->ps2dev.serio->dev;
2133 : :
2134 : 0 : dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
2135 : 0 : dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
2136 : 0 : dev2->keybit[BIT_WORD(BTN_LEFT)] =
2137 : : BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
2138 : :
2139 [ # # ]: 0 : if (input_register_device(priv->dev2))
2140 : : goto init_fail;
2141 : :
2142 : 0 : psmouse->protocol_handler = alps_process_byte;
2143 : 0 : psmouse->poll = alps_poll;
2144 : 0 : psmouse->disconnect = alps_disconnect;
2145 : 0 : psmouse->reconnect = alps_reconnect;
2146 [ # # ]: 0 : psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6;
2147 : :
2148 : : /* We are having trouble resyncing ALPS touchpads so disable it for now */
2149 : 0 : psmouse->resync_time = 0;
2150 : :
2151 : 0 : return 0;
2152 : :
2153 : : init_fail:
2154 : 0 : psmouse_reset(psmouse);
2155 : 0 : input_free_device(dev2);
2156 : 0 : kfree(priv);
2157 : 0 : psmouse->private = NULL;
2158 : 0 : return -1;
2159 : : }
2160 : :
2161 : 0 : int alps_detect(struct psmouse *psmouse, bool set_properties)
2162 : : {
2163 : : struct alps_data dummy;
2164 : :
2165 [ # # ]: 0 : if (alps_identify(psmouse, &dummy) < 0)
2166 : : return -1;
2167 : :
2168 [ # # ]: 0 : if (set_properties) {
2169 : 0 : psmouse->vendor = "ALPS";
2170 : 0 : psmouse->name = dummy.flags & ALPS_DUALPOINT ?
2171 [ # # ]: 0 : "DualPoint TouchPad" : "GlidePoint";
2172 : 0 : psmouse->model = dummy.proto_version << 8;
2173 : : }
2174 : : return 0;
2175 : : }
2176 : :
|