diff options
author | Ben Gamari <ben@smart-cactus.org> | 2016-10-04 14:33:25 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2016-10-04 14:46:41 -0400 |
commit | 4777ac220c430173e297237b896932ed5fd8aaf3 (patch) | |
tree | 86fde151cee555985888c9b1aa8578accb2a1580 /drivers/input | |
parent | f9a703a54d16ba2470391c4b12236ee56591d50c (diff) |
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: Pali Rohár <pali.rohar@gmail.com>
Tested-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Ben Gamari <ben@smart-cactus.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/alps.c | 65 | ||||
-rw-r--r-- | drivers/input/mouse/alps.h | 2 |
2 files changed, 56 insertions, 11 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 936f07a4e35f..8e15783d2932 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -1156,15 +1156,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) | |||
1156 | { | 1156 | { |
1157 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; | 1157 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; |
1158 | 1158 | ||
1159 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && | 1159 | switch (byte[3] & 0x30) { |
1160 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { | 1160 | case 0x00: |
1161 | pkt_id = SS4_PACKET_ID_IDLE; | 1161 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && |
1162 | } else if (!(byte[3] & 0x10)) { | 1162 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && |
1163 | pkt_id = SS4_PACKET_ID_ONE; | 1163 | byte[5] == 0x00) { |
1164 | } else if (!(byte[3] & 0x20)) { | 1164 | pkt_id = SS4_PACKET_ID_IDLE; |
1165 | } else { | ||
1166 | pkt_id = SS4_PACKET_ID_ONE; | ||
1167 | } | ||
1168 | break; | ||
1169 | case 0x10: | ||
1170 | /* two-finger finger positions */ | ||
1165 | pkt_id = SS4_PACKET_ID_TWO; | 1171 | pkt_id = SS4_PACKET_ID_TWO; |
1166 | } else { | 1172 | break; |
1173 | case 0x20: | ||
1174 | /* stick pointer */ | ||
1175 | pkt_id = SS4_PACKET_ID_STICK; | ||
1176 | break; | ||
1177 | case 0x30: | ||
1178 | /* third and fourth finger positions */ | ||
1167 | pkt_id = SS4_PACKET_ID_MULTI; | 1179 | pkt_id = SS4_PACKET_ID_MULTI; |
1180 | break; | ||
1168 | } | 1181 | } |
1169 | 1182 | ||
1170 | return pkt_id; | 1183 | return pkt_id; |
@@ -1246,16 +1259,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f, | |||
1246 | } | 1259 | } |
1247 | break; | 1260 | break; |
1248 | 1261 | ||
1262 | case SS4_PACKET_ID_STICK: | ||
1263 | if (!(priv->flags & ALPS_DUALPOINT)) { | ||
1264 | psmouse_warn(psmouse, | ||
1265 | "Rejected trackstick packet from non DualPoint device"); | ||
1266 | } else { | ||
1267 | int x = (s8)(((p[0] & 1) << 7) | (p[1] & 0x7f)); | ||
1268 | int y = (s8)(((p[3] & 1) << 7) | (p[2] & 0x7f)); | ||
1269 | |||
1270 | input_report_rel(priv->dev2, REL_X, x); | ||
1271 | input_report_rel(priv->dev2, REL_Y, -y); | ||
1272 | } | ||
1273 | break; | ||
1274 | |||
1249 | case SS4_PACKET_ID_IDLE: | 1275 | case SS4_PACKET_ID_IDLE: |
1250 | default: | 1276 | default: |
1251 | memset(f, 0, sizeof(struct alps_fields)); | 1277 | memset(f, 0, sizeof(struct alps_fields)); |
1252 | break; | 1278 | break; |
1253 | } | 1279 | } |
1254 | 1280 | ||
1255 | f->left = !!(SS4_BTN_V2(p) & 0x01); | 1281 | /* handle buttons */ |
1256 | if (!(priv->flags & ALPS_BUTTONPAD)) { | 1282 | if (pkt_id == SS4_PACKET_ID_STICK) { |
1257 | f->right = !!(SS4_BTN_V2(p) & 0x02); | 1283 | f->ts_left = !!(SS4_BTN_V2(p) & 0x01); |
1258 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | 1284 | if (!(priv->flags & ALPS_BUTTONPAD)) { |
1285 | f->ts_right = !!(SS4_BTN_V2(p) & 0x02); | ||
1286 | f->ts_middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1287 | } | ||
1288 | } else { | ||
1289 | f->left = !!(SS4_BTN_V2(p) & 0x01); | ||
1290 | if (!(priv->flags & ALPS_BUTTONPAD)) { | ||
1291 | f->right = !!(SS4_BTN_V2(p) & 0x02); | ||
1292 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1293 | } | ||
1259 | } | 1294 | } |
1260 | 1295 | ||
1261 | return 0; | 1296 | return 0; |
@@ -1266,6 +1301,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | |||
1266 | struct alps_data *priv = psmouse->private; | 1301 | struct alps_data *priv = psmouse->private; |
1267 | unsigned char *packet = psmouse->packet; | 1302 | unsigned char *packet = psmouse->packet; |
1268 | struct input_dev *dev = psmouse->dev; | 1303 | struct input_dev *dev = psmouse->dev; |
1304 | struct input_dev *dev2 = priv->dev2; | ||
1269 | struct alps_fields *f = &priv->f; | 1305 | struct alps_fields *f = &priv->f; |
1270 | 1306 | ||
1271 | memset(f, 0, sizeof(struct alps_fields)); | 1307 | memset(f, 0, sizeof(struct alps_fields)); |
@@ -1311,6 +1347,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | |||
1311 | 1347 | ||
1312 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | 1348 | input_report_abs(dev, ABS_PRESSURE, f->pressure); |
1313 | input_sync(dev); | 1349 | input_sync(dev); |
1350 | |||
1351 | if (priv->flags & ALPS_DUALPOINT) { | ||
1352 | input_report_key(dev2, BTN_LEFT, f->ts_left); | ||
1353 | input_report_key(dev2, BTN_RIGHT, f->ts_right); | ||
1354 | input_report_key(dev2, BTN_MIDDLE, f->ts_middle); | ||
1355 | input_sync(dev2); | ||
1356 | } | ||
1314 | } | 1357 | } |
1315 | 1358 | ||
1316 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) | 1359 | 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 d37f814dc447..b9417e2d7ad3 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -37,12 +37,14 @@ | |||
37 | * or there's button activities. | 37 | * or there's button activities. |
38 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad | 38 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad |
39 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad | 39 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad |
40 | * SS4_PACKET_ID_STICK: A stick pointer packet | ||
40 | */ | 41 | */ |
41 | enum SS4_PACKET_ID { | 42 | enum SS4_PACKET_ID { |
42 | SS4_PACKET_ID_IDLE = 0, | 43 | SS4_PACKET_ID_IDLE = 0, |
43 | SS4_PACKET_ID_ONE, | 44 | SS4_PACKET_ID_ONE, |
44 | SS4_PACKET_ID_TWO, | 45 | SS4_PACKET_ID_TWO, |
45 | SS4_PACKET_ID_MULTI, | 46 | SS4_PACKET_ID_MULTI, |
47 | SS4_PACKET_ID_STICK, | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | #define SS4_COUNT_PER_ELECTRODE 256 | 50 | #define SS4_COUNT_PER_ELECTRODE 256 |