From f941c705f68fa62f694678bf2efde64dfb9962bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Mon, 16 May 2011 22:45:54 -0700 Subject: Input: elantech - export pressure and width when supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the info of the Dell/Ubuntu driver, described in the protocol document, report both width and pressure when pressing 1 and 3 fingers, for the versions of the touchpad which support it. Signed-off-by: Éric Piel Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 23 ++++++++++++++++++++++- drivers/input/mouse/elantech.h | 6 ++++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 04d9bf320a4f..5cde11f4ef5e 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -248,9 +248,10 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) */ static void elantech_report_absolute_v2(struct psmouse *psmouse) { + struct elantech_data *etd = psmouse->private; struct input_dev *dev = psmouse->dev; unsigned char *packet = psmouse->packet; - int fingers, x1, y1, x2, y2; + int fingers, x1, y1, x2, y2, width = 0, pres = 0; /* byte 0: n1 n0 . . . . R L */ fingers = (packet[0] & 0xc0) >> 6; @@ -278,6 +279,8 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) */ input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); break; case 2: @@ -311,6 +314,10 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) input_report_abs(dev, ABS_HAT0Y, y1); input_report_abs(dev, ABS_HAT1X, x2); input_report_abs(dev, ABS_HAT1Y, y2); + + /* Unknown so just report sensible values */ + pres = 127; + width = 7; break; } @@ -320,6 +327,10 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + if (etd->reports_pressure) { + input_report_abs(dev, ABS_PRESSURE, pres); + input_report_abs(dev, ABS_TOOL_WIDTH, width); + } input_sync(dev); } @@ -478,6 +489,12 @@ static void elantech_set_input_params(struct psmouse *psmouse) __set_bit(BTN_TOOL_QUADTAP, dev->keybit); input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); + if (etd->reports_pressure) { + input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, + ETP_PMAX_V2, 0, 0); + input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, + ETP_WMAX_V2, 0, 0); + } input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); input_set_abs_params(dev, ABS_HAT0Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); input_set_abs_params(dev, ABS_HAT1X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); @@ -725,6 +742,10 @@ int elantech_init(struct psmouse *psmouse) etd->debug = 1; /* Don't know how to do parity checking for version 2 */ etd->paritycheck = 0; + + if (etd->fw_version >= 0x020800) + etd->reports_pressure = true; + } else { etd->hw_version = 1; 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 @@ #define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) #define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) +#define ETP_PMIN_V2 0 +#define ETP_PMAX_V2 255 +#define ETP_WMIN_V2 0 +#define ETP_WMAX_V2 15 + /* * For two finger touches the coordinate of each finger gets reported * separately but with reduced resolution. @@ -102,6 +107,7 @@ struct elantech_data { unsigned char capabilities; bool paritycheck; bool jumpy_cursor; + bool reports_pressure; unsigned char hw_version; unsigned int fw_version; unsigned int single_finger_reports; -- cgit v1.2.2 From 89eec4d71e0a4e47a2f12a08992ada7500ea78a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Mon, 16 May 2011 22:45:54 -0700 Subject: Input: elantech - report multitouch with proper ABS_MT messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multitouch info was reported only via a old protocol used by the proprietary X driver from elantech. Let's report the multitouch info also following the official MT protocol. It's semi-mt because the device only reports the lowest/highest coordinates. This was done following the multi-touch-protocol.txt documentation, and inspired by the bcm5974 and elantech implementations. Testing was light as there is not many applications using this protocol yet, but the X synaptics driver didn't complain and the X multitouch driver behaved correctly. Signed-off-by: Éric Piel Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 5cde11f4ef5e..32648b34b115 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "psmouse.h" @@ -242,6 +243,27 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) input_sync(dev); } +static void elantech_set_slot(struct input_dev *dev, int slot, bool active, + unsigned int x, unsigned int y) +{ + input_mt_slot(dev, slot); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); + if (active) { + input_report_abs(dev, ABS_MT_POSITION_X, x); + input_report_abs(dev, ABS_MT_POSITION_Y, y); + } +} + +/* x1 < x2 and y1 < y2 when two fingers, x = y = 0 when not pressed */ +static void elantech_report_semi_mt_data(struct input_dev *dev, + unsigned int num_fingers, + unsigned int x1, unsigned int y1, + unsigned int x2, unsigned int y2) +{ + elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); + elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); +} + /* * Interpret complete data packets and report absolute mode input events for * hardware version 2. (6 byte packets) @@ -251,7 +273,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; struct input_dev *dev = psmouse->dev; unsigned char *packet = psmouse->packet; - int fingers, x1, y1, x2, y2, width = 0, pres = 0; + unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; /* byte 0: n1 n0 . . . . R L */ fingers = (packet[0] & 0xc0) >> 6; @@ -271,14 +293,16 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) * 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]); + x1 = ((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])); + y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); + + input_report_abs(dev, ABS_X, x1); + input_report_abs(dev, ABS_Y, y1); + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); break; @@ -321,6 +345,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) break; } + elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); @@ -495,6 +520,10 @@ static void elantech_set_input_params(struct psmouse *psmouse) input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, ETP_WMAX_V2, 0, 0); } + __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + input_mt_init_slots(dev, 2); + input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); input_set_abs_params(dev, ABS_HAT0Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); input_set_abs_params(dev, ABS_HAT1X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); -- cgit v1.2.2 From 9cb6cfae4e792d9f92612dd57ee1e3ff218f17a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Piel?= Date: Mon, 16 May 2011 22:45:54 -0700 Subject: Input: elantech - remove support for proprietary X driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently somewhere someone had a proprietary X driver. To get the multitouch info, it uses some hack on the normal API instead of using the multitouch protocol. Now that the multitouch info is transmitted correctly it makes not much sense to keep it. Especially because it's impossible to find this proprietary X driver anywhere, so the number of users must be very low. Signed-off-by: Éric Piel Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/input/mouse') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 32648b34b115..32503565faf9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -330,14 +330,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) */ 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 - */ - input_report_abs(dev, ABS_HAT0X, x1); - input_report_abs(dev, ABS_HAT0Y, y1); - input_report_abs(dev, ABS_HAT1X, x2); - input_report_abs(dev, ABS_HAT1Y, y2); /* Unknown so just report sensible values */ pres = 127; @@ -524,10 +516,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); - input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); - input_set_abs_params(dev, ABS_HAT0Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); - input_set_abs_params(dev, ABS_HAT1X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); - input_set_abs_params(dev, ABS_HAT1Y, ETP_2FT_YMIN, ETP_2FT_YMAX, 0, 0); break; } } -- cgit v1.2.2