Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+54 −11
Original line number Diff line number Diff line
@@ -1156,15 +1156,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
{
	unsigned char pkt_id = SS4_PACKET_ID_IDLE;

	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) {
		    (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 &&
		    byte[5] == 0x00) {
			pkt_id = SS4_PACKET_ID_IDLE;
	} else if (!(byte[3] & 0x10)) {
		} else {
			pkt_id = SS4_PACKET_ID_ONE;
	} else if (!(byte[3] & 0x20)) {
		}
		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,17 +1259,39 @@ 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;
	}

	/* 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 +1301,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 +1347,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)
+2 −0
Original line number Diff line number Diff line
@@ -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