All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
@ 2014-08-20 18:18 Ulrik De Bie
  2014-08-20 18:18 ` [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models Ulrik De Bie
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Ulrik De Bie @ 2014-08-20 18:18 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Hans de Goede, David Herrmann, ulrik.debie-os

Hi Dmitry,

I posted these 2 months ago, but haven't seen any comments from you.
Could you please review these ?

Thanks,
Ulrik

Patch 1 adds support for trackpoint on elantech driver for v3 models.
Patch 2 adds a psmouse_reset when the elantech probes fails. Patch 2 depends
on Patch 1.

Changes since v3:
* Patch1: added (correct) error after input_allocate_device failure in elantech_init()
* Patch2: added more explanation to the why

Changes since v2:
* psmouse_reset change is now moved to a separate patch
* comments/white spaces/newlines  cleanup
* Unexpected trackpoint message warning now only printed once
* removed some unnecessary casts
* Deleted etd->trackpoint_present and use instead etd->tp_dev to indicate the
  presence of a trackpoint
* Propagate the error when elantech_init fails

Changes since v1:
* New patch now with reference to 3.14rc1
* Added etd->trackpoint_present to indicate presence of trackpoint (based
  on MSB of etd->capabilities[0])
* trackpoint will only be registered now when MSB of etd->capabilities[0] is
  set; got confirmation that this is the indicator of trackpoint
* Added input_unregister_device/input_free_device in elantech_disconnect()
* Fixed a bug in cleaning up when elantech_init fails
* Rename commit to be more specific (now also applicable to future elantech
  v3 models with trackpoint)
* input device name 'TPPS/2 IBM TrackPoint' changed to
  'Elantech PS/2 TrackPoint', this patch is not ibm/lenovo specific!
* dev2 renamed to tp_dev to indicate that this is the trackpoint device
* etd->phys renamed to etd->tp_phys
* Added Lenovo 530 and Fujitsu H730 to the laptop list because those are now
  also known.
* Added psmouse_reset at the end of elantech_init when it fails
* Added warning when trackpoint packets are received with no trackpoint detected

The patches are also available from:
https://github.com/ulrikdb/linux/commit/53d8424bc2143d34c2be76064892079fe1917a9e
https://github.com/ulrikdb/linux/commit/cf12fcc6cdf51a7aad48d056750478aecd9d7eca



Ulrik De Bie (2):
  elantech: Add support for trackpoint found on some v3 models
  elantech: Call psmouse_reset when elantech probe fails

 drivers/input/mouse/elantech.c | 123 +++++++++++++++++++++++++++++++++++++++--
 drivers/input/mouse/elantech.h |   3 +
 2 files changed, 122 insertions(+), 4 deletions(-)

-- 
2.1.0.rc1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models
  2014-08-20 18:18 [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Ulrik De Bie
@ 2014-08-20 18:18 ` Ulrik De Bie
  2014-08-24 22:14   ` Dmitry Torokhov
  2014-08-20 18:18 ` [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails Ulrik De Bie
  2014-08-21 18:04 ` [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Dmitry Torokhov
  2 siblings, 1 reply; 8+ messages in thread
From: Ulrik De Bie @ 2014-08-20 18:18 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Hans de Goede, David Herrmann, ulrik.debie-os

Some elantech v3 touchpad equipped laptops also have a trackpoint, before
this commit, these give sync errors. With this patch, the trackpoint is
provided as another input device: 'Elantech PS/2 TrackPoint'

The patch will also output messages that do not follow the expected pattern.
In the mean time I've seen 2 unknown packets occasionally:
0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x00
I don't know what those are for, but they can be safely ignored.

Currently all packets that are not known to v3 touchpad and where
packet[3] (the fourth byte) lowest nibble is 6 are now recognized as
PACKET_TRACKPOINT and processed by the new elantech_report_trackpoint.

This has been verified to work on a laptop Lenovo L530 where the
touchpad/trackpoint combined identify themselves as:
psmouse serio1: elantech: assuming hardware version 3 (with firmware version 0x350f02)
psmouse serio1: elantech: Synaptics capabilities query result 0xb9, 0x15, 0x0c.

Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
---
 drivers/input/mouse/elantech.c | 122 +++++++++++++++++++++++++++++++++++++++--
 drivers/input/mouse/elantech.h |   3 +
 2 files changed, 121 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index ee2a04d..5dd620a 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -403,6 +403,71 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 	input_sync(dev);
 }
 
+static void elantech_report_trackpoint(struct psmouse *psmouse,
+				       int packet_type)
+{
+	/*
+	 * byte 0:  0   0 ~sx ~sy   0   M   R   L
+	 * byte 1: sx   0   0   0   0   0   0   0
+	 * byte 2: sy   0   0   0   0   0   0   0
+	 * byte 3:  0   0  sy  sx   0   1   1   0
+	 * byte 4: x7  x6  x5  x4  x3  x2  x1  x0
+	 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+	 *
+	 * x and y are written in two's complement spread
+	 * over 9 bits with sx/sy the relative top bit and
+	 * x7..x0 and y7..y0 the lower bits.
+	 * The sign of y is opposite to what the input driver
+	 * expects for a relative movement
+	 */
+
+	struct elantech_data *etd = psmouse->private;
+	struct input_dev *tp_dev = etd->tp_dev;
+	unsigned char *packet = psmouse->packet;
+	int x, y;
+	u32 t;
+
+	if (!tp_dev) {
+		static bool __section(.data.unlikely) __warned;
+
+		if (!__warned) {
+			__warned = true;
+			psmouse_err(psmouse, "Unexpected trackpoint message\n");
+			if (etd->debug == 1)
+				elantech_packet_dump(psmouse);
+		}
+
+		return;
+	}
+
+	input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
+	input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
+	input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+
+	x = ((packet[1] & 0x80) ? 0U : 0xFFFFFF00U) | packet[4];
+	y = -(int)(((packet[2] & 0x80) ? 0U : 0xFFFFFF00U) | packet[5]);
+
+	input_report_rel(tp_dev, REL_X, x);
+	input_report_rel(tp_dev, REL_Y, y);
+
+	t = (((u32)packet[0] & 0xF8) << 24) | ((u32)packet[1] << 16)
+		| (u32)packet[2] << 8 | (u32)packet[3];
+	switch (t) {
+	case 0x00808036U:
+	case 0x10008026U:
+	case 0x20800016U:
+	case 0x30000006U:
+		break;
+	default:
+		/* Dump unexpected packet sequences if debug=1 (default) */
+		if (etd->debug == 1)
+			elantech_packet_dump(psmouse);
+		break;
+	}
+
+	input_sync(tp_dev);
+}
+
 /*
  * Interpret complete data packets and report absolute mode input events for
  * hardware version 3. (12 byte packets for two fingers)
@@ -715,6 +780,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
 
 		if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
 			return PACKET_V3_TAIL;
+		if ((packet[3] & 0x0f) == 0x06)
+			return PACKET_TRACKPOINT;
 	}
 
 	return PACKET_UNKNOWN;
@@ -798,7 +865,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 		if (packet_type == PACKET_UNKNOWN)
 			return PSMOUSE_BAD_DATA;
 
-		elantech_report_absolute_v3(psmouse, packet_type);
+		if (packet_type == PACKET_TRACKPOINT)
+			elantech_report_trackpoint(psmouse, packet_type);
+		else
+			elantech_report_absolute_v3(psmouse, packet_type);
 		break;
 
 	case 4:
@@ -1018,8 +1088,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
  * Lenovo L430             0x350f02        b9, 15, 0c      2 hw buttons (*)
+ * Lenovo L530             0x350f02        b9, 15, 0c      2 hw buttons (*)
  * Samsung NF210           0x150b00        78, 14, 0a      2 hw buttons
  * Samsung NP770Z5E        0x575f01        10, 15, 0f      clickpad
  * Samsung NP700Z5B        0x361f06        21, 15, 0f      clickpad
@@ -1029,6 +1101,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Samsung RF710           0x450f00        ?               2 hw buttons
  * System76 Pangolin       0x250f01        ?               2 hw buttons
  * (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
  */
 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
 {
@@ -1324,6 +1398,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
  */
 static void elantech_disconnect(struct psmouse *psmouse)
 {
+	struct elantech_data *etd = psmouse->private;
+
+	if (etd->tp_dev)
+		input_unregister_device(etd->tp_dev);
 	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
 			   &elantech_attr_group);
 	kfree(psmouse->private);
@@ -1438,8 +1516,10 @@ static int elantech_set_properties(struct elantech_data *etd)
 int elantech_init(struct psmouse *psmouse)
 {
 	struct elantech_data *etd;
-	int i, error;
+	int i;
+	int error = -EINVAL;
 	unsigned char param[3];
+	struct input_dev *tp_dev;
 
 	psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
 	if (!etd)
@@ -1498,14 +1578,48 @@ int elantech_init(struct psmouse *psmouse)
 		goto init_fail;
 	}
 
+	/* The MSB indicates the presence of the trackpoint */
+	if ((etd->capabilities[0] & 0x80) == 0x80) {
+		tp_dev = input_allocate_device();
+
+		if (!tp_dev) {
+			error = -ENOMEM;
+			goto init_fail_tp_alloc;
+		}
+
+		etd->tp_dev = tp_dev;
+		snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
+			psmouse->ps2dev.serio->phys);
+		tp_dev->phys = etd->tp_phys;
+		tp_dev->name = "Elantech PS/2 TrackPoint";
+		tp_dev->id.bustype = BUS_I8042;
+		tp_dev->id.vendor  = 0x0002;
+		tp_dev->id.product = PSMOUSE_ELANTECH;
+		tp_dev->id.version = 0x0000;
+		tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+		tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+		tp_dev->relbit[BIT_WORD(REL_X)] =
+			BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+		tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
+			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+			BIT_MASK(BTN_RIGHT);
+		error = input_register_device(etd->tp_dev);
+		if (error < 0)
+			goto init_fail_tp_reg;
+	}
+
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
 	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
-
+ init_fail_tp_reg:
+	input_free_device(tp_dev);
+ init_fail_tp_alloc:
+	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
+			   &elantech_attr_group);
  init_fail:
 	kfree(etd);
-	return -1;
+	return error;
 }
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 9e0e2a1..e410336 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -94,6 +94,7 @@
 #define PACKET_V4_HEAD			0x05
 #define PACKET_V4_MOTION		0x06
 #define PACKET_V4_STATUS		0x07
+#define PACKET_TRACKPOINT		0x08
 
 /*
  * track up to 5 fingers for v4 hardware
@@ -114,6 +115,8 @@ struct finger_pos {
 };
 
 struct elantech_data {
+	struct input_dev *tp_dev;	/* Relative device for trackpoint */
+	char	tp_phys[32];
 	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;
-- 
2.1.0.rc1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails
  2014-08-20 18:18 [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Ulrik De Bie
  2014-08-20 18:18 ` [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models Ulrik De Bie
@ 2014-08-20 18:18 ` Ulrik De Bie
  2014-08-23  0:11   ` Dmitry Torokhov
  2014-08-21 18:04 ` [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Dmitry Torokhov
  2 siblings, 1 reply; 8+ messages in thread
From: Ulrik De Bie @ 2014-08-20 18:18 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Hans de Goede, David Herrmann, ulrik.debie-os

elantech_init() calls elantech_set_absolute_mode which sets the driver in
an absolute mode. When after this the elantech_init fails, it is best
to turn the ps/2 mouse emulation mode back on by calling psmouse_reset()
so that it can work as a regular mouse.

Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
---
 drivers/input/mouse/elantech.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 5dd620a..771291c 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1620,6 +1620,7 @@ int elantech_init(struct psmouse *psmouse)
 	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
 			   &elantech_attr_group);
  init_fail:
+	psmouse_reset(psmouse);
 	kfree(etd);
 	return error;
 }
-- 
2.1.0.rc1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
  2014-08-20 18:18 [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Ulrik De Bie
  2014-08-20 18:18 ` [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models Ulrik De Bie
  2014-08-20 18:18 ` [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails Ulrik De Bie
@ 2014-08-21 18:04 ` Dmitry Torokhov
  2 siblings, 0 replies; 8+ messages in thread
From: Dmitry Torokhov @ 2014-08-21 18:04 UTC (permalink / raw)
  To: Ulrik De Bie; +Cc: linux-input, Hans de Goede, David Herrmann

Hi Ulrik,
On Wed, Aug 20, 2014 at 08:18:10PM +0200, Ulrik De Bie wrote:
> Hi Dmitry,
> 
> I posted these 2 months ago, but haven't seen any comments from you.
> Could you please review these ?

I will try to go over them by the end of this week, if you do not hear from me
please do not hesitate to ping me again.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails
  2014-08-20 18:18 ` [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails Ulrik De Bie
@ 2014-08-23  0:11   ` Dmitry Torokhov
  0 siblings, 0 replies; 8+ messages in thread
From: Dmitry Torokhov @ 2014-08-23  0:11 UTC (permalink / raw)
  To: Ulrik De Bie; +Cc: linux-input, Hans de Goede, David Herrmann

On Wed, Aug 20, 2014 at 08:18:12PM +0200, Ulrik De Bie wrote:
> elantech_init() calls elantech_set_absolute_mode which sets the driver in
> an absolute mode. When after this the elantech_init fails, it is best
> to turn the ps/2 mouse emulation mode back on by calling psmouse_reset()
> so that it can work as a regular mouse.
> 
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
> Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>

Applied, thank you.

> ---
>  drivers/input/mouse/elantech.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
> index 5dd620a..771291c 100644
> --- a/drivers/input/mouse/elantech.c
> +++ b/drivers/input/mouse/elantech.c
> @@ -1620,6 +1620,7 @@ int elantech_init(struct psmouse *psmouse)
>  	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
>  			   &elantech_attr_group);
>   init_fail:
> +	psmouse_reset(psmouse);
>  	kfree(etd);
>  	return error;
>  }
> -- 
> 2.1.0.rc1
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models
  2014-08-20 18:18 ` [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models Ulrik De Bie
@ 2014-08-24 22:14   ` Dmitry Torokhov
  2014-08-26 19:30     ` [PATCH 1/1] Input: elantech: Correct the sign of the x/y movement for trackpoint Ulrik De Bie
  0 siblings, 1 reply; 8+ messages in thread
From: Dmitry Torokhov @ 2014-08-24 22:14 UTC (permalink / raw)
  To: Ulrik De Bie; +Cc: linux-input, Hans de Goede, David Herrmann

Hi Ulrik,

On Wed, Aug 20, 2014 at 08:18:11PM +0200, Ulrik De Bie wrote:
> +
> +	t = (((u32)packet[0] & 0xF8) << 24) | ((u32)packet[1] << 16)
> +		| (u32)packet[2] << 8 | (u32)packet[3];

Majority of devices with Elantech will be little-endian devices, so if we use
get_unaligned_le32() we'll save a few ops. Does the version of patch below
still work for you?

Thanks!

-- 
Dmitry


Input: elantech - add support for trackpoint found on some v3 models

From: Ulrik De Bie <ulrik.debie-os@e2big.org>

Some elantech v3 touchpad equipped laptops also have a trackpoint, before
this commit, these give sync errors. With this patch, the trackpoint is
provided as another input device: 'Elantech PS/2 TrackPoint'

The patch will also output messages that do not follow the expected pattern.
In the mean time I've seen 2 unknown packets occasionally:
0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x00
I don't know what those are for, but they can be safely ignored.

Currently all packets that are not known to v3 touchpad and where
packet[3] (the fourth byte) lowest nibble is 6 are now recognized as
PACKET_TRACKPOINT and processed by the new elantech_report_trackpoint.

This has been verified to work on a laptop Lenovo L530 where the
touchpad/trackpoint combined identify themselves as:
psmouse serio1: elantech: assuming hardware version 3 (with firmware version 0x350f02)
psmouse serio1: elantech: Synaptics capabilities query result 0xb9, 0x15, 0x0c.

Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/mouse/elantech.c |  136 +++++++++++++++++++++++++++++++++++++---
 drivers/input/mouse/elantech.h |    3 +
 2 files changed, 130 insertions(+), 9 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index ee2a04d..b4d645a 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -18,6 +18,7 @@
 #include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/libps2.h>
+#include <asm/unaligned.h>
 #include "psmouse.h"
 #include "elantech.h"
 
@@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 	input_sync(dev);
 }
 
+static void elantech_report_trackpoint(struct psmouse *psmouse,
+				       int packet_type)
+{
+	/*
+	 * byte 0:  0   0 ~sx ~sy   0   M   R   L
+	 * byte 1: sx   0   0   0   0   0   0   0
+	 * byte 2: sy   0   0   0   0   0   0   0
+	 * byte 3:  0   0  sy  sx   0   1   1   0
+	 * byte 4: x7  x6  x5  x4  x3  x2  x1  x0
+	 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+	 *
+	 * x and y are written in two's complement spread
+	 * over 9 bits with sx/sy the relative top bit and
+	 * x7..x0 and y7..y0 the lower bits.
+	 * The sign of y is opposite to what the input driver
+	 * expects for a relative movement
+	 */
+
+	struct elantech_data *etd = psmouse->private;
+	struct input_dev *tp_dev = etd->tp_dev;
+	unsigned char *packet = psmouse->packet;
+	int x, y;
+	u32 t;
+
+	if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
+			  !tp_dev,
+			  psmouse_fmt("Unexpected trackpoint message\n"))) {
+		if (etd->debug == 1)
+			elantech_packet_dump(psmouse);
+		return;
+	}
+
+	t = get_unaligned_le32(&packet[0]);
+
+	switch (t & ~7U) {
+	case 0x06000030U:
+	case 0x16008020U:
+	case 0x26800010U:
+	case 0x36808000U:
+		x = packet[4] - (int)(packet[1] << 1);
+		y = (int)(packet[2] << 1) - packet[5];
+
+		input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
+		input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
+		input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+
+		input_report_rel(tp_dev, REL_X, x);
+		input_report_rel(tp_dev, REL_Y, y);
+
+		input_sync(tp_dev);
+
+		break;
+
+	default:
+		/* Dump unexpected packet sequences if debug=1 (default) */
+		if (etd->debug == 1)
+			elantech_packet_dump(psmouse);
+
+		break;
+	}
+}
+
 /*
  * Interpret complete data packets and report absolute mode input events for
  * hardware version 3. (12 byte packets for two fingers)
@@ -715,6 +778,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
 
 		if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
 			return PACKET_V3_TAIL;
+		if ((packet[3] & 0x0f) == 0x06)
+			return PACKET_TRACKPOINT;
 	}
 
 	return PACKET_UNKNOWN;
@@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
 	case 3:
 		packet_type = elantech_packet_check_v3(psmouse);
-		/* ignore debounce */
-		if (packet_type == PACKET_DEBOUNCE)
-			return PSMOUSE_FULL_PACKET;
-
-		if (packet_type == PACKET_UNKNOWN)
+		switch (packet_type) {
+		case PACKET_UNKNOWN:
 			return PSMOUSE_BAD_DATA;
 
-		elantech_report_absolute_v3(psmouse, packet_type);
+		case PACKET_DEBOUNCE:
+			/* ignore debounce */
+			break;
+
+		case PACKET_TRACKPOINT:
+			elantech_report_trackpoint(psmouse, packet_type);
+			break;
+
+		default:
+			elantech_report_absolute_v3(psmouse, packet_type);
+			break;
+		}
+
 		break;
 
 	case 4:
@@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
  * Lenovo L430             0x350f02        b9, 15, 0c      2 hw buttons (*)
+ * Lenovo L530             0x350f02        b9, 15, 0c      2 hw buttons (*)
  * Samsung NF210           0x150b00        78, 14, 0a      2 hw buttons
  * Samsung NP770Z5E        0x575f01        10, 15, 0f      clickpad
  * Samsung NP700Z5B        0x361f06        21, 15, 0f      clickpad
@@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Samsung RF710           0x450f00        ?               2 hw buttons
  * System76 Pangolin       0x250f01        ?               2 hw buttons
  * (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
  */
 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
 {
@@ -1324,6 +1402,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
  */
 static void elantech_disconnect(struct psmouse *psmouse)
 {
+	struct elantech_data *etd = psmouse->private;
+
+	if (etd->tp_dev)
+		input_unregister_device(etd->tp_dev);
 	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
 			   &elantech_attr_group);
 	kfree(psmouse->private);
@@ -1438,8 +1520,10 @@ static int elantech_set_properties(struct elantech_data *etd)
 int elantech_init(struct psmouse *psmouse)
 {
 	struct elantech_data *etd;
-	int i, error;
+	int i;
+	int error = -EINVAL;
 	unsigned char param[3];
+	struct input_dev *tp_dev;
 
 	psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
 	if (!etd)
@@ -1498,14 +1582,48 @@ int elantech_init(struct psmouse *psmouse)
 		goto init_fail;
 	}
 
+	/* The MSB indicates the presence of the trackpoint */
+	if ((etd->capabilities[0] & 0x80) == 0x80) {
+		tp_dev = input_allocate_device();
+
+		if (!tp_dev) {
+			error = -ENOMEM;
+			goto init_fail_tp_alloc;
+		}
+
+		etd->tp_dev = tp_dev;
+		snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
+			psmouse->ps2dev.serio->phys);
+		tp_dev->phys = etd->tp_phys;
+		tp_dev->name = "Elantech PS/2 TrackPoint";
+		tp_dev->id.bustype = BUS_I8042;
+		tp_dev->id.vendor  = 0x0002;
+		tp_dev->id.product = PSMOUSE_ELANTECH;
+		tp_dev->id.version = 0x0000;
+		tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+		tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+		tp_dev->relbit[BIT_WORD(REL_X)] =
+			BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+		tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
+			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+			BIT_MASK(BTN_RIGHT);
+		error = input_register_device(etd->tp_dev);
+		if (error < 0)
+			goto init_fail_tp_reg;
+	}
+
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
 	psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
 	return 0;
-
+ init_fail_tp_reg:
+	input_free_device(tp_dev);
+ init_fail_tp_alloc:
+	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
+			   &elantech_attr_group);
  init_fail:
 	kfree(etd);
-	return -1;
+	return error;
 }
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 9e0e2a1..6f3afec 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -94,6 +94,7 @@
 #define PACKET_V4_HEAD			0x05
 #define PACKET_V4_MOTION		0x06
 #define PACKET_V4_STATUS		0x07
+#define PACKET_TRACKPOINT		0x08
 
 /*
  * track up to 5 fingers for v4 hardware
@@ -114,6 +115,8 @@ struct finger_pos {
 };
 
 struct elantech_data {
+	struct input_dev *tp_dev;	/* Relative device for trackpoint */
+	char tp_phys[32];
 	unsigned char reg_07;
 	unsigned char reg_10;
 	unsigned char reg_11;

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 1/1] Input: elantech: Correct the sign of the x/y movement for trackpoint
  2014-08-24 22:14   ` Dmitry Torokhov
@ 2014-08-26 19:30     ` Ulrik De Bie
  2014-08-26 22:45       ` Dmitry Torokhov
  0 siblings, 1 reply; 8+ messages in thread
From: Ulrik De Bie @ 2014-08-26 19:30 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Hans de Goede, David Herrmann, ulrik.debie-os

Hi Dmitry,

Thank you for your feedback !

The x/y movement calculation was wrong, probably caused by my wrong documentation at the beginning of the elantech_report_trackpoint function.
When applying this patch to your patch, it works.

Thanks !
--
Ulrik

Input: elantech: Correct the sign of the x/y movement for trackpoint

From: Ulrik De Bie <ulrik.debie-os@e2big.org>

The sign bit in the documentation of the trackpoint x/y movement is corrected.
The sign bit in the calculation of the x/y movement for trackpoint is corrected.

Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
---
 drivers/input/mouse/elantech.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index b4d645a..63533e5 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -408,10 +408,10 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
 				       int packet_type)
 {
 	/*
-	 * byte 0:  0   0 ~sx ~sy   0   M   R   L
-	 * byte 1: sx   0   0   0   0   0   0   0
-	 * byte 2: sy   0   0   0   0   0   0   0
-	 * byte 3:  0   0  sy  sx   0   1   1   0
+	 * byte 0:  0   0  sx  sy   0   M   R   L
+	 * byte 1:~sx   0   0   0   0   0   0   0
+	 * byte 2:~sy   0   0   0   0   0   0   0
+	 * byte 3:  0   0 ~sy ~sx   0   1   1   0
 	 * byte 4: x7  x6  x5  x4  x3  x2  x1  x0
 	 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
 	 *
@@ -443,8 +443,8 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
 	case 0x16008020U:
 	case 0x26800010U:
 	case 0x36808000U:
-		x = packet[4] - (int)(packet[1] << 1);
-		y = (int)(packet[2] << 1) - packet[5];
+		x = packet[4] - (int)((packet[1]^0x80) << 1);
+		y = (int)((packet[2]^0x80) << 1) - packet[5];
 
 		input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
 		input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
-- 
2.1.0.rc1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/1] Input: elantech: Correct the sign of the x/y movement for trackpoint
  2014-08-26 19:30     ` [PATCH 1/1] Input: elantech: Correct the sign of the x/y movement for trackpoint Ulrik De Bie
@ 2014-08-26 22:45       ` Dmitry Torokhov
  0 siblings, 0 replies; 8+ messages in thread
From: Dmitry Torokhov @ 2014-08-26 22:45 UTC (permalink / raw)
  To: Ulrik De Bie; +Cc: linux-input, Hans de Goede, David Herrmann

Hi Ulrik,

On Tue, Aug 26, 2014 at 09:30:23PM +0200, Ulrik De Bie wrote:
> Hi Dmitry,
> 
> Thank you for your feedback !
> 
> The x/y movement calculation was wrong, probably caused by my wrong
> documentation at the beginning of the elantech_report_trackpoint
> function.  When applying this patch to your patch, it works.

Thank you for testing and providing both the original patch and the
fixup. I folded everything together and applied, I'll try to get it in
3.17.

Thanks!

-- 
Dmitry

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-08-26 22:45 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-20 18:18 [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Ulrik De Bie
2014-08-20 18:18 ` [PATCH RESEND v4 1/2] elantech: Add support for trackpoint found on some v3 models Ulrik De Bie
2014-08-24 22:14   ` Dmitry Torokhov
2014-08-26 19:30     ` [PATCH 1/1] Input: elantech: Correct the sign of the x/y movement for trackpoint Ulrik De Bie
2014-08-26 22:45       ` Dmitry Torokhov
2014-08-20 18:18 ` [PATCH RESEND v4 2/2] elantech: Call psmouse_reset when elantech probe fails Ulrik De Bie
2014-08-23  0:11   ` Dmitry Torokhov
2014-08-21 18:04 ` [PATCH RESEND v4 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530 Dmitry Torokhov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.