[PATCH 1/5] input/alps: Add touchstick support for SS5 hardware
Subsystems:
alps ps/2 touchpad driver , input (keyboard, mouse, joystick, touchscreen) drivers , the rest
STALE3662d
REVIEWED: 2 (1M)
2 review trailers.
8 messages,
3 authors,
2016-10-11 · open the first message on its own page
Add touchstick support for the so-called SS5 hardware, which uses a
variant of the SS4 protocol.
Reviewed-by: Pali Rohár <redacted>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
drivers/input/mouse/alps.c | 64 ++++++++++++++++++++++++++++++++++++++--------
drivers/input/mouse/alps.h | 2 ++
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 936f07a..b8454af 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c @@ -1156,15 +1156,27 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
{
unsigned char pkt_id = SS4_PACKET_ID_IDLE ;
- if ( byte [ 0 ] == 0x18 && byte [ 1 ] == 0x10 && byte [ 2 ] == 0x00 &&
- ( byte [ 3 ] & 0x88 ) == 0x08 && byte [ 4 ] == 0x10 && byte [ 5 ] == 0x00 ) {
- pkt_id = SS4_PACKET_ID_IDLE ;
- } else if ( ! ( byte [ 3 ] & 0x10 )) {
- pkt_id = SS4_PACKET_ID_ONE ;
- } else if ( ! ( byte [ 3 ] & 0x20 )) {
+ switch ( byte [ 3 ] & 0x30 ) {
+ case 0x00 :
+ if ( byte [ 0 ] == 0x18 && byte [ 1 ] == 0x10 && byte [ 2 ] == 0x00 &&
+ ( byte [ 3 ] & 0x88 ) == 0x08 && byte [ 4 ] == 0x10 && byte [ 5 ] == 0x00 ) {
+ pkt_id = SS4_PACKET_ID_IDLE ;
+ } else {
+ pkt_id = SS4_PACKET_ID_ONE ;
+ }
+ break ;
+ case 0x10 :
+ /* two-finger finger positions */
pkt_id = SS4_PACKET_ID_TWO ;
- } else {
+ break ;
+ case 0x20 :
+ /* stick pointer */
+ pkt_id = SS4_PACKET_ID_STICK ;
+ break ;
+ case 0x30 :
+ /* third and fourth finger positions */
pkt_id = SS4_PACKET_ID_MULTI ;
+ break ;
}
return pkt_id ; @@ -1246,16 +1258,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
}
break ;
+ case SS4_PACKET_ID_STICK :
+ if ( ! ( priv -> flags & ALPS_DUALPOINT )) {
+ psmouse_warn ( psmouse ,
+ "Rejected trackstick packet from non DualPoint device" );
+ } else {
+ int x = ( s8 )((( p [ 0 ] & 1 ) << 7 ) | ( p [ 1 ] & 0x7f ));
+ int y = ( s8 )((( p [ 3 ] & 1 ) << 7 ) | ( p [ 2 ] & 0x7f ));
+
+ input_report_rel ( priv -> dev2 , REL_X , x );
+ input_report_rel ( priv -> dev2 , REL_Y , - y );
+ }
+ break ;
+
case SS4_PACKET_ID_IDLE :
default :
memset ( f , 0 , sizeof ( struct alps_fields ));
break ;
}
- f -> left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
- if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
- f -> right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
- f -> middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ /* handle buttons */
+ if ( pkt_id == SS4_PACKET_ID_STICK ) {
+ f -> ts_left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
+ if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
+ f -> ts_right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
+ f -> ts_middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ }
+ } else {
+ f -> left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
+ if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
+ f -> right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
+ f -> middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ }
}
return 0 ; @@ -1266,6 +1300,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
struct alps_data * priv = psmouse -> private ;
unsigned char * packet = psmouse -> packet ;
struct input_dev * dev = psmouse -> dev ;
+ struct input_dev * dev2 = priv -> dev2 ;
struct alps_fields * f = & priv -> f ;
memset ( f , 0 , sizeof ( struct alps_fields )); @@ -1311,6 +1346,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
input_report_abs ( dev , ABS_PRESSURE , f -> pressure );
input_sync ( dev );
+
+ if ( priv -> flags & ALPS_DUALPOINT ) {
+ input_report_key ( dev2 , BTN_LEFT , f -> ts_left );
+ input_report_key ( dev2 , BTN_RIGHT , f -> ts_right );
+ input_report_key ( dev2 , BTN_MIDDLE , f -> ts_middle );
+ input_sync ( dev2 );
+ }
}
static bool alps_is_valid_package_ss4_v2 ( struct psmouse * psmouse ) diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index d37f814..b9417e2 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h @@ -37,12 +37,14 @@
* or there ' s button activities .
* SS4_PACKET_ID_TWO : There ' s two or more fingers on touchpad
* SS4_PACKET_ID_MULTI : There ' s three or more fingers on touchpad
+ * SS4_PACKET_ID_STICK : A stick pointer packet
*/
enum SS4_PACKET_ID {
SS4_PACKET_ID_IDLE = 0 ,
SS4_PACKET_ID_ONE ,
SS4_PACKET_ID_TWO ,
SS4_PACKET_ID_MULTI ,
+ SS4_PACKET_ID_STICK ,
};
#define SS4_COUNT_PER_ELECTRODE 256 --
2.9.3
The SS5 hardware can report this.
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
drivers/input/mouse/alps.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 7874f4f..25d2cad 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c @@ -103,6 +103,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
6 - byte ALPS packet */
#define ALPS_STICK_BITS 0x100 /* separate stick button bits */
#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
+ #define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */
static const struct alps_model_info alps_model_data [] = {
{ { 0x32 , 0x02 , 0x14 }, 0x00 , { ALPS_PROTO_V2 , 0xf8 , 0xf8 , ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */ @@ -1270,9 +1271,11 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
} else {
int x = ( s8 )((( p [ 0 ] & 1 ) << 7 ) | ( p [ 1 ] & 0x7f ));
int y = ( s8 )((( p [ 3 ] & 1 ) << 7 ) | ( p [ 2 ] & 0x7f ));
+ int pressure = ( s8 )( p [ 4 ] & 0x7f );
input_report_rel ( priv -> dev2 , REL_X , x );
input_report_rel ( priv -> dev2 , REL_Y , - y );
+ input_report_abs ( priv -> dev2 , ABS_PRESSURE , pressure );
}
break ;
@@ -2996,6 +2999,10 @@ int alps_init(struct psmouse *psmouse)
input_set_capability ( dev2 , EV_REL , REL_X );
input_set_capability ( dev2 , EV_REL , REL_Y );
+ if ( priv -> flags & ALPS_DUALPOINT_WITH_PRESSURE ) {
+ input_set_capability ( dev2 , EV_ABS , ABS_PRESSURE );
+ input_set_abs_params ( dev2 , ABS_PRESSURE , 0 , 127 , 0 , 0 );
+ }
input_set_capability ( dev2 , EV_KEY , BTN_LEFT );
input_set_capability ( dev2 , EV_KEY , BTN_RIGHT );
input_set_capability ( dev2 , EV_KEY , BTN_MIDDLE ); --
2.9.3
While a button is held SS5 hardware will give us single-finger packets
with x, y, and pressure equal to zero. This causes annoying jumps in
pointer position if a touch is released while the button is held. Handle
this by claiming zero contacts to ensure that no position events are
provided to the user.
Reviewed-by: Pali Rohár <redacted>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
drivers/input/mouse/alps.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b8454af..7874f4f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c @@ -1197,7 +1197,12 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
f -> mt [ 0 ]. x = SS4_1F_X_V2 ( p );
f -> mt [ 0 ]. y = SS4_1F_Y_V2 ( p );
f -> pressure = (( SS4_1F_Z_V2 ( p )) * 2 ) & 0x7f ;
- f -> fingers = 1 ;
+ /*
+ * When a button is held the device will give us events with x , y , and
+ * pressure of 0. This causes annoying jumps if a touch is released while
+ * the button is held . Handle this by claiming zero contacts .
+ */
+ f -> fingers = f -> pressure > 0 ? 1 : 0 ;
f -> first_mp = 0 ;
f -> is_mp = 0 ;
break ; --
2.9.3
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
Documentation/input/alps.txt | 57 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index 1fec113..8d1341c 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt @@ -319,3 +319,60 @@ For touchpad packet, the format is:
otherwise byte 0 bit 4 must be set and byte 0/4/5 are
in NEW fmt
F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ...
+
+
+ ALPS Absolute Mode - Protocol Version 8
+ ---------------------------------------
+
+ Spoken by SS4 (73 03 14) and SS5 (73 03 28) hardware.
+
+ The packet type is given by the APD field, bits 4-5 of byte 3.
+
+ Touchpad packet (APD = 0x2):
+
+ b7 b6 b5 b4 b3 b2 b1 b0
+ byte 0: SWM SWR SWL 1 1 0 0 X7
+ byte 1: 0 X6 X5 X4 X3 X2 X1 X0
+ byte 2: 0 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ byte 3: 0 T&P 1 0 1 0 0 Y7
+ byte 4: 0 Z6 Z5 Z4 Z3 Z2 Z1 Z0
+ byte 5: 0 0 0 0 0 0 0 0
+
+ SWM, SWR, SWL: Middle, Right, and Left button states
+
+ Touchpad 1 Finger packet (APD = 0x0):
+
+ b7 b6 b5 b4 b3 b2 b1 b0
+ byte 0: SWM SWR SWL 1 1 X2 X1 X0
+ byte 1: X9 X8 X7 1 X6 X5 X4 X3
+ byte 2: 0 X11 X10 LFB Y3 Y2 Y1 Y0
+ byte 3: Y5 Y4 0 0 1 TAPF2 TAPF1 TAPF0
+ byte 4: Zv7 Y11 Y10 1 Y9 Y8 Y7 Y6
+ byte 5: Zv6 Zv5 Zv4 0 Zv3 Zv2 Zv1 Zv0
+
+ TAPF: ???
+ LFB: ???
+
+ Touchpad 2 Finger packet (APD = 0x1):
+
+ b7 b6 b5 b4 b3 b2 b1 b0
+ byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4
+ byte 1: AX11 AX10 AX9 AX8 AX7 AZ1 AY4 AZ0
+ byte 2: AY11 AY10 AY9 CONT AY8 AY7 AY6 AY5
+ byte 3: 0 0 0 1 1 BX6 BX5 BX4
+ byte 4: BX11 BX10 BX9 BX8 BX7 BZ1 BY4 BZ0
+ byte 5: BY11 BY10 BY9 0 BY8 BY7 BY5 BY5
+
+ CONT: A 3-or-4 Finger packet is to follow
+
+ Touchpad 3-or-4 Finger packet (APD = 0x3):
+
+ b7 b6 b5 b4 b3 b2 b1 b0
+ byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4
+ byte 1: AX11 AX10 AX9 AX8 AX7 AZ1 AY4 AZ0
+ byte 2: AY11 AY10 AY9 OVF AY8 AY7 AY6 AY5
+ byte 3: 0 0 1 1 1 BX6 BX5 BX4
+ byte 4: BX11 BX10 BX9 BX8 BX7 BZ1 BY4 BZ0
+ byte 5: BY11 BY10 BY9 0 BY8 BY7 BY5 BY5
+
+ OVF: 5th finger detected--
2.9.3
Here we introduce logic in alps_identify to set the ALPS_DUALPOINT flag
for touchpad hardware responding to E7 report with 73 03 28, as is found
in the Dell Latitude E7470.
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
drivers/input/mouse/alps.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 25d2cad..308f289 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c @@ -2745,6 +2745,9 @@ static int alps_set_protocol(struct psmouse *psmouse,
if ( alps_set_defaults_ss4_v2 ( psmouse , priv ))
return - EIO ;
+ if ( priv -> fw_ver [ 1 ] == 0x1 )
+ priv -> flags |= ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE ;
+
break ;
}
@@ -2817,6 +2820,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
} else if ( e7 [ 0 ] == 0x73 && e7 [ 1 ] == 0x03 &&
e7 [ 2 ] == 0x14 && ec [ 1 ] == 0x02 ) {
protocol = & alps_v8_protocol_data ;
+ } else if ( e7 [ 0 ] == 0x73 && e7 [ 1 ] == 0x03 &&
+ e7 [ 2 ] == 0x28 && ec [ 1 ] == 0x01 ) {
+ protocol = & alps_v8_protocol_data ;
} else {
psmouse_dbg ( psmouse ,
"Likely not an ALPS touchpad: E7=%3ph, EC=%3ph \n " , e7 , ec ); --
2.9.3
On Mon, Oct 03, 2016 at 08:16:26AM -0400, Ben Gamari wrote: Add touchstick support for the so-called SS5 hardware, which uses a
variant of the SS4 protocol.
Reviewed-by: Pali Rohár <redacted>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
Applied the lot, thanks.
quoted hunk drivers/input/mouse/alps.c | 64 ++++++++++++++++++++++++++++++++++++++--------
drivers/input/mouse/alps.h | 2 ++
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 936f07a..b8454af 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c @@ -1156,15 +1156,27 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
{
unsigned char pkt_id = SS4_PACKET_ID_IDLE ;
- if ( byte [ 0 ] == 0x18 && byte [ 1 ] == 0x10 && byte [ 2 ] == 0x00 &&
- ( byte [ 3 ] & 0x88 ) == 0x08 && byte [ 4 ] == 0x10 && byte [ 5 ] == 0x00 ) {
- pkt_id = SS4_PACKET_ID_IDLE ;
- } else if ( ! ( byte [ 3 ] & 0x10 )) {
- pkt_id = SS4_PACKET_ID_ONE ;
- } else if ( ! ( byte [ 3 ] & 0x20 )) {
+ switch ( byte [ 3 ] & 0x30 ) {
+ case 0x00 :
+ if ( byte [ 0 ] == 0x18 && byte [ 1 ] == 0x10 && byte [ 2 ] == 0x00 &&
+ ( byte [ 3 ] & 0x88 ) == 0x08 && byte [ 4 ] == 0x10 && byte [ 5 ] == 0x00 ) {
+ pkt_id = SS4_PACKET_ID_IDLE ;
+ } else {
+ pkt_id = SS4_PACKET_ID_ONE ;
+ }
+ break ;
+ case 0x10 :
+ /* two-finger finger positions */
pkt_id = SS4_PACKET_ID_TWO ;
- } else {
+ break ;
+ case 0x20 :
+ /* stick pointer */
+ pkt_id = SS4_PACKET_ID_STICK ;
+ break ;
+ case 0x30 :
+ /* third and fourth finger positions */
pkt_id = SS4_PACKET_ID_MULTI ;
+ break ;
}
return pkt_id ; @@ -1246,16 +1258,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
}
break ;
+ case SS4_PACKET_ID_STICK :
+ if ( ! ( priv -> flags & ALPS_DUALPOINT )) {
+ psmouse_warn ( psmouse ,
+ "Rejected trackstick packet from non DualPoint device" );
+ } else {
+ int x = ( s8 )((( p [ 0 ] & 1 ) << 7 ) | ( p [ 1 ] & 0x7f ));
+ int y = ( s8 )((( p [ 3 ] & 1 ) << 7 ) | ( p [ 2 ] & 0x7f ));
+
+ input_report_rel ( priv -> dev2 , REL_X , x );
+ input_report_rel ( priv -> dev2 , REL_Y , - y );
+ }
+ break ;
+
case SS4_PACKET_ID_IDLE :
default :
memset ( f , 0 , sizeof ( struct alps_fields ));
break ;
}
- f -> left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
- if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
- f -> right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
- f -> middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ /* handle buttons */
+ if ( pkt_id == SS4_PACKET_ID_STICK ) {
+ f -> ts_left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
+ if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
+ f -> ts_right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
+ f -> ts_middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ }
+ } else {
+ f -> left = !! ( SS4_BTN_V2 ( p ) & 0x01 );
+ if ( ! ( priv -> flags & ALPS_BUTTONPAD )) {
+ f -> right = !! ( SS4_BTN_V2 ( p ) & 0x02 );
+ f -> middle = !! ( SS4_BTN_V2 ( p ) & 0x04 );
+ }
}
return 0 ; @@ -1266,6 +1300,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
struct alps_data * priv = psmouse -> private ;
unsigned char * packet = psmouse -> packet ;
struct input_dev * dev = psmouse -> dev ;
+ struct input_dev * dev2 = priv -> dev2 ;
struct alps_fields * f = & priv -> f ;
memset ( f , 0 , sizeof ( struct alps_fields )); @@ -1311,6 +1346,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
input_report_abs ( dev , ABS_PRESSURE , f -> pressure );
input_sync ( dev );
+
+ if ( priv -> flags & ALPS_DUALPOINT ) {
+ input_report_key ( dev2 , BTN_LEFT , f -> ts_left );
+ input_report_key ( dev2 , BTN_RIGHT , f -> ts_right );
+ input_report_key ( dev2 , BTN_MIDDLE , f -> ts_middle );
+ input_sync ( dev2 );
+ }
}
static bool alps_is_valid_package_ss4_v2 ( struct psmouse * psmouse ) diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index d37f814..b9417e2 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h @@ -37,12 +37,14 @@
* or there ' s button activities .
* SS4_PACKET_ID_TWO : There ' s two or more fingers on touchpad
* SS4_PACKET_ID_MULTI : There ' s three or more fingers on touchpad
+ * SS4_PACKET_ID_STICK : A stick pointer packet
*/
enum SS4_PACKET_ID {
SS4_PACKET_ID_IDLE = 0 ,
SS4_PACKET_ID_ONE ,
SS4_PACKET_ID_TWO ,
SS4_PACKET_ID_MULTI ,
+ SS4_PACKET_ID_STICK ,
};
#define SS4_COUNT_PER_ELECTRODE 256 --
2.9.3
--
Dmitry
On Tue, 4 Oct 2016, Dmitry Torokhov wrote:
quoted Add touchstick support for the so-called SS5 hardware, which uses a
variant of the SS4 protocol.
Reviewed-by: Pali Rohár <redacted>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
Applied the lot, thanks.
Thanks. I see this wasn't in the d4e65476b merge; what are your plans with
this, please? Still for this merge window?
Thanks,
--
Jiri Kosina
SUSE Labs
On Tue, Oct 11, 2016 at 03:46:42PM +0200, Jiri Kosina wrote: On Tue, 4 Oct 2016, Dmitry Torokhov wrote:
quoted quoted Add touchstick support for the so-called SS5 hardware, which uses a
variant of the SS4 protocol.
Reviewed-by: Pali Rohár <redacted>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <redacted>
---
Applied the lot, thanks.
Thanks. I see this wasn't in the d4e65476b merge; what are your plans with
this, please? Still for this merge window?
Yeah, I'll include in my 2nd pull later this week.
Thanks.
--
Dmitry