Branch data Line data Source code
1 : : /*
2 : : * Synaptics TouchPad PS/2 mouse driver
3 : : *
4 : : * 2003 Dmitry Torokhov <dtor@mail.ru>
5 : : * Added support for pass-through port. Special thanks to Peter Berg Larsen
6 : : * for explaining various Synaptics quirks.
7 : : *
8 : : * 2003 Peter Osterlund <petero2@telia.com>
9 : : * Ported to 2.5 input device infrastructure.
10 : : *
11 : : * Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
12 : : * start merging tpconfig and gpm code to a xfree-input module
13 : : * adding some changes and extensions (ex. 3rd and 4th button)
14 : : *
15 : : * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
16 : : * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
17 : : * code for the special synaptics commands (from the tpconfig-source)
18 : : *
19 : : * This program is free software; you can redistribute it and/or modify it
20 : : * under the terms of the GNU General Public License version 2 as published by
21 : : * the Free Software Foundation.
22 : : *
23 : : * Trademarks are the property of their respective owners.
24 : : */
25 : :
26 : : #include <linux/module.h>
27 : : #include <linux/delay.h>
28 : : #include <linux/dmi.h>
29 : : #include <linux/input/mt.h>
30 : : #include <linux/serio.h>
31 : : #include <linux/libps2.h>
32 : : #include <linux/slab.h>
33 : : #include "psmouse.h"
34 : : #include "synaptics.h"
35 : :
36 : : /*
37 : : * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
38 : : * section 2.3.2, which says that they should be valid regardless of the
39 : : * actual size of the sensor.
40 : : * Note that newer firmware allows querying device for maximum useable
41 : : * coordinates.
42 : : */
43 : : #define XMIN 0
44 : : #define XMAX 6143
45 : : #define YMIN 0
46 : : #define YMAX 6143
47 : : #define XMIN_NOMINAL 1472
48 : : #define XMAX_NOMINAL 5472
49 : : #define YMIN_NOMINAL 1408
50 : : #define YMAX_NOMINAL 4448
51 : :
52 : : /* Size in bits of absolute position values reported by the hardware */
53 : : #define ABS_POS_BITS 13
54 : :
55 : : /*
56 : : * These values should represent the absolute maximum value that will
57 : : * be reported for a positive position value. Some Synaptics firmware
58 : : * uses this value to indicate a finger near the edge of the touchpad
59 : : * whose precise position cannot be determined.
60 : : *
61 : : * At least one touchpad is known to report positions in excess of this
62 : : * value which are actually negative values truncated to the 13-bit
63 : : * reporting range. These values have never been observed to be lower
64 : : * than 8184 (i.e. -8), so we treat all values greater than 8176 as
65 : : * negative and any other value as positive.
66 : : */
67 : : #define X_MAX_POSITIVE 8176
68 : : #define Y_MAX_POSITIVE 8176
69 : :
70 : : /*****************************************************************************
71 : : * Stuff we need even when we do not want native Synaptics support
72 : : ****************************************************************************/
73 : :
74 : : /*
75 : : * Set the synaptics touchpad mode byte by special commands
76 : : */
77 : 0 : static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
78 : : {
79 : : unsigned char param[1];
80 : :
81 [ # # ]: 0 : if (psmouse_sliced_command(psmouse, mode))
82 : : return -1;
83 : 0 : param[0] = SYN_PS_SET_MODE2;
84 [ # # ]: 0 : if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
85 : : return -1;
86 : 0 : return 0;
87 : : }
88 : :
89 : 0 : int synaptics_detect(struct psmouse *psmouse, bool set_properties)
90 : : {
91 : 0 : struct ps2dev *ps2dev = &psmouse->ps2dev;
92 : : unsigned char param[4];
93 : :
94 : 0 : param[0] = 0;
95 : :
96 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
97 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
98 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
99 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
100 : 0 : ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
101 : :
102 [ # # ]: 0 : if (param[1] != 0x47)
103 : : return -ENODEV;
104 : :
105 [ # # ]: 0 : if (set_properties) {
106 : 0 : psmouse->vendor = "Synaptics";
107 : 0 : psmouse->name = "TouchPad";
108 : : }
109 : :
110 : : return 0;
111 : : }
112 : :
113 : 0 : void synaptics_reset(struct psmouse *psmouse)
114 : : {
115 : : /* reset touchpad back to relative mode, gestures enabled */
116 : 0 : synaptics_mode_cmd(psmouse, 0);
117 : 0 : }
118 : :
119 : : #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
120 : :
121 : : /*****************************************************************************
122 : : * Synaptics communications functions
123 : : ****************************************************************************/
124 : :
125 : : /*
126 : : * Synaptics touchpads report the y coordinate from bottom to top, which is
127 : : * opposite from what userspace expects.
128 : : * This function is used to invert y before reporting.
129 : : */
130 : : static int synaptics_invert_y(int y)
131 : : {
132 : 0 : return YMAX_NOMINAL + YMIN_NOMINAL - y;
133 : : }
134 : :
135 : : /*
136 : : * Send a command to the synpatics touchpad by special commands
137 : : */
138 : 0 : static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
139 : : {
140 [ # # ]: 0 : if (psmouse_sliced_command(psmouse, c))
141 : : return -1;
142 [ # # ]: 0 : if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
143 : : return -1;
144 : 0 : return 0;
145 : : }
146 : :
147 : : /*
148 : : * Read the model-id bytes from the touchpad
149 : : * see also SYN_MODEL_* macros
150 : : */
151 : 0 : static int synaptics_model_id(struct psmouse *psmouse)
152 : : {
153 : 0 : struct synaptics_data *priv = psmouse->private;
154 : : unsigned char mi[3];
155 : :
156 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
157 : : return -1;
158 : 0 : priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
159 : 0 : return 0;
160 : : }
161 : :
162 : : /*
163 : : * Read the board id from the touchpad
164 : : * The board id is encoded in the "QUERY MODES" response
165 : : */
166 : 0 : static int synaptics_board_id(struct psmouse *psmouse)
167 : : {
168 : 0 : struct synaptics_data *priv = psmouse->private;
169 : : unsigned char bid[3];
170 : :
171 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid))
172 : : return -1;
173 : 0 : priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1];
174 : 0 : return 0;
175 : : }
176 : :
177 : : /*
178 : : * Read the firmware id from the touchpad
179 : : */
180 : 0 : static int synaptics_firmware_id(struct psmouse *psmouse)
181 : : {
182 : 0 : struct synaptics_data *priv = psmouse->private;
183 : : unsigned char fwid[3];
184 : :
185 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid))
186 : : return -1;
187 : 0 : priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2];
188 : 0 : return 0;
189 : : }
190 : :
191 : : /*
192 : : * Read the capability-bits from the touchpad
193 : : * see also the SYN_CAP_* macros
194 : : */
195 : 0 : static int synaptics_capability(struct psmouse *psmouse)
196 : : {
197 : 0 : struct synaptics_data *priv = psmouse->private;
198 : : unsigned char cap[3];
199 : :
200 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
201 : : return -1;
202 : 0 : priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
203 : 0 : priv->ext_cap = priv->ext_cap_0c = 0;
204 : :
205 : : /*
206 : : * Older firmwares had submodel ID fixed to 0x47
207 : : */
208 [ # # ][ # # ]: 0 : if (SYN_ID_FULL(priv->identity) < 0x705 &&
209 : 0 : SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) {
210 : : return -1;
211 : : }
212 : :
213 : : /*
214 : : * Unless capExtended is set the rest of the flags should be ignored
215 : : */
216 [ # # ]: 0 : if (!SYN_CAP_EXTENDED(priv->capabilities))
217 : 0 : priv->capabilities = 0;
218 : :
219 [ # # ]: 0 : if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
220 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
221 : 0 : psmouse_warn(psmouse,
222 : : "device claims to have extended capabilities, but I'm not able to read them.\n");
223 : : } else {
224 : 0 : priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
225 : :
226 : : /*
227 : : * if nExtBtn is greater than 8 it should be considered
228 : : * invalid and treated as 0
229 : : */
230 [ # # ]: 0 : if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
231 : 0 : priv->ext_cap &= 0xff0fff;
232 : : }
233 : : }
234 : :
235 [ # # ]: 0 : if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
236 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
237 : 0 : psmouse_warn(psmouse,
238 : : "device claims to have extended capability 0x0c, but I'm not able to read it.\n");
239 : : } else {
240 : 0 : priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
241 : : }
242 : : }
243 : :
244 : : return 0;
245 : : }
246 : :
247 : : /*
248 : : * Identify Touchpad
249 : : * See also the SYN_ID_* macros
250 : : */
251 : 0 : static int synaptics_identify(struct psmouse *psmouse)
252 : : {
253 : 0 : struct synaptics_data *priv = psmouse->private;
254 : : unsigned char id[3];
255 : :
256 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
257 : : return -1;
258 : 0 : priv->identity = (id[0]<<16) | (id[1]<<8) | id[2];
259 [ # # ]: 0 : if (SYN_ID_IS_SYNAPTICS(priv->identity))
260 : : return 0;
261 : 0 : return -1;
262 : : }
263 : :
264 : : /*
265 : : * Read touchpad resolution and maximum reported coordinates
266 : : * Resolution is left zero if touchpad does not support the query
267 : : */
268 : 0 : static int synaptics_resolution(struct psmouse *psmouse)
269 : : {
270 : 0 : struct synaptics_data *priv = psmouse->private;
271 : : unsigned char resp[3];
272 : :
273 [ # # ]: 0 : if (SYN_ID_MAJOR(priv->identity) < 4)
274 : : return 0;
275 : :
276 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
277 [ # # ][ # # ]: 0 : if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
[ # # ]
278 : 0 : priv->x_res = resp[0]; /* x resolution in units/mm */
279 : 0 : priv->y_res = resp[2]; /* y resolution in units/mm */
280 : : }
281 : : }
282 : :
283 [ # # ][ # # ]: 0 : if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
284 : 0 : SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
285 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
286 : 0 : psmouse_warn(psmouse,
287 : : "device claims to have max coordinates query, but I'm not able to read it.\n");
288 : : } else {
289 : 0 : priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
290 : 0 : priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
291 : : }
292 : : }
293 : :
294 [ # # ][ # # ]: 0 : if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
295 : 0 : SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
296 [ # # ]: 0 : if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
297 : 0 : psmouse_warn(psmouse,
298 : : "device claims to have min coordinates query, but I'm not able to read it.\n");
299 : : } else {
300 : 0 : priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
301 : 0 : priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
302 : : }
303 : : }
304 : :
305 : : return 0;
306 : : }
307 : :
308 : 0 : static int synaptics_query_hardware(struct psmouse *psmouse)
309 : : {
310 [ # # ]: 0 : if (synaptics_identify(psmouse))
311 : : return -1;
312 [ # # ]: 0 : if (synaptics_model_id(psmouse))
313 : : return -1;
314 [ # # ]: 0 : if (synaptics_firmware_id(psmouse))
315 : : return -1;
316 [ # # ]: 0 : if (synaptics_board_id(psmouse))
317 : : return -1;
318 [ # # ]: 0 : if (synaptics_capability(psmouse))
319 : : return -1;
320 [ # # ]: 0 : if (synaptics_resolution(psmouse))
321 : : return -1;
322 : :
323 : 0 : return 0;
324 : : }
325 : :
326 : 0 : static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
327 : : {
328 : : static unsigned char param = 0xc8;
329 : 0 : struct synaptics_data *priv = psmouse->private;
330 : :
331 [ # # ]: 0 : if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
332 : : SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
333 : : return 0;
334 : :
335 [ # # ]: 0 : if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
336 : : return -1;
337 : :
338 [ # # ]: 0 : if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE))
339 : : return -1;
340 : :
341 : : /* Advanced gesture mode also sends multi finger data */
342 : 0 : priv->capabilities |= BIT(1);
343 : :
344 : 0 : return 0;
345 : : }
346 : :
347 : 0 : static int synaptics_set_mode(struct psmouse *psmouse)
348 : : {
349 : 0 : struct synaptics_data *priv = psmouse->private;
350 : :
351 : 0 : priv->mode = 0;
352 [ # # ]: 0 : if (priv->absolute_mode)
353 : 0 : priv->mode |= SYN_BIT_ABSOLUTE_MODE;
354 [ # # ]: 0 : if (priv->disable_gesture)
355 : 0 : priv->mode |= SYN_BIT_DISABLE_GESTURE;
356 [ # # ]: 0 : if (psmouse->rate >= 80)
357 : 0 : priv->mode |= SYN_BIT_HIGH_RATE;
358 [ # # ]: 0 : if (SYN_CAP_EXTENDED(priv->capabilities))
359 : 0 : priv->mode |= SYN_BIT_W_MODE;
360 : :
361 [ # # ]: 0 : if (synaptics_mode_cmd(psmouse, priv->mode))
362 : : return -1;
363 : :
364 [ # # # # ]: 0 : if (priv->absolute_mode &&
365 : 0 : synaptics_set_advanced_gesture_mode(psmouse)) {
366 : 0 : psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
367 : 0 : return -1;
368 : : }
369 : :
370 : : return 0;
371 : : }
372 : :
373 : 0 : static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
374 : : {
375 : 0 : struct synaptics_data *priv = psmouse->private;
376 : :
377 [ # # ]: 0 : if (rate >= 80) {
378 : 0 : priv->mode |= SYN_BIT_HIGH_RATE;
379 : 0 : psmouse->rate = 80;
380 : : } else {
381 : 0 : priv->mode &= ~SYN_BIT_HIGH_RATE;
382 : 0 : psmouse->rate = 40;
383 : : }
384 : :
385 : 0 : synaptics_mode_cmd(psmouse, priv->mode);
386 : 0 : }
387 : :
388 : : /*****************************************************************************
389 : : * Synaptics pass-through PS/2 port support
390 : : ****************************************************************************/
391 : 0 : static int synaptics_pt_write(struct serio *serio, unsigned char c)
392 : : {
393 : 0 : struct psmouse *parent = serio_get_drvdata(serio->parent);
394 : 0 : char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
395 : :
396 [ # # ]: 0 : if (psmouse_sliced_command(parent, c))
397 : : return -1;
398 [ # # ]: 0 : if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE))
399 : : return -1;
400 : 0 : return 0;
401 : : }
402 : :
403 : 0 : static int synaptics_pt_start(struct serio *serio)
404 : : {
405 : 0 : struct psmouse *parent = serio_get_drvdata(serio->parent);
406 : 0 : struct synaptics_data *priv = parent->private;
407 : :
408 : 0 : serio_pause_rx(parent->ps2dev.serio);
409 : 0 : priv->pt_port = serio;
410 : 0 : serio_continue_rx(parent->ps2dev.serio);
411 : :
412 : 0 : return 0;
413 : : }
414 : :
415 : 0 : static void synaptics_pt_stop(struct serio *serio)
416 : : {
417 : 0 : struct psmouse *parent = serio_get_drvdata(serio->parent);
418 : 0 : struct synaptics_data *priv = parent->private;
419 : :
420 : 0 : serio_pause_rx(parent->ps2dev.serio);
421 : 0 : priv->pt_port = NULL;
422 : 0 : serio_continue_rx(parent->ps2dev.serio);
423 : 0 : }
424 : :
425 : : static int synaptics_is_pt_packet(unsigned char *buf)
426 : : {
427 [ # # ][ # # ]: 0 : return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
428 : : }
429 : :
430 : 0 : static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
431 : : {
432 : : struct psmouse *child = serio_get_drvdata(ptport);
433 : :
434 [ # # ][ # # ]: 0 : if (child && child->state == PSMOUSE_ACTIVATED) {
435 : 0 : serio_interrupt(ptport, packet[1], 0);
436 : 0 : serio_interrupt(ptport, packet[4], 0);
437 : 0 : serio_interrupt(ptport, packet[5], 0);
438 [ # # ]: 0 : if (child->pktsize == 4)
439 : 0 : serio_interrupt(ptport, packet[2], 0);
440 : : } else
441 : 0 : serio_interrupt(ptport, packet[1], 0);
442 : 0 : }
443 : :
444 : 0 : static void synaptics_pt_activate(struct psmouse *psmouse)
445 : : {
446 : 0 : struct synaptics_data *priv = psmouse->private;
447 : 0 : struct psmouse *child = serio_get_drvdata(priv->pt_port);
448 : :
449 : : /* adjust the touchpad to child's choice of protocol */
450 [ # # ]: 0 : if (child) {
451 [ # # ]: 0 : if (child->pktsize == 4)
452 : 0 : priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT;
453 : : else
454 : 0 : priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT;
455 : :
456 [ # # ]: 0 : if (synaptics_mode_cmd(psmouse, priv->mode))
457 : 0 : psmouse_warn(psmouse,
458 : : "failed to switch guest protocol\n");
459 : : }
460 : 0 : }
461 : :
462 : 0 : static void synaptics_pt_create(struct psmouse *psmouse)
463 : : {
464 : : struct serio *serio;
465 : :
466 : : serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
467 [ # # ]: 0 : if (!serio) {
468 : 0 : psmouse_err(psmouse,
469 : : "not enough memory for pass-through port\n");
470 : 0 : return;
471 : : }
472 : :
473 : 0 : serio->id.type = SERIO_PS_PSTHRU;
474 : 0 : strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
475 : 0 : strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
476 : 0 : serio->write = synaptics_pt_write;
477 : 0 : serio->start = synaptics_pt_start;
478 : 0 : serio->stop = synaptics_pt_stop;
479 : 0 : serio->parent = psmouse->ps2dev.serio;
480 : :
481 : 0 : psmouse->pt_activate = synaptics_pt_activate;
482 : :
483 : 0 : psmouse_info(psmouse, "serio: %s port at %s\n",
484 : : serio->name, psmouse->phys);
485 : 0 : serio_register_port(serio);
486 : : }
487 : :
488 : : /*****************************************************************************
489 : : * Functions to interpret the absolute mode packets
490 : : ****************************************************************************/
491 : :
492 : : static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count,
493 : : int sgm, int agm)
494 : : {
495 : 0 : state->count = count;
496 : 0 : state->sgm = sgm;
497 : 0 : state->agm = agm;
498 : : }
499 : :
500 : 0 : static void synaptics_parse_agm(const unsigned char buf[],
501 : : struct synaptics_data *priv,
502 : : struct synaptics_hw_state *hw)
503 : : {
504 : : struct synaptics_hw_state *agm = &priv->agm;
505 : : int agm_packet_type;
506 : :
507 : 0 : agm_packet_type = (buf[5] & 0x30) >> 4;
508 [ # # # ]: 0 : switch (agm_packet_type) {
509 : : case 1:
510 : : /* Gesture packet: (x, y, z) half resolution */
511 : 0 : agm->w = hw->w;
512 : 0 : agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
513 : 0 : agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
514 : 0 : agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
515 : : break;
516 : :
517 : : case 2:
518 : : /* AGM-CONTACT packet: (count, sgm, agm) */
519 : 0 : synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]);
520 : : break;
521 : :
522 : : default:
523 : : break;
524 : : }
525 : :
526 : : /* Record that at least one AGM has been received since last SGM */
527 : 0 : priv->agm_pending = true;
528 : 0 : }
529 : :
530 : 0 : static int synaptics_parse_hw_state(const unsigned char buf[],
531 : : struct synaptics_data *priv,
532 : : struct synaptics_hw_state *hw)
533 : : {
534 : 0 : memset(hw, 0, sizeof(struct synaptics_hw_state));
535 : :
536 [ # # ]: 0 : if (SYN_MODEL_NEWABS(priv->model_id)) {
537 : 0 : hw->w = (((buf[0] & 0x30) >> 2) |
538 : 0 : ((buf[0] & 0x04) >> 1) |
539 : 0 : ((buf[3] & 0x04) >> 2));
540 : :
541 : 0 : hw->left = (buf[0] & 0x01) ? 1 : 0;
542 : 0 : hw->right = (buf[0] & 0x02) ? 1 : 0;
543 : :
544 [ # # ]: 0 : if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
545 : : /*
546 : : * Clickpad's button is transmitted as middle button,
547 : : * however, since it is primary button, we will report
548 : : * it as BTN_LEFT.
549 : : */
550 : 0 : hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
551 : :
552 [ # # ]: 0 : } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
553 : 0 : hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
554 [ # # ]: 0 : if (hw->w == 2)
555 : 0 : hw->scroll = (signed char)(buf[1]);
556 : : }
557 : :
558 [ # # ]: 0 : if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
559 : 0 : hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
560 : 0 : hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
561 : : }
562 : :
563 [ # # ]: 0 : if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
564 [ # # ]: 0 : SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
565 : : hw->w == 2) {
566 : 0 : synaptics_parse_agm(buf, priv, hw);
567 : 0 : return 1;
568 : : }
569 : :
570 : 0 : hw->x = (((buf[3] & 0x10) << 8) |
571 : 0 : ((buf[1] & 0x0f) << 8) |
572 : 0 : buf[4]);
573 : 0 : hw->y = (((buf[3] & 0x20) << 7) |
574 : 0 : ((buf[1] & 0xf0) << 4) |
575 : 0 : buf[5]);
576 : 0 : hw->z = buf[2];
577 : :
578 [ # # ][ # # ]: 0 : if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
579 : 0 : ((buf[0] ^ buf[3]) & 0x02)) {
580 [ # # # # : 0 : switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
# ]
581 : : default:
582 : : /*
583 : : * if nExtBtn is greater than 8 it should be
584 : : * considered invalid and treated as 0
585 : : */
586 : : break;
587 : : case 8:
588 [ # # ]: 0 : hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
589 [ # # ]: 0 : hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
590 : : case 6:
591 [ # # ]: 0 : hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
592 [ # # ]: 0 : hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
593 : : case 4:
594 [ # # ]: 0 : hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
595 [ # # ]: 0 : hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
596 : : case 2:
597 [ # # ]: 0 : hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
598 : 0 : hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
599 : : }
600 : : }
601 : : } else {
602 : 0 : hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
603 : 0 : hw->y = (((buf[4] & 0x1f) << 8) | buf[5]);
604 : :
605 : 0 : hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
606 : 0 : hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
607 : :
608 : 0 : hw->left = (buf[0] & 0x01) ? 1 : 0;
609 : 0 : hw->right = (buf[0] & 0x02) ? 1 : 0;
610 : : }
611 : :
612 : : /*
613 : : * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
614 : : * is used by some firmware to indicate a finger at the edge of
615 : : * the touchpad whose precise position cannot be determined, so
616 : : * convert these values to the maximum axis value.
617 : : */
618 [ # # ]: 0 : if (hw->x > X_MAX_POSITIVE)
619 : 0 : hw->x -= 1 << ABS_POS_BITS;
620 [ # # ]: 0 : else if (hw->x == X_MAX_POSITIVE)
621 : 0 : hw->x = XMAX;
622 : :
623 [ # # ]: 0 : if (hw->y > Y_MAX_POSITIVE)
624 : 0 : hw->y -= 1 << ABS_POS_BITS;
625 [ # # ]: 0 : else if (hw->y == Y_MAX_POSITIVE)
626 : 0 : hw->y = YMAX;
627 : :
628 : : return 0;
629 : : }
630 : :
631 : 0 : static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
632 : : bool active, int x, int y)
633 : : {
634 : : input_mt_slot(dev, slot);
635 : 0 : input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
636 [ # # ]: 0 : if (active) {
637 : : input_report_abs(dev, ABS_MT_POSITION_X, x);
638 : : input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y));
639 : : }
640 : 0 : }
641 : :
642 : 0 : static void synaptics_report_semi_mt_data(struct input_dev *dev,
643 : : const struct synaptics_hw_state *a,
644 : : const struct synaptics_hw_state *b,
645 : : int num_fingers)
646 : : {
647 [ # # ]: 0 : if (num_fingers >= 2) {
648 : 0 : synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
649 : 0 : min(a->y, b->y));
650 : 0 : synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
651 : 0 : max(a->y, b->y));
652 [ # # ]: 0 : } else if (num_fingers == 1) {
653 : 0 : synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
654 : 0 : synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
655 : : } else {
656 : 0 : synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
657 : 0 : synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
658 : : }
659 : 0 : }
660 : :
661 : 0 : static void synaptics_report_buttons(struct psmouse *psmouse,
662 : : const struct synaptics_hw_state *hw)
663 : : {
664 : 0 : struct input_dev *dev = psmouse->dev;
665 : 0 : struct synaptics_data *priv = psmouse->private;
666 : : int i;
667 : :
668 : 0 : input_report_key(dev, BTN_LEFT, hw->left);
669 : 0 : input_report_key(dev, BTN_RIGHT, hw->right);
670 : :
671 [ # # ]: 0 : if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
672 : 0 : input_report_key(dev, BTN_MIDDLE, hw->middle);
673 : :
674 [ # # ]: 0 : if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
675 : 0 : input_report_key(dev, BTN_FORWARD, hw->up);
676 : 0 : input_report_key(dev, BTN_BACK, hw->down);
677 : : }
678 : :
679 [ # # ]: 0 : for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
680 : 0 : input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
681 : 0 : }
682 : :
683 : 0 : static void synaptics_report_slot(struct input_dev *dev, int slot,
684 : : const struct synaptics_hw_state *hw)
685 : : {
686 : : input_mt_slot(dev, slot);
687 : 0 : input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL));
688 [ # # ]: 0 : if (!hw)
689 : 0 : return;
690 : :
691 : 0 : input_report_abs(dev, ABS_MT_POSITION_X, hw->x);
692 : 0 : input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y));
693 : 0 : input_report_abs(dev, ABS_MT_PRESSURE, hw->z);
694 : : }
695 : :
696 : 0 : static void synaptics_report_mt_data(struct psmouse *psmouse,
697 : : struct synaptics_mt_state *mt_state,
698 : : const struct synaptics_hw_state *sgm)
699 : : {
700 : 0 : struct input_dev *dev = psmouse->dev;
701 : 0 : struct synaptics_data *priv = psmouse->private;
702 : 0 : struct synaptics_hw_state *agm = &priv->agm;
703 : : struct synaptics_mt_state *old = &priv->mt_state;
704 : :
705 [ # # # ]: 0 : switch (mt_state->count) {
706 : : case 0:
707 : 0 : synaptics_report_slot(dev, 0, NULL);
708 : 0 : synaptics_report_slot(dev, 1, NULL);
709 : 0 : break;
710 : : case 1:
711 [ # # ]: 0 : if (mt_state->sgm == -1) {
712 : 0 : synaptics_report_slot(dev, 0, NULL);
713 : 0 : synaptics_report_slot(dev, 1, NULL);
714 [ # # ]: 0 : } else if (mt_state->sgm == 0) {
715 : 0 : synaptics_report_slot(dev, 0, sgm);
716 : 0 : synaptics_report_slot(dev, 1, NULL);
717 : : } else {
718 : 0 : synaptics_report_slot(dev, 0, NULL);
719 : 0 : synaptics_report_slot(dev, 1, sgm);
720 : : }
721 : : break;
722 : : default:
723 : : /*
724 : : * If the finger slot contained in SGM is valid, and either
725 : : * hasn't changed, or is new, or the old SGM has now moved to
726 : : * AGM, then report SGM in MTB slot 0.
727 : : * Otherwise, empty MTB slot 0.
728 : : */
729 [ # # ][ # # ]: 0 : if (mt_state->sgm != -1 &&
730 [ # # ]: 0 : (mt_state->sgm == old->sgm ||
731 [ # # ]: 0 : old->sgm == -1 || mt_state->agm == old->sgm))
732 : 0 : synaptics_report_slot(dev, 0, sgm);
733 : : else
734 : 0 : synaptics_report_slot(dev, 0, NULL);
735 : :
736 : : /*
737 : : * If the finger slot contained in AGM is valid, and either
738 : : * hasn't changed, or is new, then report AGM in MTB slot 1.
739 : : * Otherwise, empty MTB slot 1.
740 : : *
741 : : * However, in the case where the AGM is new, make sure that
742 : : * that it is either the same as the old SGM, or there was no
743 : : * SGM.
744 : : *
745 : : * Otherwise, if the SGM was just 1, and the new AGM is 2, then
746 : : * the new AGM will keep the old SGM's tracking ID, which can
747 : : * cause apparent drumroll. This happens if in the following
748 : : * valid finger sequence:
749 : : *
750 : : * Action SGM AGM (MTB slot:Contact)
751 : : * 1. Touch contact 0 (0:0)
752 : : * 2. Touch contact 1 (0:0, 1:1)
753 : : * 3. Lift contact 0 (1:1)
754 : : * 4. Touch contacts 2,3 (0:2, 1:3)
755 : : *
756 : : * In step 4, contact 3, in AGM must not be given the same
757 : : * tracking ID as contact 1 had in step 3. To avoid this,
758 : : * the first agm with contact 3 is dropped and slot 1 is
759 : : * invalidated (tracking ID = -1).
760 : : */
761 [ # # ][ # # ]: 0 : if (mt_state->agm != -1 &&
762 [ # # ]: 0 : (mt_state->agm == old->agm ||
763 [ # # ]: 0 : (old->agm == -1 &&
764 [ # # ]: 0 : (old->sgm == -1 || mt_state->agm == old->sgm))))
765 : 0 : synaptics_report_slot(dev, 1, agm);
766 : : else
767 : 0 : synaptics_report_slot(dev, 1, NULL);
768 : : break;
769 : : }
770 : :
771 : : /* Don't use active slot count to generate BTN_TOOL events. */
772 : 0 : input_mt_report_pointer_emulation(dev, false);
773 : :
774 : : /* Send the number of fingers reported by touchpad itself. */
775 : 0 : input_mt_report_finger_count(dev, mt_state->count);
776 : :
777 : 0 : synaptics_report_buttons(psmouse, sgm);
778 : :
779 : : input_sync(dev);
780 : 0 : }
781 : :
782 : : /* Handle case where mt_state->count = 0 */
783 : : static void synaptics_image_sensor_0f(struct synaptics_data *priv,
784 : : struct synaptics_mt_state *mt_state)
785 : : {
786 : : synaptics_mt_state_set(mt_state, 0, -1, -1);
787 : 0 : priv->mt_state_lost = false;
788 : : }
789 : :
790 : : /* Handle case where mt_state->count = 1 */
791 : 0 : static void synaptics_image_sensor_1f(struct synaptics_data *priv,
792 : : struct synaptics_mt_state *mt_state)
793 : : {
794 : : struct synaptics_hw_state *agm = &priv->agm;
795 : : struct synaptics_mt_state *old = &priv->mt_state;
796 : :
797 : : /*
798 : : * If the last AGM was (0,0,0), and there is only one finger left,
799 : : * then we absolutely know that SGM contains slot 0, and all other
800 : : * fingers have been removed.
801 : : */
802 [ # # ][ # # ]: 0 : if (priv->agm_pending && agm->z == 0) {
803 : : synaptics_mt_state_set(mt_state, 1, 0, -1);
804 : 0 : priv->mt_state_lost = false;
805 : 0 : return;
806 : : }
807 : :
808 [ # # # # : 0 : switch (old->count) {
# ]
809 : : case 0:
810 : : synaptics_mt_state_set(mt_state, 1, 0, -1);
811 : : break;
812 : : case 1:
813 : : /*
814 : : * If mt_state_lost, then the previous transition was 3->1,
815 : : * and SGM now contains either slot 0 or 1, but we don't know
816 : : * which. So, we just assume that the SGM now contains slot 1.
817 : : *
818 : : * If pending AGM and either:
819 : : * (a) the previous SGM slot contains slot 0, or
820 : : * (b) there was no SGM slot
821 : : * then, the SGM now contains slot 1
822 : : *
823 : : * Case (a) happens with very rapid "drum roll" gestures, where
824 : : * slot 0 finger is lifted and a new slot 1 finger touches
825 : : * within one reporting interval.
826 : : *
827 : : * Case (b) happens if initially two or more fingers tap
828 : : * briefly, and all but one lift before the end of the first
829 : : * reporting interval.
830 : : *
831 : : * (In both these cases, slot 0 will becomes empty, so SGM
832 : : * contains slot 1 with the new finger)
833 : : *
834 : : * Else, if there was no previous SGM, it now contains slot 0.
835 : : *
836 : : * Otherwise, SGM still contains the same slot.
837 : : */
838 [ # # ][ # # ]: 0 : if (priv->mt_state_lost ||
839 [ # # ]: 0 : (priv->agm_pending && old->sgm <= 0))
840 : : synaptics_mt_state_set(mt_state, 1, 1, -1);
841 [ # # ]: 0 : else if (old->sgm == -1)
842 : : synaptics_mt_state_set(mt_state, 1, 0, -1);
843 : : break;
844 : : case 2:
845 : : /*
846 : : * If mt_state_lost, we don't know which finger SGM contains.
847 : : *
848 : : * So, report 1 finger, but with both slots empty.
849 : : * We will use slot 1 on subsequent 1->1
850 : : */
851 [ # # ]: 0 : if (priv->mt_state_lost) {
852 : : synaptics_mt_state_set(mt_state, 1, -1, -1);
853 : : break;
854 : : }
855 : : /*
856 : : * Since the last AGM was NOT (0,0,0), it was the finger in
857 : : * slot 0 that has been removed.
858 : : * So, SGM now contains previous AGM's slot, and AGM is now
859 : : * empty.
860 : : */
861 : 0 : synaptics_mt_state_set(mt_state, 1, old->agm, -1);
862 : : break;
863 : : case 3:
864 : : /*
865 : : * Since last AGM was not (0,0,0), we don't know which finger
866 : : * is left.
867 : : *
868 : : * So, report 1 finger, but with both slots empty.
869 : : * We will use slot 1 on subsequent 1->1
870 : : */
871 : : synaptics_mt_state_set(mt_state, 1, -1, -1);
872 : 0 : priv->mt_state_lost = true;
873 : 0 : break;
874 : : case 4:
875 : : case 5:
876 : : /* mt_state was updated by AGM-CONTACT packet */
877 : : break;
878 : : }
879 : : }
880 : :
881 : : /* Handle case where mt_state->count = 2 */
882 : 0 : static void synaptics_image_sensor_2f(struct synaptics_data *priv,
883 : : struct synaptics_mt_state *mt_state)
884 : : {
885 : : struct synaptics_mt_state *old = &priv->mt_state;
886 : :
887 [ # # # # : 0 : switch (old->count) {
# ]
888 : : case 0:
889 : : synaptics_mt_state_set(mt_state, 2, 0, 1);
890 : : break;
891 : : case 1:
892 : : /*
893 : : * If previous SGM contained slot 1 or higher, SGM now contains
894 : : * slot 0 (the newly touching finger) and AGM contains SGM's
895 : : * previous slot.
896 : : *
897 : : * Otherwise, SGM still contains slot 0 and AGM now contains
898 : : * slot 1.
899 : : */
900 [ # # ]: 0 : if (old->sgm >= 1)
901 : : synaptics_mt_state_set(mt_state, 2, 0, old->sgm);
902 : : else
903 : : synaptics_mt_state_set(mt_state, 2, 0, 1);
904 : : break;
905 : : case 2:
906 : : /*
907 : : * If mt_state_lost, SGM now contains either finger 1 or 2, but
908 : : * we don't know which.
909 : : * So, we just assume that the SGM contains slot 0 and AGM 1.
910 : : */
911 [ # # ]: 0 : if (priv->mt_state_lost)
912 : : synaptics_mt_state_set(mt_state, 2, 0, 1);
913 : : /*
914 : : * Otherwise, use the same mt_state, since it either hasn't
915 : : * changed, or was updated by a recently received AGM-CONTACT
916 : : * packet.
917 : : */
918 : : break;
919 : : case 3:
920 : : /*
921 : : * 3->2 transitions have two unsolvable problems:
922 : : * 1) no indication is given which finger was removed
923 : : * 2) no way to tell if agm packet was for finger 3
924 : : * before 3->2, or finger 2 after 3->2.
925 : : *
926 : : * So, report 2 fingers, but empty all slots.
927 : : * We will guess slots [0,1] on subsequent 2->2.
928 : : */
929 : : synaptics_mt_state_set(mt_state, 2, -1, -1);
930 : 0 : priv->mt_state_lost = true;
931 : 0 : break;
932 : : case 4:
933 : : case 5:
934 : : /* mt_state was updated by AGM-CONTACT packet */
935 : : break;
936 : : }
937 : 0 : }
938 : :
939 : : /* Handle case where mt_state->count = 3 */
940 : 0 : static void synaptics_image_sensor_3f(struct synaptics_data *priv,
941 : : struct synaptics_mt_state *mt_state)
942 : : {
943 : : struct synaptics_mt_state *old = &priv->mt_state;
944 : :
945 [ # # # # : 0 : switch (old->count) {
# ]
946 : : case 0:
947 : : synaptics_mt_state_set(mt_state, 3, 0, 2);
948 : : break;
949 : : case 1:
950 : : /*
951 : : * If previous SGM contained slot 2 or higher, SGM now contains
952 : : * slot 0 (one of the newly touching fingers) and AGM contains
953 : : * SGM's previous slot.
954 : : *
955 : : * Otherwise, SGM now contains slot 0 and AGM contains slot 2.
956 : : */
957 [ # # ]: 0 : if (old->sgm >= 2)
958 : : synaptics_mt_state_set(mt_state, 3, 0, old->sgm);
959 : : else
960 : : synaptics_mt_state_set(mt_state, 3, 0, 2);
961 : : break;
962 : : case 2:
963 : : /*
964 : : * If the AGM previously contained slot 3 or higher, then the
965 : : * newly touching finger is in the lowest available slot.
966 : : *
967 : : * If SGM was previously 1 or higher, then the new SGM is
968 : : * now slot 0 (with a new finger), otherwise, the new finger
969 : : * is now in a hidden slot between 0 and AGM's slot.
970 : : *
971 : : * In all such cases, the SGM now contains slot 0, and the AGM
972 : : * continues to contain the same slot as before.
973 : : */
974 [ # # ]: 0 : if (old->agm >= 3) {
975 : : synaptics_mt_state_set(mt_state, 3, 0, old->agm);
976 : : break;
977 : : }
978 : :
979 : : /*
980 : : * After some 3->1 and all 3->2 transitions, we lose track
981 : : * of which slot is reported by SGM and AGM.
982 : : *
983 : : * For 2->3 in this state, report 3 fingers, but empty all
984 : : * slots, and we will guess (0,2) on a subsequent 0->3.
985 : : *
986 : : * To userspace, the resulting transition will look like:
987 : : * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2]
988 : : */
989 [ # # ]: 0 : if (priv->mt_state_lost) {
990 : : synaptics_mt_state_set(mt_state, 3, -1, -1);
991 : : break;
992 : : }
993 : :
994 : : /*
995 : : * If the (SGM,AGM) really previously contained slots (0, 1),
996 : : * then we cannot know what slot was just reported by the AGM,
997 : : * because the 2->3 transition can occur either before or after
998 : : * the AGM packet. Thus, this most recent AGM could contain
999 : : * either the same old slot 1 or the new slot 2.
1000 : : * Subsequent AGMs will be reporting slot 2.
1001 : : *
1002 : : * To userspace, the resulting transition will look like:
1003 : : * 2:[0,1] -> 3:[0,-1] -> 3:[0,2]
1004 : : */
1005 : : synaptics_mt_state_set(mt_state, 3, 0, -1);
1006 : : break;
1007 : : case 3:
1008 : : /*
1009 : : * If, for whatever reason, the previous agm was invalid,
1010 : : * Assume SGM now contains slot 0, AGM now contains slot 2.
1011 : : */
1012 [ # # ]: 0 : if (old->agm <= 2)
1013 : : synaptics_mt_state_set(mt_state, 3, 0, 2);
1014 : : /*
1015 : : * mt_state either hasn't changed, or was updated by a recently
1016 : : * received AGM-CONTACT packet.
1017 : : */
1018 : : break;
1019 : :
1020 : : case 4:
1021 : : case 5:
1022 : : /* mt_state was updated by AGM-CONTACT packet */
1023 : : break;
1024 : : }
1025 : 0 : }
1026 : :
1027 : : /* Handle case where mt_state->count = 4, or = 5 */
1028 : : static void synaptics_image_sensor_45f(struct synaptics_data *priv,
1029 : : struct synaptics_mt_state *mt_state)
1030 : : {
1031 : : /* mt_state was updated correctly by AGM-CONTACT packet */
1032 : 0 : priv->mt_state_lost = false;
1033 : : }
1034 : :
1035 : 0 : static void synaptics_image_sensor_process(struct psmouse *psmouse,
1036 : : struct synaptics_hw_state *sgm)
1037 : : {
1038 : 0 : struct synaptics_data *priv = psmouse->private;
1039 : : struct synaptics_hw_state *agm = &priv->agm;
1040 : : struct synaptics_mt_state mt_state;
1041 : :
1042 : : /* Initialize using current mt_state (as updated by last agm) */
1043 : 0 : mt_state = agm->mt_state;
1044 : :
1045 : : /*
1046 : : * Update mt_state using the new finger count and current mt_state.
1047 : : */
1048 [ # # ]: 0 : if (sgm->z == 0)
1049 : : synaptics_image_sensor_0f(priv, &mt_state);
1050 [ # # ]: 0 : else if (sgm->w >= 4)
1051 : 0 : synaptics_image_sensor_1f(priv, &mt_state);
1052 [ # # ]: 0 : else if (sgm->w == 0)
1053 : 0 : synaptics_image_sensor_2f(priv, &mt_state);
1054 [ # # ][ # # ]: 0 : else if (sgm->w == 1 && mt_state.count <= 3)
1055 : 0 : synaptics_image_sensor_3f(priv, &mt_state);
1056 : : else
1057 : : synaptics_image_sensor_45f(priv, &mt_state);
1058 : :
1059 : : /* Send resulting input events to user space */
1060 : 0 : synaptics_report_mt_data(psmouse, &mt_state, sgm);
1061 : :
1062 : : /* Store updated mt_state */
1063 : 0 : priv->mt_state = agm->mt_state = mt_state;
1064 : 0 : priv->agm_pending = false;
1065 : 0 : }
1066 : :
1067 : : /*
1068 : : * called for each full received packet from the touchpad
1069 : : */
1070 : 0 : static void synaptics_process_packet(struct psmouse *psmouse)
1071 : : {
1072 : 0 : struct input_dev *dev = psmouse->dev;
1073 : 0 : struct synaptics_data *priv = psmouse->private;
1074 : : struct synaptics_hw_state hw;
1075 : : int num_fingers;
1076 : : int finger_width;
1077 : :
1078 [ # # ]: 0 : if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
1079 : 0 : return;
1080 : :
1081 [ # # ]: 0 : if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
1082 : 0 : synaptics_image_sensor_process(psmouse, &hw);
1083 : 0 : return;
1084 : : }
1085 : :
1086 [ # # ]: 0 : if (hw.scroll) {
1087 : 0 : priv->scroll += hw.scroll;
1088 : :
1089 [ # # ]: 0 : while (priv->scroll >= 4) {
1090 : 0 : input_report_key(dev, BTN_BACK, !hw.down);
1091 : : input_sync(dev);
1092 : 0 : input_report_key(dev, BTN_BACK, hw.down);
1093 : : input_sync(dev);
1094 : 0 : priv->scroll -= 4;
1095 : : }
1096 [ # # ]: 0 : while (priv->scroll <= -4) {
1097 : 0 : input_report_key(dev, BTN_FORWARD, !hw.up);
1098 : : input_sync(dev);
1099 : 0 : input_report_key(dev, BTN_FORWARD, hw.up);
1100 : : input_sync(dev);
1101 : 0 : priv->scroll += 4;
1102 : : }
1103 : : return;
1104 : : }
1105 : :
1106 [ # # ][ # # ]: 0 : if (hw.z > 0 && hw.x > 1) {
1107 : : num_fingers = 1;
1108 : : finger_width = 5;
1109 [ # # ]: 0 : if (SYN_CAP_EXTENDED(priv->capabilities)) {
1110 [ # # # ]: 0 : switch (hw.w) {
1111 : : case 0 ... 1:
1112 [ # # ]: 0 : if (SYN_CAP_MULTIFINGER(priv->capabilities))
1113 : 0 : num_fingers = hw.w + 2;
1114 : : break;
1115 : : case 2:
1116 : : if (SYN_MODEL_PEN(priv->model_id))
1117 : : ; /* Nothing, treat a pen as a single finger */
1118 : : break;
1119 : : case 4 ... 15:
1120 [ # # ]: 0 : if (SYN_CAP_PALMDETECT(priv->capabilities))
1121 : : finger_width = hw.w;
1122 : : break;
1123 : : }
1124 : : }
1125 : : } else {
1126 : : num_fingers = 0;
1127 : : finger_width = 0;
1128 : : }
1129 : :
1130 [ # # ]: 0 : if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
1131 : 0 : synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
1132 : : num_fingers);
1133 : :
1134 : : /* Post events
1135 : : * BTN_TOUCH has to be first as mousedev relies on it when doing
1136 : : * absolute -> relative conversion
1137 : : */
1138 [ # # ]: 0 : if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
1139 [ # # ]: 0 : if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
1140 : :
1141 [ # # ]: 0 : if (num_fingers > 0) {
1142 : 0 : input_report_abs(dev, ABS_X, hw.x);
1143 : 0 : input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y));
1144 : : }
1145 : 0 : input_report_abs(dev, ABS_PRESSURE, hw.z);
1146 : :
1147 [ # # ]: 0 : if (SYN_CAP_PALMDETECT(priv->capabilities))
1148 : : input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
1149 : :
1150 : 0 : input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
1151 [ # # ]: 0 : if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
1152 : 0 : input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
1153 : 0 : input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
1154 : : }
1155 : :
1156 : 0 : synaptics_report_buttons(psmouse, &hw);
1157 : :
1158 : : input_sync(dev);
1159 : : }
1160 : :
1161 : 0 : static int synaptics_validate_byte(struct psmouse *psmouse,
1162 : : int idx, unsigned char pkt_type)
1163 : : {
1164 : : static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
1165 : : static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
1166 : : static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
1167 : : static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
1168 : : static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
1169 : 0 : const char *packet = psmouse->packet;
1170 : :
1171 [ # # ]: 0 : if (idx < 0 || idx > 4)
1172 : : return 0;
1173 : :
1174 [ # # # # ]: 0 : switch (pkt_type) {
1175 : :
1176 : : case SYN_NEWABS:
1177 : : case SYN_NEWABS_RELAXED:
1178 : 0 : return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
1179 : :
1180 : : case SYN_NEWABS_STRICT:
1181 : 0 : return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
1182 : :
1183 : : case SYN_OLDABS:
1184 : 0 : return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
1185 : :
1186 : : default:
1187 : 0 : psmouse_err(psmouse, "unknown packet type %d\n", pkt_type);
1188 : 0 : return 0;
1189 : : }
1190 : : }
1191 : :
1192 : 0 : static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
1193 : : {
1194 : : int i;
1195 : :
1196 [ # # ]: 0 : for (i = 0; i < 5; i++)
1197 [ # # ]: 0 : if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) {
1198 : 0 : psmouse_info(psmouse, "using relaxed packet validation\n");
1199 : 0 : return SYN_NEWABS_RELAXED;
1200 : : }
1201 : :
1202 : : return SYN_NEWABS_STRICT;
1203 : : }
1204 : :
1205 : 0 : static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
1206 : : {
1207 : 0 : struct synaptics_data *priv = psmouse->private;
1208 : :
1209 [ # # ]: 0 : if (psmouse->pktcnt >= 6) { /* Full packet received */
1210 [ # # ]: 0 : if (unlikely(priv->pkt_type == SYN_NEWABS))
1211 : 0 : priv->pkt_type = synaptics_detect_pkt_type(psmouse);
1212 : :
1213 [ # # ][ # # ]: 0 : if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
1214 : : synaptics_is_pt_packet(psmouse->packet)) {
1215 [ # # ]: 0 : if (priv->pt_port)
1216 : 0 : synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
1217 : : } else
1218 : 0 : synaptics_process_packet(psmouse);
1219 : :
1220 : : return PSMOUSE_FULL_PACKET;
1221 : : }
1222 : :
1223 : 0 : return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ?
1224 : 0 : PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
1225 : : }
1226 : :
1227 : : /*****************************************************************************
1228 : : * Driver initialization/cleanup functions
1229 : : ****************************************************************************/
1230 : 0 : static void set_abs_position_params(struct input_dev *dev,
1231 : : struct synaptics_data *priv, int x_code,
1232 : : int y_code)
1233 : : {
1234 [ # # ]: 0 : int x_min = priv->x_min ?: XMIN_NOMINAL;
1235 [ # # ]: 0 : int x_max = priv->x_max ?: XMAX_NOMINAL;
1236 [ # # ]: 0 : int y_min = priv->y_min ?: YMIN_NOMINAL;
1237 [ # # ]: 0 : int y_max = priv->y_max ?: YMAX_NOMINAL;
1238 : 0 : int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
1239 [ # # ]: 0 : SYN_REDUCED_FILTER_FUZZ : 0;
1240 : :
1241 : 0 : input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0);
1242 : 0 : input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0);
1243 : 0 : input_abs_set_res(dev, x_code, priv->x_res);
1244 : 0 : input_abs_set_res(dev, y_code, priv->y_res);
1245 : 0 : }
1246 : :
1247 : 0 : static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
1248 : : {
1249 : : int i;
1250 : :
1251 : : /* Things that apply to both modes */
1252 : : __set_bit(INPUT_PROP_POINTER, dev->propbit);
1253 : : __set_bit(EV_KEY, dev->evbit);
1254 : : __set_bit(BTN_LEFT, dev->keybit);
1255 : : __set_bit(BTN_RIGHT, dev->keybit);
1256 : :
1257 [ # # ]: 0 : if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
1258 : : __set_bit(BTN_MIDDLE, dev->keybit);
1259 : :
1260 [ # # ]: 0 : if (!priv->absolute_mode) {
1261 : : /* Relative mode */
1262 : : __set_bit(EV_REL, dev->evbit);
1263 : : __set_bit(REL_X, dev->relbit);
1264 : : __set_bit(REL_Y, dev->relbit);
1265 : 0 : return;
1266 : : }
1267 : :
1268 : : /* Absolute mode */
1269 : : __set_bit(EV_ABS, dev->evbit);
1270 : 0 : set_abs_position_params(dev, priv, ABS_X, ABS_Y);
1271 : 0 : input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
1272 : :
1273 [ # # ]: 0 : if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
1274 : 0 : set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
1275 : : ABS_MT_POSITION_Y);
1276 : : /* Image sensors can report per-contact pressure */
1277 : 0 : input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
1278 : 0 : input_mt_init_slots(dev, 2, INPUT_MT_POINTER);
1279 : :
1280 : : /* Image sensors can signal 4 and 5 finger clicks */
1281 : : __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
1282 : : __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
1283 [ # # ]: 0 : } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
1284 : : /* Non-image sensors with AGM use semi-mt */
1285 : : __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
1286 : 0 : input_mt_init_slots(dev, 2, 0);
1287 : 0 : set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
1288 : : ABS_MT_POSITION_Y);
1289 : : }
1290 : :
1291 [ # # ]: 0 : if (SYN_CAP_PALMDETECT(priv->capabilities))
1292 : 0 : input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
1293 : :
1294 : : __set_bit(BTN_TOUCH, dev->keybit);
1295 : : __set_bit(BTN_TOOL_FINGER, dev->keybit);
1296 : :
1297 [ # # ]: 0 : if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
1298 : : __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
1299 : : __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
1300 : : }
1301 : :
1302 [ # # ]: 0 : if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
1303 : : SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
1304 : : __set_bit(BTN_FORWARD, dev->keybit);
1305 : : __set_bit(BTN_BACK, dev->keybit);
1306 : : }
1307 : :
1308 [ # # ]: 0 : for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
1309 : 0 : __set_bit(BTN_0 + i, dev->keybit);
1310 : :
1311 : : __clear_bit(EV_REL, dev->evbit);
1312 : : __clear_bit(REL_X, dev->relbit);
1313 : : __clear_bit(REL_Y, dev->relbit);
1314 : :
1315 [ # # ]: 0 : if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
1316 : : __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
1317 : : /* Clickpads report only left button */
1318 : : __clear_bit(BTN_RIGHT, dev->keybit);
1319 : : __clear_bit(BTN_MIDDLE, dev->keybit);
1320 : : }
1321 : : }
1322 : :
1323 : 0 : static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse,
1324 : : void *data, char *buf)
1325 : : {
1326 : 0 : struct synaptics_data *priv = psmouse->private;
1327 : :
1328 [ # # ]: 0 : return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0');
1329 : : }
1330 : :
1331 : 0 : static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse,
1332 : : void *data, const char *buf,
1333 : : size_t len)
1334 : : {
1335 : 0 : struct synaptics_data *priv = psmouse->private;
1336 : : unsigned int value;
1337 : : int err;
1338 : :
1339 : 0 : err = kstrtouint(buf, 10, &value);
1340 [ # # ]: 0 : if (err)
1341 : : return err;
1342 : :
1343 [ # # ]: 0 : if (value > 1)
1344 : : return -EINVAL;
1345 : :
1346 [ # # ]: 0 : if (value == priv->disable_gesture)
1347 : 0 : return len;
1348 : :
1349 : 0 : priv->disable_gesture = value;
1350 [ # # ]: 0 : if (value)
1351 : 0 : priv->mode |= SYN_BIT_DISABLE_GESTURE;
1352 : : else
1353 : 0 : priv->mode &= ~SYN_BIT_DISABLE_GESTURE;
1354 : :
1355 [ # # ]: 0 : if (synaptics_mode_cmd(psmouse, priv->mode))
1356 : : return -EIO;
1357 : :
1358 : 0 : return len;
1359 : : }
1360 : :
1361 : : PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL,
1362 : : synaptics_show_disable_gesture,
1363 : : synaptics_set_disable_gesture);
1364 : :
1365 : 0 : static void synaptics_disconnect(struct psmouse *psmouse)
1366 : : {
1367 : 0 : struct synaptics_data *priv = psmouse->private;
1368 : :
1369 [ # # ][ # # ]: 0 : if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity))
1370 : 0 : device_remove_file(&psmouse->ps2dev.serio->dev,
1371 : : &psmouse_attr_disable_gesture.dattr);
1372 : :
1373 : : synaptics_reset(psmouse);
1374 : 0 : kfree(priv);
1375 : 0 : psmouse->private = NULL;
1376 : 0 : }
1377 : :
1378 : 0 : static int synaptics_reconnect(struct psmouse *psmouse)
1379 : : {
1380 : 0 : struct synaptics_data *priv = psmouse->private;
1381 : 0 : struct synaptics_data old_priv = *priv;
1382 : : unsigned char param[2];
1383 : : int retry = 0;
1384 : : int error;
1385 : :
1386 : : do {
1387 : 0 : psmouse_reset(psmouse);
1388 [ # # ]: 0 : if (retry) {
1389 : : /*
1390 : : * On some boxes, right after resuming, the touchpad
1391 : : * needs some time to finish initializing (I assume
1392 : : * it needs time to calibrate) and start responding
1393 : : * to Synaptics-specific queries, so let's wait a
1394 : : * bit.
1395 : : */
1396 : : ssleep(1);
1397 : : }
1398 : 0 : ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID);
1399 : 0 : error = synaptics_detect(psmouse, 0);
1400 [ # # ][ # # ]: 0 : } while (error && ++retry < 3);
1401 : :
1402 [ # # ]: 0 : if (error)
1403 : : return -1;
1404 : :
1405 : : if (retry > 1)
1406 : : psmouse_dbg(psmouse, "reconnected after %d tries\n", retry);
1407 : :
1408 [ # # ]: 0 : if (synaptics_query_hardware(psmouse)) {
1409 : 0 : psmouse_err(psmouse, "Unable to query device.\n");
1410 : 0 : return -1;
1411 : : }
1412 : :
1413 [ # # ]: 0 : if (synaptics_set_mode(psmouse)) {
1414 : 0 : psmouse_err(psmouse, "Unable to initialize device.\n");
1415 : 0 : return -1;
1416 : : }
1417 : :
1418 [ # # ][ # # ]: 0 : if (old_priv.identity != priv->identity ||
1419 [ # # ]: 0 : old_priv.model_id != priv->model_id ||
1420 [ # # ]: 0 : old_priv.capabilities != priv->capabilities ||
1421 : 0 : old_priv.ext_cap != priv->ext_cap) {
1422 : 0 : psmouse_err(psmouse,
1423 : : "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n",
1424 : : old_priv.identity, priv->identity,
1425 : : old_priv.model_id, priv->model_id,
1426 : : old_priv.capabilities, priv->capabilities,
1427 : : old_priv.ext_cap, priv->ext_cap);
1428 : 0 : return -1;
1429 : : }
1430 : :
1431 : : return 0;
1432 : : }
1433 : :
1434 : : static bool impaired_toshiba_kbc;
1435 : :
1436 : : static const struct dmi_system_id toshiba_dmi_table[] __initconst = {
1437 : : #if defined(CONFIG_DMI) && defined(CONFIG_X86)
1438 : : {
1439 : : /* Toshiba Satellite */
1440 : : .matches = {
1441 : : DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
1442 : : DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
1443 : : },
1444 : : },
1445 : : {
1446 : : /* Toshiba Dynabook */
1447 : : .matches = {
1448 : : DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
1449 : : DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
1450 : : },
1451 : : },
1452 : : {
1453 : : /* Toshiba Portege M300 */
1454 : : .matches = {
1455 : : DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
1456 : : DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
1457 : : },
1458 : :
1459 : : },
1460 : : {
1461 : : /* Toshiba Portege M300 */
1462 : : .matches = {
1463 : : DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
1464 : : DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
1465 : : DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
1466 : : },
1467 : :
1468 : : },
1469 : : #endif
1470 : : { }
1471 : : };
1472 : :
1473 : : static bool broken_olpc_ec;
1474 : :
1475 : : static const struct dmi_system_id olpc_dmi_table[] __initconst = {
1476 : : #if defined(CONFIG_DMI) && defined(CONFIG_OLPC)
1477 : : {
1478 : : /* OLPC XO-1 or XO-1.5 */
1479 : : .matches = {
1480 : : DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
1481 : : DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
1482 : : },
1483 : : },
1484 : : #endif
1485 : : { }
1486 : : };
1487 : :
1488 : 0 : void __init synaptics_module_init(void)
1489 : : {
1490 : 0 : impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
1491 : 0 : broken_olpc_ec = dmi_check_system(olpc_dmi_table);
1492 : 0 : }
1493 : :
1494 : 0 : static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
1495 : : {
1496 : : struct synaptics_data *priv;
1497 : : int err = -1;
1498 : :
1499 : : /*
1500 : : * The OLPC XO has issues with Synaptics' absolute mode; the constant
1501 : : * packet spew overloads the EC such that key presses on the keyboard
1502 : : * are missed. Given that, don't even attempt to use Absolute mode.
1503 : : * Relative mode seems to work just fine.
1504 : : */
1505 [ # # ][ # # ]: 0 : if (absolute_mode && broken_olpc_ec) {
1506 : 0 : psmouse_info(psmouse,
1507 : : "OLPC XO detected, not enabling Synaptics protocol.\n");
1508 : 0 : return -ENODEV;
1509 : : }
1510 : :
1511 : 0 : psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
1512 [ # # ]: 0 : if (!priv)
1513 : : return -ENOMEM;
1514 : :
1515 : 0 : psmouse_reset(psmouse);
1516 : :
1517 [ # # ]: 0 : if (synaptics_query_hardware(psmouse)) {
1518 : 0 : psmouse_err(psmouse, "Unable to query device.\n");
1519 : 0 : goto init_fail;
1520 : : }
1521 : :
1522 : 0 : priv->absolute_mode = absolute_mode;
1523 [ # # ]: 0 : if (SYN_ID_DISGEST_SUPPORTED(priv->identity))
1524 : 0 : priv->disable_gesture = true;
1525 : :
1526 [ # # ]: 0 : if (synaptics_set_mode(psmouse)) {
1527 : 0 : psmouse_err(psmouse, "Unable to initialize device.\n");
1528 : 0 : goto init_fail;
1529 : : }
1530 : :
1531 [ # # ]: 0 : priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
1532 : :
1533 : 0 : psmouse_info(psmouse,
1534 : : "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
1535 : : SYN_ID_MODEL(priv->identity),
1536 : : SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
1537 : : priv->model_id,
1538 : : priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
1539 : : priv->board_id, priv->firmware_id);
1540 : :
1541 : 0 : set_input_params(psmouse->dev, priv);
1542 : :
1543 : : /*
1544 : : * Encode touchpad model so that it can be used to set
1545 : : * input device->id.version and be visible to userspace.
1546 : : * Because version is __u16 we have to drop something.
1547 : : * Hardware info bits seem to be good candidates as they
1548 : : * are documented to be for Synaptics corp. internal use.
1549 : : */
1550 : 0 : psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
1551 : 0 : (priv->model_id & 0x000000ff);
1552 : :
1553 [ # # ]: 0 : if (absolute_mode) {
1554 : 0 : psmouse->protocol_handler = synaptics_process_byte;
1555 : 0 : psmouse->pktsize = 6;
1556 : : } else {
1557 : : /* Relative mode follows standard PS/2 mouse protocol */
1558 : 0 : psmouse->protocol_handler = psmouse_process_byte;
1559 : 0 : psmouse->pktsize = 3;
1560 : : }
1561 : :
1562 : 0 : psmouse->set_rate = synaptics_set_rate;
1563 : 0 : psmouse->disconnect = synaptics_disconnect;
1564 : 0 : psmouse->reconnect = synaptics_reconnect;
1565 : 0 : psmouse->cleanup = synaptics_reset;
1566 : : /* Synaptics can usually stay in sync without extra help */
1567 : 0 : psmouse->resync_time = 0;
1568 : :
1569 [ # # ]: 0 : if (SYN_CAP_PASS_THROUGH(priv->capabilities))
1570 : 0 : synaptics_pt_create(psmouse);
1571 : :
1572 : : /*
1573 : : * Toshiba's KBC seems to have trouble handling data from
1574 : : * Synaptics at full rate. Switch to a lower rate (roughly
1575 : : * the same rate as a standard PS/2 mouse).
1576 : : */
1577 [ # # ][ # # ]: 0 : if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
1578 : 0 : psmouse_info(psmouse,
1579 : : "Toshiba %s detected, limiting rate to 40pps.\n",
1580 : : dmi_get_system_info(DMI_PRODUCT_NAME));
1581 : 0 : psmouse->rate = 40;
1582 : : }
1583 : :
1584 [ # # ][ # # ]: 0 : if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) {
1585 : 0 : err = device_create_file(&psmouse->ps2dev.serio->dev,
1586 : : &psmouse_attr_disable_gesture.dattr);
1587 [ # # ]: 0 : if (err) {
1588 : 0 : psmouse_err(psmouse,
1589 : : "Failed to create disable_gesture attribute (%d)",
1590 : : err);
1591 : 0 : goto init_fail;
1592 : : }
1593 : : }
1594 : :
1595 : : return 0;
1596 : :
1597 : : init_fail:
1598 : 0 : kfree(priv);
1599 : 0 : return err;
1600 : : }
1601 : :
1602 : 0 : int synaptics_init(struct psmouse *psmouse)
1603 : : {
1604 : 0 : return __synaptics_init(psmouse, true);
1605 : : }
1606 : :
1607 : 0 : int synaptics_init_relative(struct psmouse *psmouse)
1608 : : {
1609 : 0 : return __synaptics_init(psmouse, false);
1610 : : }
1611 : :
1612 : 0 : bool synaptics_supported(void)
1613 : : {
1614 : 0 : return true;
1615 : : }
1616 : :
1617 : : #else /* CONFIG_MOUSE_PS2_SYNAPTICS */
1618 : :
1619 : : void __init synaptics_module_init(void)
1620 : : {
1621 : : }
1622 : :
1623 : : int synaptics_init(struct psmouse *psmouse)
1624 : : {
1625 : : return -ENOSYS;
1626 : : }
1627 : :
1628 : : bool synaptics_supported(void)
1629 : : {
1630 : : return false;
1631 : : }
1632 : :
1633 : : #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
|