diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/input/mouse | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/Kconfig | 11 | ||||
-rw-r--r-- | drivers/input/mouse/appletouch.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/atarimouse.c | 15 | ||||
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 70 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 74 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 6 | ||||
-rw-r--r-- | drivers/input/mouse/hgpk.c | 695 | ||||
-rw-r--r-- | drivers/input/mouse/hgpk.h | 31 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 5 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 197 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 31 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics_i2c.c | 18 | ||||
-rw-r--r-- | drivers/input/mouse/touchkit_ps2.c | 4 | ||||
-rw-r--r-- | drivers/input/mouse/trackpoint.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/vsxxxaa.c | 2 |
15 files changed, 1009 insertions, 154 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index c714ca2407f8..9c1e6ee83531 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -30,6 +30,7 @@ config MOUSE_PS2 | |||
30 | <http://w1.894.telia.com/~u89404340/touchpad/index.html> | 30 | <http://w1.894.telia.com/~u89404340/touchpad/index.html> |
31 | and a new version of GPM at: | 31 | and a new version of GPM at: |
32 | <http://www.geocities.com/dt_or/gpm/gpm.html> | 32 | <http://www.geocities.com/dt_or/gpm/gpm.html> |
33 | <http://xorg.freedesktop.org/archive/individual/driver/> | ||
33 | to take advantage of the advanced features of the touchpad. | 34 | to take advantage of the advanced features of the touchpad. |
34 | 35 | ||
35 | If unsure, say Y. | 36 | If unsure, say Y. |
@@ -38,7 +39,7 @@ config MOUSE_PS2 | |||
38 | module will be called psmouse. | 39 | module will be called psmouse. |
39 | 40 | ||
40 | config MOUSE_PS2_ALPS | 41 | config MOUSE_PS2_ALPS |
41 | bool "ALPS PS/2 mouse protocol extension" if EMBEDDED | 42 | bool "ALPS PS/2 mouse protocol extension" if EXPERT |
42 | default y | 43 | default y |
43 | depends on MOUSE_PS2 | 44 | depends on MOUSE_PS2 |
44 | help | 45 | help |
@@ -48,7 +49,7 @@ config MOUSE_PS2_ALPS | |||
48 | If unsure, say Y. | 49 | If unsure, say Y. |
49 | 50 | ||
50 | config MOUSE_PS2_LOGIPS2PP | 51 | config MOUSE_PS2_LOGIPS2PP |
51 | bool "Logitech PS/2++ mouse protocol extension" if EMBEDDED | 52 | bool "Logitech PS/2++ mouse protocol extension" if EXPERT |
52 | default y | 53 | default y |
53 | depends on MOUSE_PS2 | 54 | depends on MOUSE_PS2 |
54 | help | 55 | help |
@@ -58,7 +59,7 @@ config MOUSE_PS2_LOGIPS2PP | |||
58 | If unsure, say Y. | 59 | If unsure, say Y. |
59 | 60 | ||
60 | config MOUSE_PS2_SYNAPTICS | 61 | config MOUSE_PS2_SYNAPTICS |
61 | bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED | 62 | bool "Synaptics PS/2 mouse protocol extension" if EXPERT |
62 | default y | 63 | default y |
63 | depends on MOUSE_PS2 | 64 | depends on MOUSE_PS2 |
64 | help | 65 | help |
@@ -68,7 +69,7 @@ config MOUSE_PS2_SYNAPTICS | |||
68 | If unsure, say Y. | 69 | If unsure, say Y. |
69 | 70 | ||
70 | config MOUSE_PS2_LIFEBOOK | 71 | config MOUSE_PS2_LIFEBOOK |
71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 72 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT |
72 | default y | 73 | default y |
73 | depends on MOUSE_PS2 && X86 && DMI | 74 | depends on MOUSE_PS2 && X86 && DMI |
74 | help | 75 | help |
@@ -78,7 +79,7 @@ config MOUSE_PS2_LIFEBOOK | |||
78 | If unsure, say Y. | 79 | If unsure, say Y. |
79 | 80 | ||
80 | config MOUSE_PS2_TRACKPOINT | 81 | config MOUSE_PS2_TRACKPOINT |
81 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED | 82 | bool "IBM Trackpoint PS/2 mouse protocol extension" if EXPERT |
82 | default y | 83 | default y |
83 | depends on MOUSE_PS2 | 84 | depends on MOUSE_PS2 |
84 | help | 85 | help |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index a9cf76831634..b77f9991278e 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -630,7 +630,7 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
630 | /* Just update the base values (i.e. touchpad in untouched state) */ | 630 | /* Just update the base values (i.e. touchpad in untouched state) */ |
631 | if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) { | 631 | if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) { |
632 | 632 | ||
633 | dprintk(KERN_DEBUG "appletouch: updated base values\n"); | 633 | dprintk("appletouch: updated base values\n"); |
634 | 634 | ||
635 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 635 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
636 | goto exit; | 636 | goto exit; |
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c index adf45b3040e9..5c4a692bf73a 100644 --- a/drivers/input/mouse/atarimouse.c +++ b/drivers/input/mouse/atarimouse.c | |||
@@ -77,15 +77,15 @@ static void atamouse_interrupt(char *buf) | |||
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | /* only relative events get here */ | 79 | /* only relative events get here */ |
80 | dx = buf[1]; | 80 | dx = buf[1]; |
81 | dy = -buf[2]; | 81 | dy = buf[2]; |
82 | 82 | ||
83 | input_report_rel(atamouse_dev, REL_X, dx); | 83 | input_report_rel(atamouse_dev, REL_X, dx); |
84 | input_report_rel(atamouse_dev, REL_Y, dy); | 84 | input_report_rel(atamouse_dev, REL_Y, dy); |
85 | 85 | ||
86 | input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x1); | 86 | input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x4); |
87 | input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2); | 87 | input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2); |
88 | input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x4); | 88 | input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x1); |
89 | 89 | ||
90 | input_sync(atamouse_dev); | 90 | input_sync(atamouse_dev); |
91 | 91 | ||
@@ -108,7 +108,7 @@ static int atamouse_open(struct input_dev *dev) | |||
108 | static void atamouse_close(struct input_dev *dev) | 108 | static void atamouse_close(struct input_dev *dev) |
109 | { | 109 | { |
110 | ikbd_mouse_disable(); | 110 | ikbd_mouse_disable(); |
111 | atari_mouse_interrupt_hook = NULL; | 111 | atari_input_mouse_interrupt_hook = NULL; |
112 | } | 112 | } |
113 | 113 | ||
114 | static int __init atamouse_init(void) | 114 | static int __init atamouse_init(void) |
@@ -118,8 +118,9 @@ static int __init atamouse_init(void) | |||
118 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) | 118 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) |
119 | return -ENODEV; | 119 | return -ENODEV; |
120 | 120 | ||
121 | if (!atari_keyb_init()) | 121 | error = atari_keyb_init(); |
122 | return -ENODEV; | 122 | if (error) |
123 | return error; | ||
123 | 124 | ||
124 | atamouse_dev = input_allocate_device(); | 125 | atamouse_dev = input_allocate_device(); |
125 | if (!atamouse_dev) | 126 | if (!atamouse_dev) |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b95231763911..3126983c004a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -55,6 +55,18 @@ | |||
55 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | 55 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 |
56 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | 56 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 |
57 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | 57 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 |
58 | /* MacbookAir3,2 (unibody), aka wellspring5 */ | ||
59 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f | ||
60 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 | ||
61 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 | ||
62 | /* MacbookAir3,1 (unibody), aka wellspring4 */ | ||
63 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 | ||
64 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 | ||
65 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 | ||
66 | /* Macbook8 (unibody, March 2011) */ | ||
67 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 | ||
68 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 | ||
69 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 | ||
58 | 70 | ||
59 | #define BCM5974_DEVICE(prod) { \ | 71 | #define BCM5974_DEVICE(prod) { \ |
60 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | 72 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ |
@@ -80,6 +92,18 @@ static const struct usb_device_id bcm5974_table[] = { | |||
80 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), | 92 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), |
81 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), | 93 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), |
82 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | 94 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), |
95 | /* MacbookAir3,2 */ | ||
96 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), | ||
97 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), | ||
98 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), | ||
99 | /* MacbookAir3,1 */ | ||
100 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), | ||
101 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), | ||
102 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), | ||
103 | /* MacbookPro8 */ | ||
104 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), | ||
105 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), | ||
106 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), | ||
83 | /* Terminating entry */ | 107 | /* Terminating entry */ |
84 | {} | 108 | {} |
85 | }; | 109 | }; |
@@ -234,6 +258,42 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
234 | { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, | 258 | { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, |
235 | { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } | 259 | { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } |
236 | }, | 260 | }, |
261 | { | ||
262 | USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, | ||
263 | USB_DEVICE_ID_APPLE_WELLSPRING4_ISO, | ||
264 | USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, | ||
265 | HAS_INTEGRATED_BUTTON, | ||
266 | 0x84, sizeof(struct bt_data), | ||
267 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
268 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
269 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
270 | { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, | ||
271 | { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } | ||
272 | }, | ||
273 | { | ||
274 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, | ||
275 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO, | ||
276 | USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, | ||
277 | HAS_INTEGRATED_BUTTON, | ||
278 | 0x84, sizeof(struct bt_data), | ||
279 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
280 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
281 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
282 | { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, | ||
283 | { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } | ||
284 | }, | ||
285 | { | ||
286 | USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, | ||
287 | USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, | ||
288 | USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, | ||
289 | HAS_INTEGRATED_BUTTON, | ||
290 | 0x84, sizeof(struct bt_data), | ||
291 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
292 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
293 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
294 | { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, | ||
295 | { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } | ||
296 | }, | ||
237 | {} | 297 | {} |
238 | }; | 298 | }; |
239 | 299 | ||
@@ -390,10 +450,6 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
390 | ptest = int2bound(&c->p, raw_p); | 450 | ptest = int2bound(&c->p, raw_p); |
391 | origin = raw2int(f->origin); | 451 | origin = raw2int(f->origin); |
392 | 452 | ||
393 | /* set the integrated button if applicable */ | ||
394 | if (c->tp_type == TYPE2) | ||
395 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | ||
396 | |||
397 | /* while tracking finger still valid, count all fingers */ | 453 | /* while tracking finger still valid, count all fingers */ |
398 | if (ptest > PRESSURE_LOW && origin) { | 454 | if (ptest > PRESSURE_LOW && origin) { |
399 | abs_p = ptest; | 455 | abs_p = ptest; |
@@ -412,6 +468,10 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
412 | } | 468 | } |
413 | } | 469 | } |
414 | 470 | ||
471 | /* set the integrated button if applicable */ | ||
472 | if (c->tp_type == TYPE2) | ||
473 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | ||
474 | |||
415 | if (dev->fingers < nmin) | 475 | if (dev->fingers < nmin) |
416 | dev->fingers = nmin; | 476 | dev->fingers = nmin; |
417 | if (dev->fingers > nmax) | 477 | if (dev->fingers > nmax) |
@@ -579,7 +639,7 @@ exit: | |||
579 | * device, resulting in trackpad malfunction under certain | 639 | * device, resulting in trackpad malfunction under certain |
580 | * circumstances. To get around this problem, there is at least one | 640 | * circumstances. To get around this problem, there is at least one |
581 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to | 641 | * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to |
582 | * recieve a reset_resume request rather than the normal resume. | 642 | * receive a reset_resume request rather than the normal resume. |
583 | * Since the implementation of reset_resume is equal to mode switch | 643 | * Since the implementation of reset_resume is equal to mode switch |
584 | * plus start_traffic, it seems easier to always do the switch when | 644 | * plus start_traffic, it seems easier to always do the switch when |
585 | * starting traffic on the device. | 645 | * starting traffic on the device. |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 48311204ba51..32503565faf9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/input/mt.h> | ||
19 | #include <linux/serio.h> | 20 | #include <linux/serio.h> |
20 | #include <linux/libps2.h> | 21 | #include <linux/libps2.h> |
21 | #include "psmouse.h" | 22 | #include "psmouse.h" |
@@ -242,15 +243,37 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
242 | input_sync(dev); | 243 | input_sync(dev); |
243 | } | 244 | } |
244 | 245 | ||
246 | static void elantech_set_slot(struct input_dev *dev, int slot, bool active, | ||
247 | unsigned int x, unsigned int y) | ||
248 | { | ||
249 | input_mt_slot(dev, slot); | ||
250 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
251 | if (active) { | ||
252 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
253 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* x1 < x2 and y1 < y2 when two fingers, x = y = 0 when not pressed */ | ||
258 | static void elantech_report_semi_mt_data(struct input_dev *dev, | ||
259 | unsigned int num_fingers, | ||
260 | unsigned int x1, unsigned int y1, | ||
261 | unsigned int x2, unsigned int y2) | ||
262 | { | ||
263 | elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); | ||
264 | elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); | ||
265 | } | ||
266 | |||
245 | /* | 267 | /* |
246 | * Interpret complete data packets and report absolute mode input events for | 268 | * Interpret complete data packets and report absolute mode input events for |
247 | * hardware version 2. (6 byte packets) | 269 | * hardware version 2. (6 byte packets) |
248 | */ | 270 | */ |
249 | static void elantech_report_absolute_v2(struct psmouse *psmouse) | 271 | static void elantech_report_absolute_v2(struct psmouse *psmouse) |
250 | { | 272 | { |
273 | struct elantech_data *etd = psmouse->private; | ||
251 | struct input_dev *dev = psmouse->dev; | 274 | struct input_dev *dev = psmouse->dev; |
252 | unsigned char *packet = psmouse->packet; | 275 | unsigned char *packet = psmouse->packet; |
253 | int fingers, x1, y1, x2, y2; | 276 | unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; |
254 | 277 | ||
255 | /* byte 0: n1 n0 . . . . R L */ | 278 | /* byte 0: n1 n0 . . . . R L */ |
256 | fingers = (packet[0] & 0xc0) >> 6; | 279 | fingers = (packet[0] & 0xc0) >> 6; |
@@ -270,14 +293,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
270 | * byte 1: . . . . . x10 x9 x8 | 293 | * byte 1: . . . . . x10 x9 x8 |
271 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | 294 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
272 | */ | 295 | */ |
273 | input_report_abs(dev, ABS_X, | 296 | x1 = ((packet[1] & 0x07) << 8) | packet[2]; |
274 | ((packet[1] & 0x07) << 8) | packet[2]); | ||
275 | /* | 297 | /* |
276 | * byte 4: . . . . . . y9 y8 | 298 | * byte 4: . . . . . . y9 y8 |
277 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | 299 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
278 | */ | 300 | */ |
279 | input_report_abs(dev, ABS_Y, | 301 | y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); |
280 | ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); | 302 | |
303 | input_report_abs(dev, ABS_X, x1); | ||
304 | input_report_abs(dev, ABS_Y, y1); | ||
305 | |||
306 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | ||
307 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | ||
281 | break; | 308 | break; |
282 | 309 | ||
283 | case 2: | 310 | case 2: |
@@ -303,23 +330,24 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
303 | */ | 330 | */ |
304 | input_report_abs(dev, ABS_X, x1 << 2); | 331 | input_report_abs(dev, ABS_X, x1 << 2); |
305 | input_report_abs(dev, ABS_Y, y1 << 2); | 332 | input_report_abs(dev, ABS_Y, y1 << 2); |
306 | /* | 333 | |
307 | * For compatibility with the proprietary X Elantech driver | 334 | /* Unknown so just report sensible values */ |
308 | * report both coordinates as hat coordinates | 335 | pres = 127; |
309 | */ | 336 | width = 7; |
310 | input_report_abs(dev, ABS_HAT0X, x1); | ||
311 | input_report_abs(dev, ABS_HAT0Y, y1); | ||
312 | input_report_abs(dev, ABS_HAT1X, x2); | ||
313 | input_report_abs(dev, ABS_HAT1Y, y2); | ||
314 | break; | 337 | break; |
315 | } | 338 | } |
316 | 339 | ||
340 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | ||
317 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 341 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
318 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 342 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
319 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | 343 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
320 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); | 344 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); |
321 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 345 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
322 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 346 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
347 | if (etd->reports_pressure) { | ||
348 | input_report_abs(dev, ABS_PRESSURE, pres); | ||
349 | input_report_abs(dev, ABS_TOOL_WIDTH, width); | ||
350 | } | ||
323 | 351 | ||
324 | input_sync(dev); | 352 | input_sync(dev); |
325 | } | 353 | } |
@@ -478,10 +506,16 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
478 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 506 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
479 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); | 507 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); |
480 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); | 508 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); |
481 | input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); | 509 | if (etd->reports_pressure) { |
482 | input_set_abs_params(dev, ABS_HAT0Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); | 510 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, |
483 | input_set_abs_params(dev, ABS_HAT1X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); | 511 | ETP_PMAX_V2, 0, 0); |
484 | input_set_abs_params(dev, ABS_HAT1Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); | 512 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, |
513 | ETP_WMAX_V2, 0, 0); | ||
514 | } | ||
515 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
516 | input_mt_init_slots(dev, 2); | ||
517 | input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); | ||
518 | input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); | ||
485 | break; | 519 | break; |
486 | } | 520 | } |
487 | } | 521 | } |
@@ -699,7 +733,7 @@ int elantech_init(struct psmouse *psmouse) | |||
699 | 733 | ||
700 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 734 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
701 | if (!etd) | 735 | if (!etd) |
702 | return -1; | 736 | return -ENOMEM; |
703 | 737 | ||
704 | etd->parity[0] = 1; | 738 | etd->parity[0] = 1; |
705 | for (i = 1; i < 256; i++) | 739 | for (i = 1; i < 256; i++) |
@@ -725,6 +759,10 @@ int elantech_init(struct psmouse *psmouse) | |||
725 | etd->debug = 1; | 759 | etd->debug = 1; |
726 | /* Don't know how to do parity checking for version 2 */ | 760 | /* Don't know how to do parity checking for version 2 */ |
727 | etd->paritycheck = 0; | 761 | etd->paritycheck = 0; |
762 | |||
763 | if (etd->fw_version >= 0x020800) | ||
764 | etd->reports_pressure = true; | ||
765 | |||
728 | } else { | 766 | } else { |
729 | etd->hw_version = 1; | 767 | etd->hw_version = 1; |
730 | etd->paritycheck = 1; | 768 | etd->paritycheck = 1; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index aa4aac5d2198..fabb2b99615c 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -77,6 +77,11 @@ | |||
77 | #define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) | 77 | #define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) |
78 | #define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) | 78 | #define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) |
79 | 79 | ||
80 | #define ETP_PMIN_V2 0 | ||
81 | #define ETP_PMAX_V2 255 | ||
82 | #define ETP_WMIN_V2 0 | ||
83 | #define ETP_WMAX_V2 15 | ||
84 | |||
80 | /* | 85 | /* |
81 | * For two finger touches the coordinate of each finger gets reported | 86 | * For two finger touches the coordinate of each finger gets reported |
82 | * separately but with reduced resolution. | 87 | * separately but with reduced resolution. |
@@ -102,6 +107,7 @@ struct elantech_data { | |||
102 | unsigned char capabilities; | 107 | unsigned char capabilities; |
103 | bool paritycheck; | 108 | bool paritycheck; |
104 | bool jumpy_cursor; | 109 | bool jumpy_cursor; |
110 | bool reports_pressure; | ||
105 | unsigned char hw_version; | 111 | unsigned char hw_version; |
106 | unsigned int fw_version; | 112 | unsigned int fw_version; |
107 | unsigned int single_finger_reports; | 113 | unsigned int single_finger_reports; |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 1d2205b24800..95577c15ae56 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include "psmouse.h" | 40 | #include "psmouse.h" |
41 | #include "hgpk.h" | 41 | #include "hgpk.h" |
42 | 42 | ||
43 | #define ILLEGAL_XY 999999 | ||
44 | |||
43 | static bool tpdebug; | 45 | static bool tpdebug; |
44 | module_param(tpdebug, bool, 0644); | 46 | module_param(tpdebug, bool, 0644); |
45 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | 47 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); |
@@ -47,48 +49,150 @@ MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | |||
47 | static int recalib_delta = 100; | 49 | static int recalib_delta = 100; |
48 | module_param(recalib_delta, int, 0644); | 50 | module_param(recalib_delta, int, 0644); |
49 | MODULE_PARM_DESC(recalib_delta, | 51 | MODULE_PARM_DESC(recalib_delta, |
50 | "packets containing a delta this large will cause a recalibration."); | 52 | "packets containing a delta this large will be discarded, and a " |
53 | "recalibration may be scheduled."); | ||
51 | 54 | ||
52 | static int jumpy_delay = 1000; | 55 | static int jumpy_delay = 20; |
53 | module_param(jumpy_delay, int, 0644); | 56 | module_param(jumpy_delay, int, 0644); |
54 | MODULE_PARM_DESC(jumpy_delay, | 57 | MODULE_PARM_DESC(jumpy_delay, |
55 | "delay (ms) before recal after jumpiness detected"); | 58 | "delay (ms) before recal after jumpiness detected"); |
56 | 59 | ||
57 | static int spew_delay = 1000; | 60 | static int spew_delay = 1; |
58 | module_param(spew_delay, int, 0644); | 61 | module_param(spew_delay, int, 0644); |
59 | MODULE_PARM_DESC(spew_delay, | 62 | MODULE_PARM_DESC(spew_delay, |
60 | "delay (ms) before recal after packet spew detected"); | 63 | "delay (ms) before recal after packet spew detected"); |
61 | 64 | ||
62 | static int recal_guard_time = 2000; | 65 | static int recal_guard_time; |
63 | module_param(recal_guard_time, int, 0644); | 66 | module_param(recal_guard_time, int, 0644); |
64 | MODULE_PARM_DESC(recal_guard_time, | 67 | MODULE_PARM_DESC(recal_guard_time, |
65 | "interval (ms) during which recal will be restarted if packet received"); | 68 | "interval (ms) during which recal will be restarted if packet received"); |
66 | 69 | ||
67 | static int post_interrupt_delay = 1000; | 70 | static int post_interrupt_delay = 40; |
68 | module_param(post_interrupt_delay, int, 0644); | 71 | module_param(post_interrupt_delay, int, 0644); |
69 | MODULE_PARM_DESC(post_interrupt_delay, | 72 | MODULE_PARM_DESC(post_interrupt_delay, |
70 | "delay (ms) before recal after recal interrupt detected"); | 73 | "delay (ms) before recal after recal interrupt detected"); |
71 | 74 | ||
75 | static bool autorecal = true; | ||
76 | module_param(autorecal, bool, 0644); | ||
77 | MODULE_PARM_DESC(autorecal, "enable recalibration in the driver"); | ||
78 | |||
79 | static char hgpk_mode_name[16]; | ||
80 | module_param_string(hgpk_mode, hgpk_mode_name, sizeof(hgpk_mode_name), 0644); | ||
81 | MODULE_PARM_DESC(hgpk_mode, | ||
82 | "default hgpk mode: mouse, glidesensor or pentablet"); | ||
83 | |||
84 | static int hgpk_default_mode = HGPK_MODE_MOUSE; | ||
85 | |||
86 | static const char * const hgpk_mode_names[] = { | ||
87 | [HGPK_MODE_MOUSE] = "Mouse", | ||
88 | [HGPK_MODE_GLIDESENSOR] = "GlideSensor", | ||
89 | [HGPK_MODE_PENTABLET] = "PenTablet", | ||
90 | }; | ||
91 | |||
92 | static int hgpk_mode_from_name(const char *buf, int len) | ||
93 | { | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < ARRAY_SIZE(hgpk_mode_names); i++) { | ||
97 | const char *name = hgpk_mode_names[i]; | ||
98 | if (strlen(name) == len && !strncasecmp(name, buf, len)) | ||
99 | return i; | ||
100 | } | ||
101 | |||
102 | return HGPK_MODE_INVALID; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * see if new value is within 20% of half of old value | ||
107 | */ | ||
108 | static int approx_half(int curr, int prev) | ||
109 | { | ||
110 | int belowhalf, abovehalf; | ||
111 | |||
112 | if (curr < 5 || prev < 5) | ||
113 | return 0; | ||
114 | |||
115 | belowhalf = (prev * 8) / 20; | ||
116 | abovehalf = (prev * 12) / 20; | ||
117 | |||
118 | return belowhalf < curr && curr <= abovehalf; | ||
119 | } | ||
120 | |||
72 | /* | 121 | /* |
73 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" | 122 | * Throw out oddly large delta packets, and any that immediately follow whose |
74 | * above the pad and still have it send packets. This causes a jump cursor | 123 | * values are each approximately half of the previous. It seems that the ALPS |
75 | * when one places their finger on the pad. We can probably detect the | 124 | * firmware emits errant packets, and they get averaged out slowly. |
76 | * jump as we see a large deltas (>= 100px). In mouse mode, I've been | ||
77 | * unable to even come close to 100px deltas during normal usage, so I think | ||
78 | * this threshold is safe. If a large delta occurs, trigger a recalibration. | ||
79 | */ | 125 | */ |
80 | static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) | 126 | static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) |
81 | { | 127 | { |
82 | struct hgpk_data *priv = psmouse->private; | 128 | struct hgpk_data *priv = psmouse->private; |
129 | int avx, avy; | ||
130 | bool do_recal = false; | ||
131 | |||
132 | avx = abs(x); | ||
133 | avy = abs(y); | ||
134 | |||
135 | /* discard if too big, or half that but > 4 times the prev delta */ | ||
136 | if (avx > recalib_delta || | ||
137 | (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) { | ||
138 | hgpk_err(psmouse, "detected %dpx jump in x\n", x); | ||
139 | priv->xbigj = avx; | ||
140 | } else if (approx_half(avx, priv->xbigj)) { | ||
141 | hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x); | ||
142 | priv->xbigj = avx; | ||
143 | priv->xsaw_secondary++; | ||
144 | } else { | ||
145 | if (priv->xbigj && priv->xsaw_secondary > 1) | ||
146 | do_recal = true; | ||
147 | priv->xbigj = 0; | ||
148 | priv->xsaw_secondary = 0; | ||
149 | } | ||
150 | |||
151 | if (avy > recalib_delta || | ||
152 | (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) { | ||
153 | hgpk_err(psmouse, "detected %dpx jump in y\n", y); | ||
154 | priv->ybigj = avy; | ||
155 | } else if (approx_half(avy, priv->ybigj)) { | ||
156 | hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y); | ||
157 | priv->ybigj = avy; | ||
158 | priv->ysaw_secondary++; | ||
159 | } else { | ||
160 | if (priv->ybigj && priv->ysaw_secondary > 1) | ||
161 | do_recal = true; | ||
162 | priv->ybigj = 0; | ||
163 | priv->ysaw_secondary = 0; | ||
164 | } | ||
83 | 165 | ||
84 | if (abs(x) > recalib_delta || abs(y) > recalib_delta) { | 166 | priv->xlast = avx; |
85 | hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n", | 167 | priv->ylast = avy; |
86 | recalib_delta, x, y); | 168 | |
87 | /* My car gets forty rods to the hogshead and that's the | 169 | if (do_recal && jumpy_delay) { |
88 | * way I likes it! */ | 170 | hgpk_err(psmouse, "scheduling recalibration\n"); |
89 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 171 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
90 | msecs_to_jiffies(jumpy_delay)); | 172 | msecs_to_jiffies(jumpy_delay)); |
91 | } | 173 | } |
174 | |||
175 | return priv->xbigj || priv->ybigj; | ||
176 | } | ||
177 | |||
178 | static void hgpk_reset_spew_detection(struct hgpk_data *priv) | ||
179 | { | ||
180 | priv->spew_count = 0; | ||
181 | priv->dupe_count = 0; | ||
182 | priv->x_tally = 0; | ||
183 | priv->y_tally = 0; | ||
184 | priv->spew_flag = NO_SPEW; | ||
185 | } | ||
186 | |||
187 | static void hgpk_reset_hack_state(struct psmouse *psmouse) | ||
188 | { | ||
189 | struct hgpk_data *priv = psmouse->private; | ||
190 | |||
191 | priv->abs_x = priv->abs_y = -1; | ||
192 | priv->xlast = priv->ylast = ILLEGAL_XY; | ||
193 | priv->xbigj = priv->ybigj = 0; | ||
194 | priv->xsaw_secondary = priv->ysaw_secondary = 0; | ||
195 | hgpk_reset_spew_detection(priv); | ||
92 | } | 196 | } |
93 | 197 | ||
94 | /* | 198 | /* |
@@ -116,20 +220,57 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, | |||
116 | if (l || r) | 220 | if (l || r) |
117 | return; | 221 | return; |
118 | 222 | ||
223 | /* don't track spew if the workaround feature has been turned off */ | ||
224 | if (!spew_delay) | ||
225 | return; | ||
226 | |||
227 | if (abs(x) > 3 || abs(y) > 3) { | ||
228 | /* no spew, or spew ended */ | ||
229 | hgpk_reset_spew_detection(priv); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | /* Keep a tally of the overall delta to the cursor position caused by | ||
234 | * the spew */ | ||
119 | priv->x_tally += x; | 235 | priv->x_tally += x; |
120 | priv->y_tally += y; | 236 | priv->y_tally += y; |
121 | 237 | ||
122 | if (++priv->count > 100) { | 238 | switch (priv->spew_flag) { |
239 | case NO_SPEW: | ||
240 | /* we're not spewing, but this packet might be the start */ | ||
241 | priv->spew_flag = MAYBE_SPEWING; | ||
242 | |||
243 | /* fall-through */ | ||
244 | |||
245 | case MAYBE_SPEWING: | ||
246 | priv->spew_count++; | ||
247 | |||
248 | if (priv->spew_count < SPEW_WATCH_COUNT) | ||
249 | break; | ||
250 | |||
251 | /* excessive spew detected, request recalibration */ | ||
252 | priv->spew_flag = SPEW_DETECTED; | ||
253 | |||
254 | /* fall-through */ | ||
255 | |||
256 | case SPEW_DETECTED: | ||
257 | /* only recalibrate when the overall delta to the cursor | ||
258 | * is really small. if the spew is causing significant cursor | ||
259 | * movement, it is probably a case of the user moving the | ||
260 | * cursor very slowly across the screen. */ | ||
123 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { | 261 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { |
124 | hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", | 262 | hgpk_err(psmouse, "packet spew detected (%d,%d)\n", |
125 | priv->x_tally, priv->y_tally); | 263 | priv->x_tally, priv->y_tally); |
264 | priv->spew_flag = RECALIBRATING; | ||
126 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 265 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
127 | msecs_to_jiffies(spew_delay)); | 266 | msecs_to_jiffies(spew_delay)); |
128 | } | 267 | } |
129 | /* reset every 100 packets */ | 268 | |
130 | priv->count = 0; | 269 | break; |
131 | priv->x_tally = 0; | 270 | case RECALIBRATING: |
132 | priv->y_tally = 0; | 271 | /* we already detected a spew and requested a recalibration, |
272 | * just wait for the queue to kick into action. */ | ||
273 | break; | ||
133 | } | 274 | } |
134 | } | 275 | } |
135 | 276 | ||
@@ -143,25 +284,168 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, | |||
143 | * swr/swl are the left/right buttons. | 284 | * swr/swl are the left/right buttons. |
144 | * x-neg/y-neg are the x and y delta negative bits | 285 | * x-neg/y-neg are the x and y delta negative bits |
145 | * x-over/y-over are the x and y overflow bits | 286 | * x-over/y-over are the x and y overflow bits |
287 | * | ||
288 | * --- | ||
289 | * | ||
290 | * HGPK Advanced Mode - single-mode format | ||
291 | * | ||
292 | * byte 0(PT): 1 1 0 0 1 1 1 1 | ||
293 | * byte 0(GS): 1 1 1 1 1 1 1 1 | ||
294 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | ||
295 | * byte 2(PT): 0 0 x9 x8 x7 ? pt-dsw 0 | ||
296 | * byte 2(GS): 0 x10 x9 x8 x7 ? gs-dsw pt-dsw | ||
297 | * byte 3: 0 y9 y8 y7 1 0 swr swl | ||
298 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | ||
299 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | ||
300 | * | ||
301 | * ?'s are not defined in the protocol spec, may vary between models. | ||
302 | * | ||
303 | * swr/swl are the left/right buttons. | ||
304 | * | ||
305 | * pt-dsw/gs-dsw indicate that the pt/gs sensor is detecting a | ||
306 | * pen/finger | ||
146 | */ | 307 | */ |
147 | static int hgpk_validate_byte(unsigned char *packet) | 308 | static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) |
148 | { | 309 | { |
149 | return (packet[0] & 0x0C) != 0x08; | 310 | struct hgpk_data *priv = psmouse->private; |
311 | int pktcnt = psmouse->pktcnt; | ||
312 | bool valid; | ||
313 | |||
314 | switch (priv->mode) { | ||
315 | case HGPK_MODE_MOUSE: | ||
316 | valid = (packet[0] & 0x0C) == 0x08; | ||
317 | break; | ||
318 | |||
319 | case HGPK_MODE_GLIDESENSOR: | ||
320 | valid = pktcnt == 1 ? | ||
321 | packet[0] == HGPK_GS : !(packet[pktcnt - 1] & 0x80); | ||
322 | break; | ||
323 | |||
324 | case HGPK_MODE_PENTABLET: | ||
325 | valid = pktcnt == 1 ? | ||
326 | packet[0] == HGPK_PT : !(packet[pktcnt - 1] & 0x80); | ||
327 | break; | ||
328 | |||
329 | default: | ||
330 | valid = false; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (!valid) | ||
335 | hgpk_dbg(psmouse, | ||
336 | "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", | ||
337 | priv->mode, pktcnt, | ||
338 | psmouse->packet[0], psmouse->packet[1], | ||
339 | psmouse->packet[2], psmouse->packet[3], | ||
340 | psmouse->packet[4], psmouse->packet[5]); | ||
341 | |||
342 | return valid; | ||
150 | } | 343 | } |
151 | 344 | ||
152 | static void hgpk_process_packet(struct psmouse *psmouse) | 345 | static void hgpk_process_advanced_packet(struct psmouse *psmouse) |
153 | { | 346 | { |
154 | struct input_dev *dev = psmouse->dev; | 347 | struct hgpk_data *priv = psmouse->private; |
348 | struct input_dev *idev = psmouse->dev; | ||
155 | unsigned char *packet = psmouse->packet; | 349 | unsigned char *packet = psmouse->packet; |
156 | int x, y, left, right; | 350 | int down = !!(packet[2] & 2); |
351 | int left = !!(packet[3] & 1); | ||
352 | int right = !!(packet[3] & 2); | ||
353 | int x = packet[1] | ((packet[2] & 0x78) << 4); | ||
354 | int y = packet[4] | ((packet[3] & 0x70) << 3); | ||
355 | |||
356 | if (priv->mode == HGPK_MODE_GLIDESENSOR) { | ||
357 | int pt_down = !!(packet[2] & 1); | ||
358 | int finger_down = !!(packet[2] & 2); | ||
359 | int z = packet[5]; | ||
360 | |||
361 | input_report_abs(idev, ABS_PRESSURE, z); | ||
362 | if (tpdebug) | ||
363 | hgpk_dbg(psmouse, "pd=%d fd=%d z=%d", | ||
364 | pt_down, finger_down, z); | ||
365 | } else { | ||
366 | /* | ||
367 | * PenTablet mode does not report pressure, so we don't | ||
368 | * report it here | ||
369 | */ | ||
370 | if (tpdebug) | ||
371 | hgpk_dbg(psmouse, "pd=%d ", down); | ||
372 | } | ||
373 | |||
374 | if (tpdebug) | ||
375 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | ||
376 | |||
377 | input_report_key(idev, BTN_TOUCH, down); | ||
378 | input_report_key(idev, BTN_LEFT, left); | ||
379 | input_report_key(idev, BTN_RIGHT, right); | ||
380 | |||
381 | /* | ||
382 | * If this packet says that the finger was removed, reset our position | ||
383 | * tracking so that we don't erroneously detect a jump on next press. | ||
384 | */ | ||
385 | if (!down) { | ||
386 | hgpk_reset_hack_state(psmouse); | ||
387 | goto done; | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * Weed out duplicate packets (we get quite a few, and they mess up | ||
392 | * our jump detection) | ||
393 | */ | ||
394 | if (x == priv->abs_x && y == priv->abs_y) { | ||
395 | if (++priv->dupe_count > SPEW_WATCH_COUNT) { | ||
396 | if (tpdebug) | ||
397 | hgpk_dbg(psmouse, "hard spew detected\n"); | ||
398 | priv->spew_flag = RECALIBRATING; | ||
399 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
400 | msecs_to_jiffies(spew_delay)); | ||
401 | } | ||
402 | goto done; | ||
403 | } | ||
157 | 404 | ||
158 | left = packet[0] & 1; | 405 | /* not a duplicate, continue with position reporting */ |
159 | right = (packet[0] >> 1) & 1; | 406 | priv->dupe_count = 0; |
407 | |||
408 | /* Don't apply hacks in PT mode, it seems reliable */ | ||
409 | if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) { | ||
410 | int x_diff = priv->abs_x - x; | ||
411 | int y_diff = priv->abs_y - y; | ||
412 | if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) { | ||
413 | if (tpdebug) | ||
414 | hgpk_dbg(psmouse, "discarding\n"); | ||
415 | goto done; | ||
416 | } | ||
417 | hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff); | ||
418 | } | ||
160 | 419 | ||
161 | x = packet[1] - ((packet[0] << 4) & 0x100); | 420 | input_report_abs(idev, ABS_X, x); |
162 | y = ((packet[0] << 3) & 0x100) - packet[2]; | 421 | input_report_abs(idev, ABS_Y, y); |
422 | priv->abs_x = x; | ||
423 | priv->abs_y = y; | ||
424 | |||
425 | done: | ||
426 | input_sync(idev); | ||
427 | } | ||
428 | |||
429 | static void hgpk_process_simple_packet(struct psmouse *psmouse) | ||
430 | { | ||
431 | struct input_dev *dev = psmouse->dev; | ||
432 | unsigned char *packet = psmouse->packet; | ||
433 | int left = packet[0] & 1; | ||
434 | int right = (packet[0] >> 1) & 1; | ||
435 | int x = packet[1] - ((packet[0] << 4) & 0x100); | ||
436 | int y = ((packet[0] << 3) & 0x100) - packet[2]; | ||
437 | |||
438 | if (packet[0] & 0xc0) | ||
439 | hgpk_dbg(psmouse, | ||
440 | "overflow -- 0x%02x 0x%02x 0x%02x\n", | ||
441 | packet[0], packet[1], packet[2]); | ||
442 | |||
443 | if (hgpk_discard_decay_hack(psmouse, x, y)) { | ||
444 | if (tpdebug) | ||
445 | hgpk_dbg(psmouse, "discarding\n"); | ||
446 | return; | ||
447 | } | ||
163 | 448 | ||
164 | hgpk_jumpy_hack(psmouse, x, y); | ||
165 | hgpk_spewing_hack(psmouse, left, right, x, y); | 449 | hgpk_spewing_hack(psmouse, left, right, x, y); |
166 | 450 | ||
167 | if (tpdebug) | 451 | if (tpdebug) |
@@ -180,15 +464,14 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | |||
180 | { | 464 | { |
181 | struct hgpk_data *priv = psmouse->private; | 465 | struct hgpk_data *priv = psmouse->private; |
182 | 466 | ||
183 | if (hgpk_validate_byte(psmouse->packet)) { | 467 | if (!hgpk_is_byte_valid(psmouse, psmouse->packet)) |
184 | hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n", | ||
185 | __func__, psmouse->pktcnt, psmouse->packet[0], | ||
186 | psmouse->packet[1], psmouse->packet[2]); | ||
187 | return PSMOUSE_BAD_DATA; | 468 | return PSMOUSE_BAD_DATA; |
188 | } | ||
189 | 469 | ||
190 | if (psmouse->pktcnt >= psmouse->pktsize) { | 470 | if (psmouse->pktcnt >= psmouse->pktsize) { |
191 | hgpk_process_packet(psmouse); | 471 | if (priv->mode == HGPK_MODE_MOUSE) |
472 | hgpk_process_simple_packet(psmouse); | ||
473 | else | ||
474 | hgpk_process_advanced_packet(psmouse); | ||
192 | return PSMOUSE_FULL_PACKET; | 475 | return PSMOUSE_FULL_PACKET; |
193 | } | 476 | } |
194 | 477 | ||
@@ -210,33 +493,176 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | |||
210 | return PSMOUSE_GOOD_DATA; | 493 | return PSMOUSE_GOOD_DATA; |
211 | } | 494 | } |
212 | 495 | ||
496 | static int hgpk_select_mode(struct psmouse *psmouse) | ||
497 | { | ||
498 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
499 | struct hgpk_data *priv = psmouse->private; | ||
500 | int i; | ||
501 | int cmd; | ||
502 | |||
503 | /* | ||
504 | * 4 disables to enable advanced mode | ||
505 | * then 3 0xf2 bytes as the preamble for GS/PT selection | ||
506 | */ | ||
507 | const int advanced_init[] = { | ||
508 | PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, | ||
509 | PSMOUSE_CMD_DISABLE, PSMOUSE_CMD_DISABLE, | ||
510 | 0xf2, 0xf2, 0xf2, | ||
511 | }; | ||
512 | |||
513 | switch (priv->mode) { | ||
514 | case HGPK_MODE_MOUSE: | ||
515 | psmouse->pktsize = 3; | ||
516 | break; | ||
517 | |||
518 | case HGPK_MODE_GLIDESENSOR: | ||
519 | case HGPK_MODE_PENTABLET: | ||
520 | psmouse->pktsize = 6; | ||
521 | |||
522 | /* Switch to 'Advanced mode.', four disables in a row. */ | ||
523 | for (i = 0; i < ARRAY_SIZE(advanced_init); i++) | ||
524 | if (ps2_command(ps2dev, NULL, advanced_init[i])) | ||
525 | return -EIO; | ||
526 | |||
527 | /* select between GlideSensor (mouse) or PenTablet */ | ||
528 | cmd = priv->mode == HGPK_MODE_GLIDESENSOR ? | ||
529 | PSMOUSE_CMD_SETSCALE11 : PSMOUSE_CMD_SETSCALE21; | ||
530 | |||
531 | if (ps2_command(ps2dev, NULL, cmd)) | ||
532 | return -EIO; | ||
533 | break; | ||
534 | |||
535 | default: | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static void hgpk_setup_input_device(struct input_dev *input, | ||
543 | struct input_dev *old_input, | ||
544 | enum hgpk_mode mode) | ||
545 | { | ||
546 | if (old_input) { | ||
547 | input->name = old_input->name; | ||
548 | input->phys = old_input->phys; | ||
549 | input->id = old_input->id; | ||
550 | input->dev.parent = old_input->dev.parent; | ||
551 | } | ||
552 | |||
553 | memset(input->evbit, 0, sizeof(input->evbit)); | ||
554 | memset(input->relbit, 0, sizeof(input->relbit)); | ||
555 | memset(input->keybit, 0, sizeof(input->keybit)); | ||
556 | |||
557 | /* All modes report left and right buttons */ | ||
558 | __set_bit(EV_KEY, input->evbit); | ||
559 | __set_bit(BTN_LEFT, input->keybit); | ||
560 | __set_bit(BTN_RIGHT, input->keybit); | ||
561 | |||
562 | switch (mode) { | ||
563 | case HGPK_MODE_MOUSE: | ||
564 | __set_bit(EV_REL, input->evbit); | ||
565 | __set_bit(REL_X, input->relbit); | ||
566 | __set_bit(REL_Y, input->relbit); | ||
567 | break; | ||
568 | |||
569 | case HGPK_MODE_GLIDESENSOR: | ||
570 | __set_bit(BTN_TOUCH, input->keybit); | ||
571 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
572 | |||
573 | __set_bit(EV_ABS, input->evbit); | ||
574 | |||
575 | /* GlideSensor has pressure sensor, PenTablet does not */ | ||
576 | input_set_abs_params(input, ABS_PRESSURE, 0, 15, 0, 0); | ||
577 | |||
578 | /* From device specs */ | ||
579 | input_set_abs_params(input, ABS_X, 0, 399, 0, 0); | ||
580 | input_set_abs_params(input, ABS_Y, 0, 290, 0, 0); | ||
581 | |||
582 | /* Calculated by hand based on usable size (52mm x 38mm) */ | ||
583 | input_abs_set_res(input, ABS_X, 8); | ||
584 | input_abs_set_res(input, ABS_Y, 8); | ||
585 | break; | ||
586 | |||
587 | case HGPK_MODE_PENTABLET: | ||
588 | __set_bit(BTN_TOUCH, input->keybit); | ||
589 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
590 | |||
591 | __set_bit(EV_ABS, input->evbit); | ||
592 | |||
593 | /* From device specs */ | ||
594 | input_set_abs_params(input, ABS_X, 0, 999, 0, 0); | ||
595 | input_set_abs_params(input, ABS_Y, 5, 239, 0, 0); | ||
596 | |||
597 | /* Calculated by hand based on usable size (156mm x 38mm) */ | ||
598 | input_abs_set_res(input, ABS_X, 6); | ||
599 | input_abs_set_res(input, ABS_Y, 8); | ||
600 | break; | ||
601 | |||
602 | default: | ||
603 | BUG(); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) | ||
608 | { | ||
609 | int err; | ||
610 | |||
611 | psmouse_reset(psmouse); | ||
612 | |||
613 | if (recalibrate) { | ||
614 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
615 | |||
616 | /* send the recalibrate request */ | ||
617 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
618 | ps2_command(ps2dev, NULL, 0xf5) || | ||
619 | ps2_command(ps2dev, NULL, 0xe6) || | ||
620 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
621 | return -1; | ||
622 | } | ||
623 | |||
624 | /* according to ALPS, 150mS is required for recalibration */ | ||
625 | msleep(150); | ||
626 | } | ||
627 | |||
628 | err = hgpk_select_mode(psmouse); | ||
629 | if (err) { | ||
630 | hgpk_err(psmouse, "failed to select mode\n"); | ||
631 | return err; | ||
632 | } | ||
633 | |||
634 | hgpk_reset_hack_state(psmouse); | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
213 | static int hgpk_force_recalibrate(struct psmouse *psmouse) | 639 | static int hgpk_force_recalibrate(struct psmouse *psmouse) |
214 | { | 640 | { |
215 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 641 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
216 | struct hgpk_data *priv = psmouse->private; | 642 | struct hgpk_data *priv = psmouse->private; |
643 | int err; | ||
217 | 644 | ||
218 | /* C-series touchpads added the recalibrate command */ | 645 | /* C-series touchpads added the recalibrate command */ |
219 | if (psmouse->model < HGPK_MODEL_C) | 646 | if (psmouse->model < HGPK_MODEL_C) |
220 | return 0; | 647 | return 0; |
221 | 648 | ||
649 | if (!autorecal) { | ||
650 | hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n"); | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
655 | |||
222 | /* we don't want to race with the irq handler, nor with resyncs */ | 656 | /* we don't want to race with the irq handler, nor with resyncs */ |
223 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 657 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
224 | 658 | ||
225 | /* start by resetting the device */ | 659 | /* start by resetting the device */ |
226 | psmouse_reset(psmouse); | 660 | err = hgpk_reset_device(psmouse, true); |
227 | 661 | if (err) | |
228 | /* send the recalibrate request */ | 662 | return err; |
229 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
230 | ps2_command(ps2dev, NULL, 0xf5) || | ||
231 | ps2_command(ps2dev, NULL, 0xe6) || | ||
232 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
233 | return -1; | ||
234 | } | ||
235 | |||
236 | /* according to ALPS, 150mS is required for recalibration */ | ||
237 | msleep(150); | ||
238 | 663 | ||
239 | /* XXX: If a finger is down during this delay, recalibration will | 664 | /* |
665 | * XXX: If a finger is down during this delay, recalibration will | ||
240 | * detect capacitance incorrectly. This is a hardware bug, and | 666 | * detect capacitance incorrectly. This is a hardware bug, and |
241 | * we don't have a good way to deal with it. The 2s window stuff | 667 | * we don't have a good way to deal with it. The 2s window stuff |
242 | * (below) is our best option for now. | 668 | * (below) is our best option for now. |
@@ -247,25 +673,35 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) | |||
247 | 673 | ||
248 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 674 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
249 | 675 | ||
250 | /* After we recalibrate, we shouldn't get any packets for 2s. If | 676 | if (tpdebug) |
251 | * we do, it's likely that someone's finger was on the touchpad. | 677 | hgpk_dbg(psmouse, "touchpad reactivated\n"); |
252 | * If someone's finger *was* on the touchpad, it's probably | 678 | |
253 | * miscalibrated. So, we should schedule another recalibration | 679 | /* |
680 | * If we get packets right away after recalibrating, it's likely | ||
681 | * that a finger was on the touchpad. If so, it's probably | ||
682 | * miscalibrated, so we optionally schedule another. | ||
254 | */ | 683 | */ |
255 | priv->recalib_window = jiffies + msecs_to_jiffies(recal_guard_time); | 684 | if (recal_guard_time) |
685 | priv->recalib_window = jiffies + | ||
686 | msecs_to_jiffies(recal_guard_time); | ||
256 | 687 | ||
257 | return 0; | 688 | return 0; |
258 | } | 689 | } |
259 | 690 | ||
260 | /* | 691 | /* |
261 | * This kills power to the touchpad; according to ALPS, current consumption | 692 | * This puts the touchpad in a power saving mode; according to ALPS, current |
262 | * goes down to 50uA after running this. To turn power back on, we drive | 693 | * consumption goes down to 50uA after running this. To turn power back on, |
263 | * MS-DAT low. | 694 | * we drive MS-DAT low. Measuring with a 1mA resolution ammeter says that |
695 | * the current on the SUS_3.3V rail drops from 3mA or 4mA to 0 when we do this. | ||
696 | * | ||
697 | * We have no formal spec that details this operation -- the low-power | ||
698 | * sequence came from a long-lost email trail. | ||
264 | */ | 699 | */ |
265 | static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | 700 | static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable) |
266 | { | 701 | { |
267 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 702 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
268 | int timeo; | 703 | int timeo; |
704 | int err; | ||
269 | 705 | ||
270 | /* Added on D-series touchpads */ | 706 | /* Added on D-series touchpads */ |
271 | if (psmouse->model < HGPK_MODEL_D) | 707 | if (psmouse->model < HGPK_MODEL_D) |
@@ -279,24 +715,27 @@ static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | |||
279 | * the controller. Once we get an ACK back from it, it | 715 | * the controller. Once we get an ACK back from it, it |
280 | * means we can continue with the touchpad re-init. ALPS | 716 | * means we can continue with the touchpad re-init. ALPS |
281 | * tells us that 1s should be long enough, so set that as | 717 | * tells us that 1s should be long enough, so set that as |
282 | * the upper bound. | 718 | * the upper bound. (in practice, it takes about 3 loops.) |
283 | */ | 719 | */ |
284 | for (timeo = 20; timeo > 0; timeo--) { | 720 | for (timeo = 20; timeo > 0; timeo--) { |
285 | if (!ps2_sendbyte(&psmouse->ps2dev, | 721 | if (!ps2_sendbyte(&psmouse->ps2dev, |
286 | PSMOUSE_CMD_DISABLE, 20)) | 722 | PSMOUSE_CMD_DISABLE, 20)) |
287 | break; | 723 | break; |
288 | msleep(50); | 724 | msleep(25); |
289 | } | 725 | } |
290 | 726 | ||
291 | psmouse_reset(psmouse); | 727 | err = hgpk_reset_device(psmouse, false); |
728 | if (err) { | ||
729 | hgpk_err(psmouse, "Failed to reset device!\n"); | ||
730 | return err; | ||
731 | } | ||
292 | 732 | ||
293 | /* should be all set, enable the touchpad */ | 733 | /* should be all set, enable the touchpad */ |
294 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 734 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
295 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 735 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
296 | 736 | hgpk_dbg(psmouse, "Touchpad powered up.\n"); | |
297 | } else { | 737 | } else { |
298 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); | 738 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); |
299 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
300 | 739 | ||
301 | if (ps2_command(ps2dev, NULL, 0xec) || | 740 | if (ps2_command(ps2dev, NULL, 0xec) || |
302 | ps2_command(ps2dev, NULL, 0xec) || | 741 | ps2_command(ps2dev, NULL, 0xec) || |
@@ -304,6 +743,8 @@ static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | |||
304 | return -1; | 743 | return -1; |
305 | } | 744 | } |
306 | 745 | ||
746 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
747 | |||
307 | /* probably won't see an ACK, the touchpad will be off */ | 748 | /* probably won't see an ACK, the touchpad will be off */ |
308 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); | 749 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); |
309 | } | 750 | } |
@@ -319,17 +760,20 @@ static int hgpk_poll(struct psmouse *psmouse) | |||
319 | 760 | ||
320 | static int hgpk_reconnect(struct psmouse *psmouse) | 761 | static int hgpk_reconnect(struct psmouse *psmouse) |
321 | { | 762 | { |
322 | /* During suspend/resume the ps2 rails remain powered. We don't want | 763 | struct hgpk_data *priv = psmouse->private; |
764 | |||
765 | /* | ||
766 | * During suspend/resume the ps2 rails remain powered. We don't want | ||
323 | * to do a reset because it's flush data out of buffers; however, | 767 | * to do a reset because it's flush data out of buffers; however, |
324 | * earlier prototypes (B1) had some brokenness that required a reset. */ | 768 | * earlier prototypes (B1) had some brokenness that required a reset. |
769 | */ | ||
325 | if (olpc_board_at_least(olpc_board(0xb2))) | 770 | if (olpc_board_at_least(olpc_board(0xb2))) |
326 | if (psmouse->ps2dev.serio->dev.power.power_state.event != | 771 | if (psmouse->ps2dev.serio->dev.power.power_state.event != |
327 | PM_EVENT_ON) | 772 | PM_EVENT_ON) |
328 | return 0; | 773 | return 0; |
329 | 774 | ||
330 | psmouse_reset(psmouse); | 775 | priv->powered = 1; |
331 | 776 | return hgpk_reset_device(psmouse, false); | |
332 | return 0; | ||
333 | } | 777 | } |
334 | 778 | ||
335 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) | 779 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) |
@@ -355,7 +799,7 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
355 | * hgpk_toggle_power will deal w/ state so | 799 | * hgpk_toggle_power will deal w/ state so |
356 | * we're not racing w/ irq | 800 | * we're not racing w/ irq |
357 | */ | 801 | */ |
358 | err = hgpk_toggle_power(psmouse, value); | 802 | err = hgpk_toggle_powersave(psmouse, value); |
359 | if (!err) | 803 | if (!err) |
360 | priv->powered = value; | 804 | priv->powered = value; |
361 | } | 805 | } |
@@ -366,6 +810,65 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
366 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 810 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
367 | hgpk_show_powered, hgpk_set_powered, false); | 811 | hgpk_show_powered, hgpk_set_powered, false); |
368 | 812 | ||
813 | static ssize_t attr_show_mode(struct psmouse *psmouse, void *data, char *buf) | ||
814 | { | ||
815 | struct hgpk_data *priv = psmouse->private; | ||
816 | |||
817 | return sprintf(buf, "%s\n", hgpk_mode_names[priv->mode]); | ||
818 | } | ||
819 | |||
820 | static ssize_t attr_set_mode(struct psmouse *psmouse, void *data, | ||
821 | const char *buf, size_t len) | ||
822 | { | ||
823 | struct hgpk_data *priv = psmouse->private; | ||
824 | enum hgpk_mode old_mode = priv->mode; | ||
825 | enum hgpk_mode new_mode = hgpk_mode_from_name(buf, len); | ||
826 | struct input_dev *old_dev = psmouse->dev; | ||
827 | struct input_dev *new_dev; | ||
828 | int err; | ||
829 | |||
830 | if (new_mode == HGPK_MODE_INVALID) | ||
831 | return -EINVAL; | ||
832 | |||
833 | if (old_mode == new_mode) | ||
834 | return len; | ||
835 | |||
836 | new_dev = input_allocate_device(); | ||
837 | if (!new_dev) | ||
838 | return -ENOMEM; | ||
839 | |||
840 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
841 | |||
842 | /* Switch device into the new mode */ | ||
843 | priv->mode = new_mode; | ||
844 | err = hgpk_reset_device(psmouse, false); | ||
845 | if (err) | ||
846 | goto err_try_restore; | ||
847 | |||
848 | hgpk_setup_input_device(new_dev, old_dev, new_mode); | ||
849 | |||
850 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
851 | |||
852 | err = input_register_device(new_dev); | ||
853 | if (err) | ||
854 | goto err_try_restore; | ||
855 | |||
856 | psmouse->dev = new_dev; | ||
857 | input_unregister_device(old_dev); | ||
858 | |||
859 | return len; | ||
860 | |||
861 | err_try_restore: | ||
862 | input_free_device(new_dev); | ||
863 | priv->mode = old_mode; | ||
864 | hgpk_reset_device(psmouse, false); | ||
865 | |||
866 | return err; | ||
867 | } | ||
868 | |||
869 | PSMOUSE_DEFINE_ATTR(hgpk_mode, S_IWUSR | S_IRUGO, NULL, | ||
870 | attr_show_mode, attr_set_mode); | ||
871 | |||
369 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | 872 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, |
370 | void *data, char *buf) | 873 | void *data, char *buf) |
371 | { | 874 | { |
@@ -401,6 +904,8 @@ static void hgpk_disconnect(struct psmouse *psmouse) | |||
401 | 904 | ||
402 | device_remove_file(&psmouse->ps2dev.serio->dev, | 905 | device_remove_file(&psmouse->ps2dev.serio->dev, |
403 | &psmouse_attr_powered.dattr); | 906 | &psmouse_attr_powered.dattr); |
907 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
908 | &psmouse_attr_hgpk_mode.dattr); | ||
404 | 909 | ||
405 | if (psmouse->model >= HGPK_MODEL_C) | 910 | if (psmouse->model >= HGPK_MODEL_C) |
406 | device_remove_file(&psmouse->ps2dev.serio->dev, | 911 | device_remove_file(&psmouse->ps2dev.serio->dev, |
@@ -416,14 +921,13 @@ static void hgpk_recalib_work(struct work_struct *work) | |||
416 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); | 921 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); |
417 | struct psmouse *psmouse = priv->psmouse; | 922 | struct psmouse *psmouse = priv->psmouse; |
418 | 923 | ||
419 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
420 | |||
421 | if (hgpk_force_recalibrate(psmouse)) | 924 | if (hgpk_force_recalibrate(psmouse)) |
422 | hgpk_err(psmouse, "recalibration failed!\n"); | 925 | hgpk_err(psmouse, "recalibration failed!\n"); |
423 | } | 926 | } |
424 | 927 | ||
425 | static int hgpk_register(struct psmouse *psmouse) | 928 | static int hgpk_register(struct psmouse *psmouse) |
426 | { | 929 | { |
930 | struct hgpk_data *priv = psmouse->private; | ||
427 | int err; | 931 | int err; |
428 | 932 | ||
429 | /* register handlers */ | 933 | /* register handlers */ |
@@ -431,13 +935,14 @@ static int hgpk_register(struct psmouse *psmouse) | |||
431 | psmouse->poll = hgpk_poll; | 935 | psmouse->poll = hgpk_poll; |
432 | psmouse->disconnect = hgpk_disconnect; | 936 | psmouse->disconnect = hgpk_disconnect; |
433 | psmouse->reconnect = hgpk_reconnect; | 937 | psmouse->reconnect = hgpk_reconnect; |
434 | psmouse->pktsize = 3; | ||
435 | 938 | ||
436 | /* Disable the idle resync. */ | 939 | /* Disable the idle resync. */ |
437 | psmouse->resync_time = 0; | 940 | psmouse->resync_time = 0; |
438 | /* Reset after a lot of bad bytes. */ | 941 | /* Reset after a lot of bad bytes. */ |
439 | psmouse->resetafter = 1024; | 942 | psmouse->resetafter = 1024; |
440 | 943 | ||
944 | hgpk_setup_input_device(psmouse->dev, NULL, priv->mode); | ||
945 | |||
441 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 946 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
442 | &psmouse_attr_powered.dattr); | 947 | &psmouse_attr_powered.dattr); |
443 | if (err) { | 948 | if (err) { |
@@ -445,6 +950,13 @@ static int hgpk_register(struct psmouse *psmouse) | |||
445 | return err; | 950 | return err; |
446 | } | 951 | } |
447 | 952 | ||
953 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
954 | &psmouse_attr_hgpk_mode.dattr); | ||
955 | if (err) { | ||
956 | hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n"); | ||
957 | goto err_remove_powered; | ||
958 | } | ||
959 | |||
448 | /* C-series touchpads added the recalibrate command */ | 960 | /* C-series touchpads added the recalibrate command */ |
449 | if (psmouse->model >= HGPK_MODEL_C) { | 961 | if (psmouse->model >= HGPK_MODEL_C) { |
450 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 962 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
@@ -452,30 +964,40 @@ static int hgpk_register(struct psmouse *psmouse) | |||
452 | if (err) { | 964 | if (err) { |
453 | hgpk_err(psmouse, | 965 | hgpk_err(psmouse, |
454 | "Failed creating 'recalibrate' sysfs node\n"); | 966 | "Failed creating 'recalibrate' sysfs node\n"); |
455 | device_remove_file(&psmouse->ps2dev.serio->dev, | 967 | goto err_remove_mode; |
456 | &psmouse_attr_powered.dattr); | ||
457 | return err; | ||
458 | } | 968 | } |
459 | } | 969 | } |
460 | 970 | ||
461 | return 0; | 971 | return 0; |
972 | |||
973 | err_remove_mode: | ||
974 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
975 | &psmouse_attr_hgpk_mode.dattr); | ||
976 | err_remove_powered: | ||
977 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
978 | &psmouse_attr_powered.dattr); | ||
979 | return err; | ||
462 | } | 980 | } |
463 | 981 | ||
464 | int hgpk_init(struct psmouse *psmouse) | 982 | int hgpk_init(struct psmouse *psmouse) |
465 | { | 983 | { |
466 | struct hgpk_data *priv; | 984 | struct hgpk_data *priv; |
467 | int err = -ENOMEM; | 985 | int err; |
468 | 986 | ||
469 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); | 987 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); |
470 | if (!priv) | 988 | if (!priv) { |
989 | err = -ENOMEM; | ||
471 | goto alloc_fail; | 990 | goto alloc_fail; |
991 | } | ||
472 | 992 | ||
473 | psmouse->private = priv; | 993 | psmouse->private = priv; |
994 | |||
474 | priv->psmouse = psmouse; | 995 | priv->psmouse = psmouse; |
475 | priv->powered = true; | 996 | priv->powered = true; |
997 | priv->mode = hgpk_default_mode; | ||
476 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | 998 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); |
477 | 999 | ||
478 | err = psmouse_reset(psmouse); | 1000 | err = hgpk_reset_device(psmouse, false); |
479 | if (err) | 1001 | if (err) |
480 | goto init_fail; | 1002 | goto init_fail; |
481 | 1003 | ||
@@ -531,3 +1053,14 @@ int hgpk_detect(struct psmouse *psmouse, bool set_properties) | |||
531 | 1053 | ||
532 | return 0; | 1054 | return 0; |
533 | } | 1055 | } |
1056 | |||
1057 | void hgpk_module_init(void) | ||
1058 | { | ||
1059 | hgpk_default_mode = hgpk_mode_from_name(hgpk_mode_name, | ||
1060 | strlen(hgpk_mode_name)); | ||
1061 | if (hgpk_default_mode == HGPK_MODE_INVALID) { | ||
1062 | hgpk_default_mode = HGPK_MODE_MOUSE; | ||
1063 | strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE], | ||
1064 | sizeof(hgpk_mode_name)); | ||
1065 | } | ||
1066 | } | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index d61cfd3ee9cb..311c0e87fcbf 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
@@ -5,6 +5,9 @@ | |||
5 | #ifndef _HGPK_H | 5 | #ifndef _HGPK_H |
6 | #define _HGPK_H | 6 | #define _HGPK_H |
7 | 7 | ||
8 | #define HGPK_GS 0xff /* The GlideSensor */ | ||
9 | #define HGPK_PT 0xcf /* The PenTablet */ | ||
10 | |||
8 | enum hgpk_model_t { | 11 | enum hgpk_model_t { |
9 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ | 12 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ |
10 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ | 13 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ |
@@ -13,12 +16,34 @@ enum hgpk_model_t { | |||
13 | HGPK_MODEL_D = 0x50, /* C1, mass production */ | 16 | HGPK_MODEL_D = 0x50, /* C1, mass production */ |
14 | }; | 17 | }; |
15 | 18 | ||
19 | enum hgpk_spew_flag { | ||
20 | NO_SPEW, | ||
21 | MAYBE_SPEWING, | ||
22 | SPEW_DETECTED, | ||
23 | RECALIBRATING, | ||
24 | }; | ||
25 | |||
26 | #define SPEW_WATCH_COUNT 42 /* at 12ms/packet, this is 1/2 second */ | ||
27 | |||
28 | enum hgpk_mode { | ||
29 | HGPK_MODE_MOUSE, | ||
30 | HGPK_MODE_GLIDESENSOR, | ||
31 | HGPK_MODE_PENTABLET, | ||
32 | HGPK_MODE_INVALID | ||
33 | }; | ||
34 | |||
16 | struct hgpk_data { | 35 | struct hgpk_data { |
17 | struct psmouse *psmouse; | 36 | struct psmouse *psmouse; |
37 | enum hgpk_mode mode; | ||
18 | bool powered; | 38 | bool powered; |
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | 39 | enum hgpk_spew_flag spew_flag; |
40 | int spew_count, x_tally, y_tally; /* spew detection */ | ||
20 | unsigned long recalib_window; | 41 | unsigned long recalib_window; |
21 | struct delayed_work recalib_wq; | 42 | struct delayed_work recalib_wq; |
43 | int abs_x, abs_y; | ||
44 | int dupe_count; | ||
45 | int xbigj, ybigj, xlast, ylast; /* jumpiness detection */ | ||
46 | int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ | ||
22 | }; | 47 | }; |
23 | 48 | ||
24 | #define hgpk_dbg(psmouse, format, arg...) \ | 49 | #define hgpk_dbg(psmouse, format, arg...) \ |
@@ -33,9 +58,13 @@ struct hgpk_data { | |||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | 58 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) |
34 | 59 | ||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | 60 | #ifdef CONFIG_MOUSE_PS2_OLPC |
61 | void hgpk_module_init(void); | ||
36 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); | 62 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
37 | int hgpk_init(struct psmouse *psmouse); | 63 | int hgpk_init(struct psmouse *psmouse); |
38 | #else | 64 | #else |
65 | static inline void hgpk_module_init(void) | ||
66 | { | ||
67 | } | ||
39 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) | 68 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
40 | { | 69 | { |
41 | return -ENODEV; | 70 | return -ENODEV; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 73a7af2542a8..3f74baee102b 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -1584,10 +1584,10 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1584 | if (!new_dev) | 1584 | if (!new_dev) |
1585 | return -ENOMEM; | 1585 | return -ENOMEM; |
1586 | 1586 | ||
1587 | while (serio->child) { | 1587 | while (!list_empty(&serio->children)) { |
1588 | if (++retry > 3) { | 1588 | if (++retry > 3) { |
1589 | printk(KERN_WARNING | 1589 | printk(KERN_WARNING |
1590 | "psmouse: failed to destroy child port, " | 1590 | "psmouse: failed to destroy children ports, " |
1591 | "protocol change aborted.\n"); | 1591 | "protocol change aborted.\n"); |
1592 | input_free_device(new_dev); | 1592 | input_free_device(new_dev); |
1593 | return -EIO; | 1593 | return -EIO; |
@@ -1711,6 +1711,7 @@ static int __init psmouse_init(void) | |||
1711 | 1711 | ||
1712 | lifebook_module_init(); | 1712 | lifebook_module_init(); |
1713 | synaptics_module_init(); | 1713 | synaptics_module_init(); |
1714 | hgpk_module_init(); | ||
1714 | 1715 | ||
1715 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | 1716 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); |
1716 | if (!kpsmoused_wq) { | 1717 | if (!kpsmoused_wq) { |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 96b70a43515f..e06e045bf907 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/dmi.h> | 27 | #include <linux/dmi.h> |
28 | #include <linux/input.h> | 28 | #include <linux/input/mt.h> |
29 | #include <linux/serio.h> | 29 | #include <linux/serio.h> |
30 | #include <linux/libps2.h> | 30 | #include <linux/libps2.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -279,6 +279,25 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) | |||
279 | synaptics_mode_cmd(psmouse, priv->mode); | 279 | synaptics_mode_cmd(psmouse, priv->mode); |
280 | } | 280 | } |
281 | 281 | ||
282 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | ||
283 | { | ||
284 | static unsigned char param = 0xc8; | ||
285 | struct synaptics_data *priv = psmouse->private; | ||
286 | |||
287 | if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
288 | return 0; | ||
289 | |||
290 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | ||
291 | return -1; | ||
292 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | ||
293 | return -1; | ||
294 | |||
295 | /* Advanced gesture mode also sends multi finger data */ | ||
296 | priv->capabilities |= BIT(1); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
282 | /***************************************************************************** | 301 | /***************************************************************************** |
283 | * Synaptics pass-through PS/2 port support | 302 | * Synaptics pass-through PS/2 port support |
284 | ****************************************************************************/ | 303 | ****************************************************************************/ |
@@ -294,7 +313,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c) | |||
294 | return 0; | 313 | return 0; |
295 | } | 314 | } |
296 | 315 | ||
297 | static inline int synaptics_is_pt_packet(unsigned char *buf) | 316 | static int synaptics_pt_start(struct serio *serio) |
317 | { | ||
318 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
319 | struct synaptics_data *priv = parent->private; | ||
320 | |||
321 | serio_pause_rx(parent->ps2dev.serio); | ||
322 | priv->pt_port = serio; | ||
323 | serio_continue_rx(parent->ps2dev.serio); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static void synaptics_pt_stop(struct serio *serio) | ||
329 | { | ||
330 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
331 | struct synaptics_data *priv = parent->private; | ||
332 | |||
333 | serio_pause_rx(parent->ps2dev.serio); | ||
334 | priv->pt_port = NULL; | ||
335 | serio_continue_rx(parent->ps2dev.serio); | ||
336 | } | ||
337 | |||
338 | static int synaptics_is_pt_packet(unsigned char *buf) | ||
298 | { | 339 | { |
299 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 340 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
300 | } | 341 | } |
@@ -315,9 +356,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet | |||
315 | 356 | ||
316 | static void synaptics_pt_activate(struct psmouse *psmouse) | 357 | static void synaptics_pt_activate(struct psmouse *psmouse) |
317 | { | 358 | { |
318 | struct serio *ptport = psmouse->ps2dev.serio->child; | ||
319 | struct psmouse *child = serio_get_drvdata(ptport); | ||
320 | struct synaptics_data *priv = psmouse->private; | 359 | struct synaptics_data *priv = psmouse->private; |
360 | struct psmouse *child = serio_get_drvdata(priv->pt_port); | ||
321 | 361 | ||
322 | /* adjust the touchpad to child's choice of protocol */ | 362 | /* adjust the touchpad to child's choice of protocol */ |
323 | if (child) { | 363 | if (child) { |
@@ -345,6 +385,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
345 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); | 385 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); |
346 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); | 386 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); |
347 | serio->write = synaptics_pt_write; | 387 | serio->write = synaptics_pt_write; |
388 | serio->start = synaptics_pt_start; | ||
389 | serio->stop = synaptics_pt_stop; | ||
348 | serio->parent = psmouse->ps2dev.serio; | 390 | serio->parent = psmouse->ps2dev.serio; |
349 | 391 | ||
350 | psmouse->pt_activate = synaptics_pt_activate; | 392 | psmouse->pt_activate = synaptics_pt_activate; |
@@ -357,7 +399,9 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
357 | * Functions to interpret the absolute mode packets | 399 | * Functions to interpret the absolute mode packets |
358 | ****************************************************************************/ | 400 | ****************************************************************************/ |
359 | 401 | ||
360 | static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) | 402 | static int synaptics_parse_hw_state(const unsigned char buf[], |
403 | struct synaptics_data *priv, | ||
404 | struct synaptics_hw_state *hw) | ||
361 | { | 405 | { |
362 | memset(hw, 0, sizeof(struct synaptics_hw_state)); | 406 | memset(hw, 0, sizeof(struct synaptics_hw_state)); |
363 | 407 | ||
@@ -374,6 +418,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
374 | ((buf[0] & 0x04) >> 1) | | 418 | ((buf[0] & 0x04) >> 1) | |
375 | ((buf[3] & 0x04) >> 2)); | 419 | ((buf[3] & 0x04) >> 2)); |
376 | 420 | ||
421 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { | ||
422 | /* Gesture packet: (x, y, z) at half resolution */ | ||
423 | priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | ||
424 | priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | ||
425 | priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | ||
426 | return 1; | ||
427 | } | ||
428 | |||
377 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 429 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
378 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 430 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
379 | 431 | ||
@@ -429,6 +481,36 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
429 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 481 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
430 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 482 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
431 | } | 483 | } |
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y) | ||
489 | { | ||
490 | input_mt_slot(dev, slot); | ||
491 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
492 | if (active) { | ||
493 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
494 | input_report_abs(dev, ABS_MT_POSITION_Y, | ||
495 | YMAX_NOMINAL + YMIN_NOMINAL - y); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | static void synaptics_report_semi_mt_data(struct input_dev *dev, | ||
500 | const struct synaptics_hw_state *a, | ||
501 | const struct synaptics_hw_state *b, | ||
502 | int num_fingers) | ||
503 | { | ||
504 | if (num_fingers >= 2) { | ||
505 | set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y)); | ||
506 | set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y)); | ||
507 | } else if (num_fingers == 1) { | ||
508 | set_slot(dev, 0, true, a->x, a->y); | ||
509 | set_slot(dev, 1, false, 0, 0); | ||
510 | } else { | ||
511 | set_slot(dev, 0, false, 0, 0); | ||
512 | set_slot(dev, 1, false, 0, 0); | ||
513 | } | ||
432 | } | 514 | } |
433 | 515 | ||
434 | /* | 516 | /* |
@@ -443,7 +525,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
443 | int finger_width; | 525 | int finger_width; |
444 | int i; | 526 | int i; |
445 | 527 | ||
446 | synaptics_parse_hw_state(psmouse->packet, priv, &hw); | 528 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) |
529 | return; | ||
447 | 530 | ||
448 | if (hw.scroll) { | 531 | if (hw.scroll) { |
449 | priv->scroll += hw.scroll; | 532 | priv->scroll += hw.scroll; |
@@ -465,7 +548,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
465 | return; | 548 | return; |
466 | } | 549 | } |
467 | 550 | ||
468 | if (hw.z > 0) { | 551 | if (hw.z > 0 && hw.x > 1) { |
469 | num_fingers = 1; | 552 | num_fingers = 1; |
470 | finger_width = 5; | 553 | finger_width = 5; |
471 | if (SYN_CAP_EXTENDED(priv->capabilities)) { | 554 | if (SYN_CAP_EXTENDED(priv->capabilities)) { |
@@ -489,6 +572,9 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
489 | finger_width = 0; | 572 | finger_width = 0; |
490 | } | 573 | } |
491 | 574 | ||
575 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
576 | synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers); | ||
577 | |||
492 | /* Post events | 578 | /* Post events |
493 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 579 | * BTN_TOUCH has to be first as mousedev relies on it when doing |
494 | * absolute -> relative conversion | 580 | * absolute -> relative conversion |
@@ -496,7 +582,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
496 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | 582 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); |
497 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | 583 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); |
498 | 584 | ||
499 | if (hw.z > 0) { | 585 | if (num_fingers > 0) { |
500 | input_report_abs(dev, ABS_X, hw.x); | 586 | input_report_abs(dev, ABS_X, hw.x); |
501 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | 587 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); |
502 | } | 588 | } |
@@ -578,9 +664,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
578 | if (unlikely(priv->pkt_type == SYN_NEWABS)) | 664 | if (unlikely(priv->pkt_type == SYN_NEWABS)) |
579 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); | 665 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); |
580 | 666 | ||
581 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { | 667 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
582 | if (psmouse->ps2dev.serio->child) | 668 | synaptics_is_pt_packet(psmouse->packet)) { |
583 | synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet); | 669 | if (priv->pt_port) |
670 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | ||
584 | } else | 671 | } else |
585 | synaptics_process_packet(psmouse); | 672 | synaptics_process_packet(psmouse); |
586 | 673 | ||
@@ -598,6 +685,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
598 | { | 685 | { |
599 | int i; | 686 | int i; |
600 | 687 | ||
688 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | ||
689 | |||
601 | __set_bit(EV_ABS, dev->evbit); | 690 | __set_bit(EV_ABS, dev->evbit); |
602 | input_set_abs_params(dev, ABS_X, | 691 | input_set_abs_params(dev, ABS_X, |
603 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); | 692 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); |
@@ -605,6 +694,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
605 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); | 694 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); |
606 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 695 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
607 | 696 | ||
697 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | ||
698 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
699 | input_mt_init_slots(dev, 2); | ||
700 | input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, | ||
701 | priv->x_max ?: XMAX_NOMINAL, 0, 0); | ||
702 | input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, | ||
703 | priv->y_max ?: YMAX_NOMINAL, 0, 0); | ||
704 | } | ||
705 | |||
608 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 706 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
609 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | 707 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); |
610 | 708 | ||
@@ -639,6 +737,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
639 | input_abs_set_res(dev, ABS_Y, priv->y_res); | 737 | input_abs_set_res(dev, ABS_Y, priv->y_res); |
640 | 738 | ||
641 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 739 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
740 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | ||
642 | /* Clickpads report only left button */ | 741 | /* Clickpads report only left button */ |
643 | __clear_bit(BTN_RIGHT, dev->keybit); | 742 | __clear_bit(BTN_RIGHT, dev->keybit); |
644 | __clear_bit(BTN_MIDDLE, dev->keybit); | 743 | __clear_bit(BTN_MIDDLE, dev->keybit); |
@@ -656,25 +755,46 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
656 | { | 755 | { |
657 | struct synaptics_data *priv = psmouse->private; | 756 | struct synaptics_data *priv = psmouse->private; |
658 | struct synaptics_data old_priv = *priv; | 757 | struct synaptics_data old_priv = *priv; |
758 | int retry = 0; | ||
759 | int error; | ||
659 | 760 | ||
660 | psmouse_reset(psmouse); | 761 | do { |
762 | psmouse_reset(psmouse); | ||
763 | error = synaptics_detect(psmouse, 0); | ||
764 | } while (error && ++retry < 3); | ||
661 | 765 | ||
662 | if (synaptics_detect(psmouse, 0)) | 766 | if (error) |
663 | return -1; | 767 | return -1; |
664 | 768 | ||
769 | if (retry > 1) | ||
770 | printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", | ||
771 | retry); | ||
772 | |||
665 | if (synaptics_query_hardware(psmouse)) { | 773 | if (synaptics_query_hardware(psmouse)) { |
666 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 774 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); |
667 | return -1; | 775 | return -1; |
668 | } | 776 | } |
669 | 777 | ||
778 | if (synaptics_set_absolute_mode(psmouse)) { | ||
779 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | ||
780 | return -1; | ||
781 | } | ||
782 | |||
783 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
784 | printk(KERN_ERR "Advanced gesture mode reconnect failed.\n"); | ||
785 | return -1; | ||
786 | } | ||
787 | |||
670 | if (old_priv.identity != priv->identity || | 788 | if (old_priv.identity != priv->identity || |
671 | old_priv.model_id != priv->model_id || | 789 | old_priv.model_id != priv->model_id || |
672 | old_priv.capabilities != priv->capabilities || | 790 | old_priv.capabilities != priv->capabilities || |
673 | old_priv.ext_cap != priv->ext_cap) | 791 | old_priv.ext_cap != priv->ext_cap) { |
674 | return -1; | 792 | printk(KERN_ERR "Synaptics hardware appears to be different: " |
675 | 793 | "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", | |
676 | if (synaptics_set_absolute_mode(psmouse)) { | 794 | old_priv.identity, priv->identity, |
677 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | 795 | old_priv.model_id, priv->model_id, |
796 | old_priv.capabilities, priv->capabilities, | ||
797 | old_priv.ext_cap, priv->ext_cap); | ||
678 | return -1; | 798 | return -1; |
679 | } | 799 | } |
680 | 800 | ||
@@ -716,22 +836,52 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = { | |||
716 | }, | 836 | }, |
717 | 837 | ||
718 | }, | 838 | }, |
839 | #endif | ||
719 | { } | 840 | { } |
841 | }; | ||
842 | |||
843 | static bool broken_olpc_ec; | ||
844 | |||
845 | static const struct dmi_system_id __initconst olpc_dmi_table[] = { | ||
846 | #if defined(CONFIG_DMI) && defined(CONFIG_OLPC) | ||
847 | { | ||
848 | /* OLPC XO-1 or XO-1.5 */ | ||
849 | .matches = { | ||
850 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), | ||
851 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), | ||
852 | }, | ||
853 | }, | ||
720 | #endif | 854 | #endif |
855 | { } | ||
721 | }; | 856 | }; |
722 | 857 | ||
723 | void __init synaptics_module_init(void) | 858 | void __init synaptics_module_init(void) |
724 | { | 859 | { |
725 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 860 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
861 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | ||
726 | } | 862 | } |
727 | 863 | ||
728 | int synaptics_init(struct psmouse *psmouse) | 864 | int synaptics_init(struct psmouse *psmouse) |
729 | { | 865 | { |
730 | struct synaptics_data *priv; | 866 | struct synaptics_data *priv; |
731 | 867 | ||
868 | /* | ||
869 | * The OLPC XO has issues with Synaptics' absolute mode; similarly to | ||
870 | * the HGPK, it quickly degrades and the hardware becomes jumpy and | ||
871 | * overly sensitive. Not only that, but the constant packet spew | ||
872 | * (even at a lowered 40pps rate) overloads the EC such that key | ||
873 | * presses on the keyboard are missed. Given all of that, don't | ||
874 | * even attempt to use Synaptics mode. Relative mode seems to work | ||
875 | * just fine. | ||
876 | */ | ||
877 | if (broken_olpc_ec) { | ||
878 | printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n"); | ||
879 | return -ENODEV; | ||
880 | } | ||
881 | |||
732 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); | 882 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); |
733 | if (!priv) | 883 | if (!priv) |
734 | return -1; | 884 | return -ENOMEM; |
735 | 885 | ||
736 | psmouse_reset(psmouse); | 886 | psmouse_reset(psmouse); |
737 | 887 | ||
@@ -745,6 +895,11 @@ int synaptics_init(struct psmouse *psmouse) | |||
745 | goto init_fail; | 895 | goto init_fail; |
746 | } | 896 | } |
747 | 897 | ||
898 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
899 | printk(KERN_ERR "Advanced gesture mode init failed.\n"); | ||
900 | goto init_fail; | ||
901 | } | ||
902 | |||
748 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 903 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
749 | 904 | ||
750 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", | 905 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
@@ -778,8 +933,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
778 | 933 | ||
779 | /* | 934 | /* |
780 | * Toshiba's KBC seems to have trouble handling data from | 935 | * Toshiba's KBC seems to have trouble handling data from |
781 | * Synaptics as full rate, switch to lower rate which is roughly | 936 | * Synaptics at full rate. Switch to a lower rate (roughly |
782 | * thye same as rate of standard PS/2 mouse. | 937 | * the same rate as a standard PS/2 mouse). |
783 | */ | 938 | */ |
784 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { | 939 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
785 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", | 940 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index b6aa7d20d8a3..7453938bf5ef 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -51,8 +51,33 @@ | |||
51 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) | 51 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) |
52 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) | 52 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) |
53 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) | 53 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) |
54 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) | 54 | |
55 | /* | ||
56 | * The following describes response for the 0x0c query. | ||
57 | * | ||
58 | * byte mask name meaning | ||
59 | * ---- ---- ------- ------------ | ||
60 | * 1 0x01 adjustable threshold capacitive button sensitivity | ||
61 | * can be adjusted | ||
62 | * 1 0x02 report max query 0x0d gives max coord reported | ||
63 | * 1 0x04 clearpad sensor is ClearPad product | ||
64 | * 1 0x08 advanced gesture not particularly meaningful | ||
65 | * 1 0x10 clickpad bit 0 1-button ClickPad | ||
66 | * 1 0x60 multifinger mode identifies firmware finger counting | ||
67 | * (not reporting!) algorithm. | ||
68 | * Not particularly meaningful | ||
69 | * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered | ||
70 | * 2 0x01 clickpad bit 1 2-button ClickPad | ||
71 | * 2 0x02 deluxe LED controls touchpad support LED commands | ||
72 | * ala multimedia control bar | ||
73 | * 2 0x04 reduced filtering firmware does less filtering on | ||
74 | * position data, driver should watch | ||
75 | * for noise. | ||
76 | */ | ||
77 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | ||
78 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | ||
55 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) | 79 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) |
80 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | ||
56 | 81 | ||
57 | /* synaptics modes query bits */ | 82 | /* synaptics modes query bits */ |
58 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 83 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -110,6 +135,10 @@ struct synaptics_data { | |||
110 | unsigned char pkt_type; /* packet type - old, new, etc */ | 135 | unsigned char pkt_type; /* packet type - old, new, etc */ |
111 | unsigned char mode; /* current mode byte */ | 136 | unsigned char mode; /* current mode byte */ |
112 | int scroll; | 137 | int scroll; |
138 | |||
139 | struct serio *pt_port; /* Pass-through serio port */ | ||
140 | |||
141 | struct synaptics_hw_state mt; /* current gesture packet */ | ||
113 | }; | 142 | }; |
114 | 143 | ||
115 | void synaptics_module_init(void); | 144 | void synaptics_module_init(void); |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 0ae62f0bcb32..cba3c84d2f21 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/pm.h> | ||
21 | 22 | ||
22 | #define DRIVER_NAME "synaptics_i2c" | 23 | #define DRIVER_NAME "synaptics_i2c" |
23 | /* maximum product id is 15 characters */ | 24 | /* maximum product id is 15 characters */ |
@@ -461,7 +462,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) | |||
461 | * While interrupt driven, there is no real need to poll the device. | 462 | * While interrupt driven, there is no real need to poll the device. |
462 | * But touchpads are very sensitive, so there could be errors | 463 | * But touchpads are very sensitive, so there could be errors |
463 | * related to physical environment and the attention line isn't | 464 | * related to physical environment and the attention line isn't |
464 | * neccesarily asserted. In such case we can lose the touchpad. | 465 | * necessarily asserted. In such case we can lose the touchpad. |
465 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | 466 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and |
466 | * if error is detected, we try to reset and reconfigure the touchpad. | 467 | * if error is detected, we try to reset and reconfigure the touchpad. |
467 | */ | 468 | */ |
@@ -619,8 +620,9 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) | |||
619 | } | 620 | } |
620 | 621 | ||
621 | #ifdef CONFIG_PM | 622 | #ifdef CONFIG_PM |
622 | static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 623 | static int synaptics_i2c_suspend(struct device *dev) |
623 | { | 624 | { |
625 | struct i2c_client *client = to_i2c_client(dev); | ||
624 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 626 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
625 | 627 | ||
626 | cancel_delayed_work_sync(&touch->dwork); | 628 | cancel_delayed_work_sync(&touch->dwork); |
@@ -631,9 +633,10 @@ static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | |||
631 | return 0; | 633 | return 0; |
632 | } | 634 | } |
633 | 635 | ||
634 | static int synaptics_i2c_resume(struct i2c_client *client) | 636 | static int synaptics_i2c_resume(struct device *dev) |
635 | { | 637 | { |
636 | int ret; | 638 | int ret; |
639 | struct i2c_client *client = to_i2c_client(dev); | ||
637 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 640 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
638 | 641 | ||
639 | ret = synaptics_i2c_reset_config(client); | 642 | ret = synaptics_i2c_reset_config(client); |
@@ -645,11 +648,11 @@ static int synaptics_i2c_resume(struct i2c_client *client) | |||
645 | 648 | ||
646 | return 0; | 649 | return 0; |
647 | } | 650 | } |
648 | #else | ||
649 | #define synaptics_i2c_suspend NULL | ||
650 | #define synaptics_i2c_resume NULL | ||
651 | #endif | 651 | #endif |
652 | 652 | ||
653 | static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, | ||
654 | synaptics_i2c_resume); | ||
655 | |||
653 | static const struct i2c_device_id synaptics_i2c_id_table[] = { | 656 | static const struct i2c_device_id synaptics_i2c_id_table[] = { |
654 | { "synaptics_i2c", 0 }, | 657 | { "synaptics_i2c", 0 }, |
655 | { }, | 658 | { }, |
@@ -660,13 +663,12 @@ static struct i2c_driver synaptics_i2c_driver = { | |||
660 | .driver = { | 663 | .driver = { |
661 | .name = DRIVER_NAME, | 664 | .name = DRIVER_NAME, |
662 | .owner = THIS_MODULE, | 665 | .owner = THIS_MODULE, |
666 | .pm = &synaptics_i2c_pm, | ||
663 | }, | 667 | }, |
664 | 668 | ||
665 | .probe = synaptics_i2c_probe, | 669 | .probe = synaptics_i2c_probe, |
666 | .remove = __devexit_p(synaptics_i2c_remove), | 670 | .remove = __devexit_p(synaptics_i2c_remove), |
667 | 671 | ||
668 | .suspend = synaptics_i2c_suspend, | ||
669 | .resume = synaptics_i2c_resume, | ||
670 | .id_table = synaptics_i2c_id_table, | 672 | .id_table = synaptics_i2c_id_table, |
671 | }; | 673 | }; |
672 | 674 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 88121c59c3cc..1fd8f5e192f9 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c | |||
@@ -21,8 +21,8 @@ | |||
21 | * | 21 | * |
22 | * Based upon touchkitusb.c | 22 | * Based upon touchkitusb.c |
23 | * | 23 | * |
24 | * Vendor documentation is available in support section of: | 24 | * Vendor documentation is available at: |
25 | * http://www.egalax.com.tw/ | 25 | * http://home.eeti.com.tw/web20/drivers/Software%20Programming%20Guide_v2.0.pdf |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 0643e49ca603..54b2fa892e19 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -303,7 +303,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
303 | 303 | ||
304 | psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); | 304 | psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); |
305 | if (!psmouse->private) | 305 | if (!psmouse->private) |
306 | return -1; | 306 | return -ENOMEM; |
307 | 307 | ||
308 | psmouse->vendor = "IBM"; | 308 | psmouse->vendor = "IBM"; |
309 | psmouse->name = "TrackPoint"; | 309 | psmouse->name = "TrackPoint"; |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index bf2c0c80d6cc..eb9a3cfbeefa 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -334,7 +334,7 @@ static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse) | |||
334 | * M: manufacturer location code | 334 | * M: manufacturer location code |
335 | * R: revision code | 335 | * R: revision code |
336 | * E: Error code. If it's in the range of 0x00..0x1f, only some | 336 | * E: Error code. If it's in the range of 0x00..0x1f, only some |
337 | * minor problem occured. Errors >= 0x20 are considered bad | 337 | * minor problem occurred. Errors >= 0x20 are considered bad |
338 | * and the device may not work properly... | 338 | * and the device may not work properly... |
339 | * D: <0010> == mouse, <0100> == tablet | 339 | * D: <0010> == mouse, <0100> == tablet |
340 | */ | 340 | */ |