Commit 4777ac22 authored by Ben Gamari's avatar Ben Gamari Committed by Dmitry Torokhov

Input: ALPS - add touchstick support for SS5 hardware

Add touchstick support for the so-called SS5 hardware, which uses a
variant of the SS4 protocol.
Reviewed-by: default avatarPali Rohár <pali.rohar@gmail.com>
Tested-by: default avatarMichal Hocko <mhocko@suse.com>
Signed-off-by: default avatarBen Gamari <ben@smart-cactus.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent f9a703a5
...@@ -1156,15 +1156,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) ...@@ -1156,15 +1156,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
{ {
unsigned char pkt_id = SS4_PACKET_ID_IDLE; unsigned char pkt_id = SS4_PACKET_ID_IDLE;
if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && switch (byte[3] & 0x30) {
(byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { case 0x00:
pkt_id = SS4_PACKET_ID_IDLE; if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 &&
} else if (!(byte[3] & 0x10)) { (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 &&
pkt_id = SS4_PACKET_ID_ONE; byte[5] == 0x00) {
} else if (!(byte[3] & 0x20)) { 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; 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; pkt_id = SS4_PACKET_ID_MULTI;
break;
} }
return pkt_id; return pkt_id;
...@@ -1246,16 +1259,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f, ...@@ -1246,16 +1259,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
} }
break; 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: case SS4_PACKET_ID_IDLE:
default: default:
memset(f, 0, sizeof(struct alps_fields)); memset(f, 0, sizeof(struct alps_fields));
break; break;
} }
f->left = !!(SS4_BTN_V2(p) & 0x01); /* handle buttons */
if (!(priv->flags & ALPS_BUTTONPAD)) { if (pkt_id == SS4_PACKET_ID_STICK) {
f->right = !!(SS4_BTN_V2(p) & 0x02); f->ts_left = !!(SS4_BTN_V2(p) & 0x01);
f->middle = !!(SS4_BTN_V2(p) & 0x04); 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; return 0;
...@@ -1266,6 +1301,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) ...@@ -1266,6 +1301,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
struct alps_data *priv = psmouse->private; struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet; unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev; struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
struct alps_fields *f = &priv->f; struct alps_fields *f = &priv->f;
memset(f, 0, sizeof(struct alps_fields)); memset(f, 0, sizeof(struct alps_fields));
...@@ -1311,6 +1347,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) ...@@ -1311,6 +1347,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
input_report_abs(dev, ABS_PRESSURE, f->pressure); input_report_abs(dev, ABS_PRESSURE, f->pressure);
input_sync(dev); 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) static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
......
...@@ -37,12 +37,14 @@ ...@@ -37,12 +37,14 @@
* or there's button activities. * or there's button activities.
* SS4_PACKET_ID_TWO: There's two or more fingers on touchpad * 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_MULTI: There's three or more fingers on touchpad
* SS4_PACKET_ID_STICK: A stick pointer packet
*/ */
enum SS4_PACKET_ID { enum SS4_PACKET_ID {
SS4_PACKET_ID_IDLE = 0, SS4_PACKET_ID_IDLE = 0,
SS4_PACKET_ID_ONE, SS4_PACKET_ID_ONE,
SS4_PACKET_ID_TWO, SS4_PACKET_ID_TWO,
SS4_PACKET_ID_MULTI, SS4_PACKET_ID_MULTI,
SS4_PACKET_ID_STICK,
}; };
#define SS4_COUNT_PER_ELECTRODE 256 #define SS4_COUNT_PER_ELECTRODE 256
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment