| From 1f13ec466759e682e47fab79bd74b8f84cd7bd4a Mon Sep 17 00:00:00 2001 |
| From: Florian Ragwitz <rafl@debian.org> |
| Date: Mon, 3 May 2010 23:29:37 -0700 |
| Subject: Input: elantech - ignore high bits in the position coordinates |
| |
| From: Florian Ragwitz <rafl@debian.org> |
| |
| commit e938fbfd4a7ac829d48b767c4dc365535d5c4f97 upstream. |
| |
| In older versions of the elantech hardware/firmware those bits always |
| were unset, so it didn't actually matter, but newer versions seem to |
| use those high bits for something else, screwing up the coordinates |
| we report to the input layer for those devices. |
| |
| Signed-off-by: Florian Ragwitz <rafl@debian.org> |
| Signed-off-by: Dmitry Torokhov <dtor@mail.ru> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| drivers/input/mouse/elantech.c | 69 ++++++++++++++++++++++++++--------------- |
| 1 file changed, 44 insertions(+), 25 deletions(-) |
| |
| --- a/drivers/input/mouse/elantech.c |
| +++ b/drivers/input/mouse/elantech.c |
| @@ -185,13 +185,17 @@ static void elantech_report_absolute_v1( |
| static int old_fingers; |
| |
| if (etd->fw_version_maj == 0x01) { |
| - /* byte 0: D U p1 p2 1 p3 R L |
| - byte 1: f 0 th tw x9 x8 y9 y8 */ |
| + /* |
| + * byte 0: D U p1 p2 1 p3 R L |
| + * byte 1: f 0 th tw x9 x8 y9 y8 |
| + */ |
| fingers = ((packet[1] & 0x80) >> 7) + |
| ((packet[1] & 0x30) >> 4); |
| } else { |
| - /* byte 0: n1 n0 p2 p1 1 p3 R L |
| - byte 1: 0 0 0 0 x9 x8 y9 y8 */ |
| + /* |
| + * byte 0: n1 n0 p2 p1 1 p3 R L |
| + * byte 1: 0 0 0 0 x9 x8 y9 y8 |
| + */ |
| fingers = (packet[0] & 0xc0) >> 6; |
| } |
| |
| @@ -205,13 +209,15 @@ static void elantech_report_absolute_v1( |
| |
| input_report_key(dev, BTN_TOUCH, fingers != 0); |
| |
| - /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
| - byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ |
| + /* |
| + * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
| + * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 |
| + */ |
| if (fingers) { |
| input_report_abs(dev, ABS_X, |
| ((packet[1] & 0x0c) << 6) | packet[2]); |
| - input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - |
| - (((packet[1] & 0x03) << 8) | packet[3])); |
| + input_report_abs(dev, ABS_Y, |
| + ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); |
| } |
| |
| input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
| @@ -250,34 +256,47 @@ static void elantech_report_absolute_v2( |
| |
| switch (fingers) { |
| case 1: |
| - /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 |
| - byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ |
| - input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); |
| - /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 |
| - byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ |
| - input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - |
| - ((packet[4] << 8) | packet[5])); |
| + /* |
| + * byte 1: . . . . . x10 x9 x8 |
| + * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
| + */ |
| + input_report_abs(dev, ABS_X, |
| + ((packet[1] & 0x07) << 8) | packet[2]); |
| + /* |
| + * byte 4: . . . . . . y9 y8 |
| + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
| + */ |
| + input_report_abs(dev, ABS_Y, |
| + ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); |
| break; |
| |
| case 2: |
| - /* The coordinate of each finger is reported separately with |
| - a lower resolution for two finger touches */ |
| - /* byte 0: . . ay8 ax8 . . . . |
| - byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ |
| + /* |
| + * The coordinate of each finger is reported separately |
| + * with a lower resolution for two finger touches: |
| + * byte 0: . . ay8 ax8 . . . . |
| + * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 |
| + */ |
| x1 = ((packet[0] & 0x10) << 4) | packet[1]; |
| /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
| y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); |
| - /* byte 3: . . by8 bx8 . . . . |
| - byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ |
| + /* |
| + * byte 3: . . by8 bx8 . . . . |
| + * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 |
| + */ |
| x2 = ((packet[3] & 0x10) << 4) | packet[4]; |
| /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
| y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); |
| - /* For compatibility with the X Synaptics driver scale up one |
| - coordinate and report as ordinary mouse movent */ |
| + /* |
| + * For compatibility with the X Synaptics driver scale up |
| + * one coordinate and report as ordinary mouse movent |
| + */ |
| input_report_abs(dev, ABS_X, x1 << 2); |
| input_report_abs(dev, ABS_Y, y1 << 2); |
| - /* For compatibility with the proprietary X Elantech driver |
| - report both coordinates as hat coordinates */ |
| + /* |
| + * For compatibility with the proprietary X Elantech driver |
| + * report both coordinates as hat coordinates |
| + */ |
| input_report_abs(dev, ABS_HAT0X, x1); |
| input_report_abs(dev, ABS_HAT0Y, y1); |
| input_report_abs(dev, ABS_HAT1X, x2); |