@@ -103,6 +103,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
103103 6-byte ALPS packet */
104104#define ALPS_STICK_BITS 0x100 /* separate stick button bits */
105105#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
106+ #define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */
106107
107108static const struct alps_model_info alps_model_data [] = {
108109 { { 0x32 , 0x02 , 0x14 }, 0x00 , { ALPS_PROTO_V2 , 0xf8 , 0xf8 , ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
@@ -1156,15 +1157,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
11561157{
11571158 unsigned char pkt_id = SS4_PACKET_ID_IDLE ;
11581159
1159- if (byte [0 ] == 0x18 && byte [1 ] == 0x10 && byte [2 ] == 0x00 &&
1160- (byte [3 ] & 0x88 ) == 0x08 && byte [4 ] == 0x10 && byte [5 ] == 0x00 ) {
1161- pkt_id = SS4_PACKET_ID_IDLE ;
1162- } else if (!(byte [3 ] & 0x10 )) {
1163- pkt_id = SS4_PACKET_ID_ONE ;
1164- } else if (!(byte [3 ] & 0x20 )) {
1160+ switch (byte [3 ] & 0x30 ) {
1161+ case 0x00 :
1162+ if (byte [0 ] == 0x18 && byte [1 ] == 0x10 && byte [2 ] == 0x00 &&
1163+ (byte [3 ] & 0x88 ) == 0x08 && byte [4 ] == 0x10 &&
1164+ byte [5 ] == 0x00 ) {
1165+ pkt_id = SS4_PACKET_ID_IDLE ;
1166+ } else {
1167+ pkt_id = SS4_PACKET_ID_ONE ;
1168+ }
1169+ break ;
1170+ case 0x10 :
1171+ /* two-finger finger positions */
11651172 pkt_id = SS4_PACKET_ID_TWO ;
1166- } else {
1173+ break ;
1174+ case 0x20 :
1175+ /* stick pointer */
1176+ pkt_id = SS4_PACKET_ID_STICK ;
1177+ break ;
1178+ case 0x30 :
1179+ /* third and fourth finger positions */
11671180 pkt_id = SS4_PACKET_ID_MULTI ;
1181+ break ;
11681182 }
11691183
11701184 return pkt_id ;
@@ -1185,7 +1199,13 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
11851199 f -> mt [0 ].x = SS4_1F_X_V2 (p );
11861200 f -> mt [0 ].y = SS4_1F_Y_V2 (p );
11871201 f -> pressure = ((SS4_1F_Z_V2 (p )) * 2 ) & 0x7f ;
1188- f -> fingers = 1 ;
1202+ /*
1203+ * When a button is held the device will give us events
1204+ * with x, y, and pressure of 0. This causes annoying jumps
1205+ * if a touch is released while the button is held.
1206+ * Handle this by claiming zero contacts.
1207+ */
1208+ f -> fingers = f -> pressure > 0 ? 1 : 0 ;
11891209 f -> first_mp = 0 ;
11901210 f -> is_mp = 0 ;
11911211 break ;
@@ -1246,16 +1266,40 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
12461266 }
12471267 break ;
12481268
1269+ case SS4_PACKET_ID_STICK :
1270+ if (!(priv -> flags & ALPS_DUALPOINT )) {
1271+ psmouse_warn (psmouse ,
1272+ "Rejected trackstick packet from non DualPoint device" );
1273+ } else {
1274+ int x = (s8 )(((p [0 ] & 1 ) << 7 ) | (p [1 ] & 0x7f ));
1275+ int y = (s8 )(((p [3 ] & 1 ) << 7 ) | (p [2 ] & 0x7f ));
1276+ int pressure = (s8 )(p [4 ] & 0x7f );
1277+
1278+ input_report_rel (priv -> dev2 , REL_X , x );
1279+ input_report_rel (priv -> dev2 , REL_Y , - y );
1280+ input_report_abs (priv -> dev2 , ABS_PRESSURE , pressure );
1281+ }
1282+ break ;
1283+
12491284 case SS4_PACKET_ID_IDLE :
12501285 default :
12511286 memset (f , 0 , sizeof (struct alps_fields ));
12521287 break ;
12531288 }
12541289
1255- f -> left = !!(SS4_BTN_V2 (p ) & 0x01 );
1256- if (!(priv -> flags & ALPS_BUTTONPAD )) {
1257- f -> right = !!(SS4_BTN_V2 (p ) & 0x02 );
1258- f -> middle = !!(SS4_BTN_V2 (p ) & 0x04 );
1290+ /* handle buttons */
1291+ if (pkt_id == SS4_PACKET_ID_STICK ) {
1292+ f -> ts_left = !!(SS4_BTN_V2 (p ) & 0x01 );
1293+ if (!(priv -> flags & ALPS_BUTTONPAD )) {
1294+ f -> ts_right = !!(SS4_BTN_V2 (p ) & 0x02 );
1295+ f -> ts_middle = !!(SS4_BTN_V2 (p ) & 0x04 );
1296+ }
1297+ } else {
1298+ f -> left = !!(SS4_BTN_V2 (p ) & 0x01 );
1299+ if (!(priv -> flags & ALPS_BUTTONPAD )) {
1300+ f -> right = !!(SS4_BTN_V2 (p ) & 0x02 );
1301+ f -> middle = !!(SS4_BTN_V2 (p ) & 0x04 );
1302+ }
12591303 }
12601304
12611305 return 0 ;
@@ -1266,6 +1310,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
12661310 struct alps_data * priv = psmouse -> private ;
12671311 unsigned char * packet = psmouse -> packet ;
12681312 struct input_dev * dev = psmouse -> dev ;
1313+ struct input_dev * dev2 = priv -> dev2 ;
12691314 struct alps_fields * f = & priv -> f ;
12701315
12711316 memset (f , 0 , sizeof (struct alps_fields ));
@@ -1311,6 +1356,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
13111356
13121357 input_report_abs (dev , ABS_PRESSURE , f -> pressure );
13131358 input_sync (dev );
1359+
1360+ if (priv -> flags & ALPS_DUALPOINT ) {
1361+ input_report_key (dev2 , BTN_LEFT , f -> ts_left );
1362+ input_report_key (dev2 , BTN_RIGHT , f -> ts_right );
1363+ input_report_key (dev2 , BTN_MIDDLE , f -> ts_middle );
1364+ input_sync (dev2 );
1365+ }
13141366}
13151367
13161368static bool alps_is_valid_package_ss4_v2 (struct psmouse * psmouse )
@@ -2695,6 +2747,10 @@ static int alps_set_protocol(struct psmouse *psmouse,
26952747 if (alps_set_defaults_ss4_v2 (psmouse , priv ))
26962748 return - EIO ;
26972749
2750+ if (priv -> fw_ver [1 ] == 0x1 )
2751+ priv -> flags |= ALPS_DUALPOINT |
2752+ ALPS_DUALPOINT_WITH_PRESSURE ;
2753+
26982754 break ;
26992755 }
27002756
@@ -2767,6 +2823,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
27672823 } else if (e7 [0 ] == 0x73 && e7 [1 ] == 0x03 &&
27682824 e7 [2 ] == 0x14 && ec [1 ] == 0x02 ) {
27692825 protocol = & alps_v8_protocol_data ;
2826+ } else if (e7 [0 ] == 0x73 && e7 [1 ] == 0x03 &&
2827+ e7 [2 ] == 0x28 && ec [1 ] == 0x01 ) {
2828+ protocol = & alps_v8_protocol_data ;
27702829 } else {
27712830 psmouse_dbg (psmouse ,
27722831 "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n" , e7 , ec );
@@ -2949,6 +3008,10 @@ int alps_init(struct psmouse *psmouse)
29493008
29503009 input_set_capability (dev2 , EV_REL , REL_X );
29513010 input_set_capability (dev2 , EV_REL , REL_Y );
3011+ if (priv -> flags & ALPS_DUALPOINT_WITH_PRESSURE ) {
3012+ input_set_capability (dev2 , EV_ABS , ABS_PRESSURE );
3013+ input_set_abs_params (dev2 , ABS_PRESSURE , 0 , 127 , 0 , 0 );
3014+ }
29523015 input_set_capability (dev2 , EV_KEY , BTN_LEFT );
29533016 input_set_capability (dev2 , EV_KEY , BTN_RIGHT );
29543017 input_set_capability (dev2 , EV_KEY , BTN_MIDDLE );
0 commit comments