Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): 20140613205547.GA5244@lantern
v3 cover Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
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 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/f8570efe466fb835b76f11fdbaf277fea9999a42
https://github.com/ulrikdb/linux/commit/69ab8ef8cf96237a90b393607727d080930d4469
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 | 120 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/elantech.h | 3 ++ 2 files changed, 119 insertions(+), 4 deletions(-)
Signature · 1 line
2.0.0
PATCH v3 1/2 elantech: Add support for trackpoint found on some v3 models
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 , 0x000x00 , 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.
--- drivers/input/mouse/elantech.c | 119 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/elantech.h | 3 ++ 2 files changed, 118 insertions(+), 4 deletions(-)
drivers/input/mouse/elantech.c +115 -4
@@ -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,45 @@ 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) + 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; }
drivers/input/mouse/elantech.h +3 -0
@@ -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;
Signature · 1 line
2.0.0
Re: [PATCH v3 1/2] elantech: Add support for trackpoint found on some v3 models
Hi
Quoted 167 lines · Ulrik De Bie
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,0x000x00,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_TRACKPOINTand processed by the newelantech_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 version0x350f02) psmouse serio1: elantech: Synaptics capabilities query result0xb9,0x15,0x0c.Reviewed-by Hans de Goede <[email protected]>Signed-off-by Ulrik De Bie <[email protected]>--- drivers/input/mouse/elantech.c | 119 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/elantech.h | 3 ++ 2 files changed, 118 insertions(+), 4 deletions(-)drivers/input/mouse/elantech.c +82
-2@@ -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)
drivers/input/mouse/elantech.c int elantech_init(struct psmouse *psmouse) · line 1585
Quoted 8 lines
drivers/input/mouse/elantech.c +5
-0@@ -1498,14 +1578,45 @@ 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) + goto init_fail_tp_alloc;
This must be:
if (!tp_dev) {
error = -ENOMEM;
goto init_fail_tp_alloc;
}Otherwise, error is 0 due to the previous call to sysfs_create_group() and this function will return 0 erroneously.
Apart from that, patch looks good to me:
Thanks
David
Quoted 63 lines
drivers/input/mouse/elantech.c +28
-2+ + 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; }drivers/input/mouse/elantech.h +3
-1@@ -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.0.0
v4 cover Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
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(-)
Signature · 1 line
2.0.0
PATCH v4 1/2 elantech: Add support for trackpoint found on some v3 models
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 , 0x000x00 , 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.
--- drivers/input/mouse/elantech.c | 122 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/elantech.h | 3 + 2 files changed, 121 insertions(+), 4 deletions(-)
drivers/input/mouse/elantech.c +118 -4
@@ -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; }
drivers/input/mouse/elantech.h +3 -0
@@ -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;
Signature · 1 line
2.0.0
PATCH v4 2/2 elantech: Call psmouse_reset when elantech probe fails
In reply to Ulrik De Bieelantech_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.
--- drivers/input/mouse/elantech.c | 1 + 1 file changed, 1 insertion(+)
drivers/input/mouse/elantech.c +1 -0
@@ -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; }
Signature · 1 line
2.0.0
Re: [PATCH v4 2/2] elantech: Call psmouse_reset when elantech probe fails
Hi,
Quoted 6 lines · Ulrik De Bie
elantech_init()callselantech_set_absolute_modewhich sets the driver in an absolute mode. When after this theelantech_initfails, it is best to turn the ps/2 mouse emulation mode back on by callingpsmouse_reset()so that it can work as a regular mouse.Signed-off-by Ulrik De Bie <[email protected]>
Looks good, this patch is:
Regards,
Hans
Quoted 17 lines
--- drivers/input/mouse/elantech.c | 1 + 1 file changed, 1 insertion(+)drivers/input/mouse/elantech.c +1
-0@@ -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; }
Hi Dmitry,
could you please give feedback on this set of 2 patches ?
They have been updated and reviewed and this patch set v4 is 1 month old now.
I have some other patches waiting to make Fujitsu H730 work too but it will rely for part of the functionality on this patch.
Thanks for your time and feedback !
Ulrik
Quoted 66 lines · Ulrik De Bie
Date: Mon, 16 Jun 2014 23:53:07 +0200
From: Ulrik De Bie <[email protected]>
To: Dmitry Torokhov <[email protected]>
Cc: [email protected], Hans de Goede <[email protected]>, David
Herrmann <[email protected]>, [email protected]
Subject: [PATCH v4 0/2] Input: Support in the elantech driver of the
trackpoint present on for instance Lenovo L530
X-Mailer: git-send-email 2.0.0
X-Mailing-List: [email protected]Patch 1 adds support for trackpoint on elantech driver for v3 models. Patch 2 adds a
psmouse_resetwhen the elantech probes fails. Patch 2 depends on Patch 1.Changes since v3:
* Patch1: added (correct) error afterinput_allocate_devicefailure inelantech_init()
* Patch2: added more explanation to the whyChanges since v2:
*psmouse_resetchange is now moved to a separate patch
* comments/white spaces/newlines cleanup
* Unexpected trackpoint message warning now only printed once
* removed some unnecessary casts
* Deletedetd->trackpoint_presentand use insteadetd->tp_devto indicate the presence of a trackpoint
* Propagate the error whenelantech_initfailsChanges since v1:
* New patch now with reference to 3.14rc1
* Addedetd->trackpoint_presentto 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 inelantech_disconnect()
* Fixed a bug in cleaning up whenelantech_initfails
* 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 totp_devto indicate that this is the trackpoint device
*etd->physrenamed toetd->tp_phys
* Added Lenovo 530 and Fujitsu H730 to the laptop list because those are now also known.
* Addedpsmouse_resetat the end ofelantech_initwhen it fails
* Added warning when trackpoint packets are received with no trackpoint detectedThe patches are also available from:
https://github.com/ulrikdb/linux/commit/53d8424bc2143d34c2be76064892079fe1917a9e
https://github.com/ulrikdb/linux/commit/cf12fcc6cdf51a7aad48d056750478aecd9d7ecaUlrik De Bie (2):
elantech: Add support for trackpoint found on some v3 models
elantech: Callpsmouse_resetwhen elantech probe failsdrivers/input/mouse/elantech.c | 123 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/elantech.h | 3 + 2 files changed, 122 insertions(+), 4 deletions(-)Signature · 6 lines
2.0.0 -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 2/2 elantech: Call psmouse_reset when elantech probe fails
In reply to Ulrik De Bie--- drivers/input/mouse/elantech.c | 1 + 1 file changed, 1 insertion(+)
drivers/input/mouse/elantech.c +1 -0
@@ -1617,6 +1617,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; }
Signature · 1 line
2.0.0
Re: [PATCH v3 2/2] elantech: Call psmouse_reset when elantech probe fails
Hi
Quoted 1 line · Ulrik De Bie
Signed-off-by Ulrik De Bie <[email protected]>
This patch lacks _any_ explanation why this is done. Please always write commit-messages! It is totally unclear from the patch description why the device is reset.
Thanks
David
Quoted 19 lines
--- drivers/input/mouse/elantech.c | 1 + 1 file changed, 1 insertion(+)drivers/input/mouse/elantech.c +1
-1@@ -1617,6 +1617,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.0.0