All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali.rohar@gmail.com>
To: Ben Gamari <ben@smart-cactus.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Allen Hung <Allen_Hung@dell.com>,
	Ben Morgan <Ben_Morgan@dell.com>,
	Masaki Ota <masaki.ota@jp.alps.com>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Canonical has own Ubuntu driver for ALPS 73 03 28 devices
Date: Sun, 19 Jun 2016 01:43:46 +0200	[thread overview]
Message-ID: <201606190143.46444@pali> (raw)


[-- Attachment #1.1: Type: Text/Plain, Size: 454 bytes --]

I did not know about it since I found:

http://oem.archive.canonical.com/pool/public/o/oem-alps-touchpad-1521052-dkms/oem-alps-touchpad-1521052-dkms_1oem7_all.deb

If you are interested extracted patch is in attachment.

I do not understand it... Why Canonical is hidden and don't communicate
with rest of world? Otherwise touchpads could work out-of-box on non
Ubuntu systems too with mainline kernel.

-- 
Pali Rohár
pali.rohar@gmail.com

[-- Attachment #1.2: alps.patch --]
[-- Type: text/x-patch, Size: 12071 bytes --]

--- alps.c	2016-06-19 01:26:34.755016680 +0200
+++ alps.c	2016-02-03 07:09:04.000000000 +0100
@@ -159,6 +159,10 @@ static const struct alps_protocol_info a
 	ALPS_PROTO_V8, 0x18, 0x18, 0
 };
 
+static const struct alps_protocol_info alps_flare_protocol_data = {
+	ALPS_PROTO_FLARE, 0x18, 0x18, 0
+};
+
 /*
  * Some v2 models report the stick buttons in separate bits
  */
@@ -509,7 +513,7 @@ static void alps_report_mt_data(struct p
 	struct alps_fields *f = &priv->f;
 	int i, slot[MAX_TOUCHES];
 
-	input_mt_assign_slots(dev, slot, f->mt, n, 0);
+	input_mt_assign_slots(dev, slot, f->mt, n);
 	for (i = 0; i < n; i++)
 		alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
 
@@ -716,6 +720,84 @@ static int alps_decode_dolphin(struct al
 	return 0;
 }
 
+static int alps_decode_flare_standard(struct alps_fields *f, unsigned char *p,
+				struct psmouse *psmouse)
+{
+	if (FLARE_IS_1F_PACKET(p)) {
+		f->fingers = 1;
+		f->st.x = FLARE_1F_X(p);
+		f->st.y = FLARE_1F_Y(p);
+		f->pressure = FLARE_1F_Z(p);
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+
+		f->middle = !!(FLARE_STD_BTN(p) & 0x04);
+		f->right = !!(FLARE_STD_BTN(p) & 0x02);
+		f->left = !!(FLARE_STD_BTN(p) & 0x01);
+
+		/* Guard */
+		if (f->pressure == 0) {
+			f->fingers = 0;
+		}
+	} else if (FLARE_IS_2F_PACKET(p)) {
+		f->fingers = 2;
+		if (FLARE_MF_Z(p, 0) == 1) {
+			f->pressure = 64;
+		} else if (FLARE_MF_Z(p, 0) == 2) {
+			f->pressure = 127;
+		}
+
+		f->mt[0].x = FLARE_STD_MF_X(p, 0);
+		f->mt[0].y = FLARE_STD_MF_Y(p, 0);
+		f->mt[1].x = FLARE_STD_MF_X(p, 1);
+		f->mt[1].y = FLARE_STD_MF_Y(p, 1);
+
+		f->st.x = f->mt[0].x;
+		f->st.y = f->mt[0].y;
+	}
+
+	return 0;
+}
+
+static int alps_decode_flare_buttonless(struct alps_fields *f, unsigned char *p,
+				struct psmouse *psmouse)
+{
+	if (FLARE_IS_1F_PACKET(p)) {
+		f->fingers = 1;
+		f->st.x = FLARE_1F_X(p);
+		f->st.y = FLARE_1F_Y(p);
+		f->pressure = FLARE_1F_LFB(p) ? 127 : 64;
+		f->mt[0].x = f->st.x;
+		f->mt[0].y = f->st.y;
+
+		/* Guard.
+		 * How the Z value is calculated is arbitrary. :-) */
+		if (FLARE_1F_Z(p) == 0) {
+			f->fingers = 0;
+			f->pressure = 0;
+		} else if (FLARE_1F_Z(p) < 6) {
+			f->pressure = FLARE_1F_Z(p) * 12;
+		}
+	} else if (FLARE_IS_2F_PACKET(p)) {
+		f->fingers = 2;
+		if (FLARE_MF_Z(p, 0) == 1) {
+			f->pressure = 64;
+		} else if (FLARE_MF_Z(p, 0) == 2) {
+			f->pressure = 127;
+		}
+
+		f->mt[0].x = FLARE_BTL_MF_X(p, 0);
+		f->mt[0].y = FLARE_BTL_MF_Y(p, 0);
+		f->mt[1].x = FLARE_BTL_MF_X(p, 1);
+		f->mt[1].y = FLARE_BTL_MF_Y(p, 1);
+
+		f->st.x = f->mt[0].x;
+		f->st.y = f->mt[0].y;
+	}
+
+	return 0;
+}
+
 static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -793,6 +875,66 @@ static void alps_process_touchpad_packet
 		input_sync(dev2);
 	}
 }
+static void alps_process_touchpad_packet_flare(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+	struct input_dev *dev = psmouse->dev;
+	int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+	int fingers = 0;
+	struct alps_fields *f = &priv->f;
+
+	priv->decode_fields(f, packet, psmouse);
+
+	fingers = f->fingers;
+	x1 = f->mt[0].x;
+	y1 = f->mt[0].y;
+	x2 = f->mt[1].x;
+	y2 = f->mt[1].y;
+
+	/*
+	 * Sometimes the hardware sends a single packet with z = 0
+	 * in the middle of a stream. Real releases generate packets
+	 * with x, y, and z all zero, so these seem to be flukes.
+	 * Ignore them.
+	 */
+	if (f->st.x && f->st.y && !f->pressure)
+		return;
+
+	if (f->pressure > 0)
+		input_report_key(dev, BTN_TOUCH, 1);
+	else
+		input_report_key(dev, BTN_TOUCH, 0);
+
+
+	input_mt_slot(dev, 0);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, fingers != 0);
+	if (fingers != 0) {
+		input_report_abs(dev, ABS_MT_POSITION_X, x1);
+		input_report_abs(dev, ABS_MT_POSITION_Y, y1);
+	}
+
+	input_mt_slot(dev, 1);
+	input_mt_report_slot_state(dev, MT_TOOL_FINGER, fingers == 2);
+	if (fingers == 2) {
+		input_report_abs(dev, ABS_MT_POSITION_X, x2);
+		input_report_abs(dev, ABS_MT_POSITION_Y, y2);
+	}
+
+	input_mt_report_finger_count(dev, fingers);
+
+	input_report_key(dev, BTN_LEFT, f->left);
+	input_report_key(dev, BTN_RIGHT, f->right);
+	input_report_key(dev, BTN_MIDDLE, f->middle);
+
+	if (f->pressure > 0) {
+		input_report_abs(dev, ABS_X, f->st.x);
+		input_report_abs(dev, ABS_Y, f->st.y);
+	}
+	input_report_abs(dev, ABS_PRESSURE, f->pressure);
+
+	input_sync(dev);
+}
 
 static void alps_process_packet_v3(struct psmouse *psmouse)
 {
@@ -1545,6 +1687,7 @@ static psmouse_ret_t alps_process_byte(s
 	 * Can not distinguish V8's first byte from PS/2 packet's
 	 */
 	if (priv->proto_version != ALPS_PROTO_V8 &&
+	    priv->proto_version != ALPS_PROTO_FLARE && /* Ss5 use absolute mode */
 	    !psmouse->out_of_sync_cnt &&
 	    (psmouse->packet[0] & 0xc8) == 0x08) {
 
@@ -2518,6 +2661,24 @@ static int alps_hw_init_dolphin_v1(struc
 	return 0;
 }
 
+static int alps_hw_init_flare(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[2];
+
+	/* This is dolphin "v1" as empirically defined by florin9doi */
+	param[0] = 0x64;
+	param[1] = 0x28;
+
+	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+	    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+	    ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+	    ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+		return -1;
+
+	return 0;
+}
+
 static int alps_hw_init_v7(struct psmouse *psmouse)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -2576,10 +2737,29 @@ error:
 	return ret;
 }
 
+static void alps_set_abs_params_mt(struct alps_data *priv,
+				   struct input_dev *dev1)
+{
+	set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
+	input_mt_init_slots(dev1, 2, 0);
+	input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
+	input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
+
+	set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
+	set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
+	set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
+
+	input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
+	input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
+}
+
 static int alps_set_protocol(struct psmouse *psmouse,
 			     struct alps_data *priv,
 			     const struct alps_protocol_info *protocol)
 {
+	unsigned char flare_config_page[3];
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+
 	psmouse->private = priv;
 
 	setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
@@ -2654,6 +2834,52 @@ static int alps_set_protocol(struct psmo
 
 		break;
 
+	case ALPS_PROTO_FLARE:
+		priv->hw_init = alps_hw_init_flare;
+		priv->process_packet = alps_process_touchpad_packet_flare;
+		priv->set_abs_params = alps_set_abs_params_mt;
+		priv->nibble_commands = alps_v3_nibble_commands;
+		priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+		priv->x_bits = 12;
+		priv->y_bits = 12;
+
+		/* Read configure page 0 */
+		if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+		    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+		    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+		    ps2_command(ps2dev, flare_config_page, PSMOUSE_CMD_GETINFO) ||
+		    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+		    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+		    ps2_command(ps2dev, flare_config_page, PSMOUSE_CMD_GETINFO)) {
+			return -EIO;
+		}
+
+		priv->x_max = (flare_config_page[2] & 0x0f) + 16 - 1;
+		priv->y_max = ((flare_config_page[2] >> 4) & 0x0f) + 5 - 1;
+
+		/* Read configure page 1 */
+		if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
+		    ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
+		    ps2_command(ps2dev, flare_config_page, PSMOUSE_CMD_GETINFO)) {
+			return -EIO;
+		}
+
+		/* b1 of byte0 of configure page 1: Pad Button Emulation
+		 * 	0: No,  standard mode
+		 * 	1: Yes, buttonless(or force) mode */
+		if ((flare_config_page[0] & 0x02)) {
+			priv->decode_fields = alps_decode_flare_buttonless;
+			priv->x_max <<= 6;
+			priv->y_max <<= 6;
+
+		} else {
+			priv->decode_fields = alps_decode_flare_standard;
+			priv->x_max <<= 7;
+			priv->y_max <<= 7;
+		}
+
+		break;
+
 	case ALPS_PROTO_V6:
 		priv->hw_init = alps_hw_init_v6;
 		priv->process_packet = alps_process_packet_v6;
@@ -2744,7 +2970,6 @@ static int alps_identify(struct psmouse
 			 PSMOUSE_CMD_RESET_WRAP, ec) ||
 	    alps_exit_command_mode(psmouse))
 		return -EIO;
-
 	protocol = alps_match_table(e7, ec);
 	if (!protocol) {
 		if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
@@ -2761,6 +2986,8 @@ static int alps_identify(struct psmouse
 		} 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) {
+			protocol = &alps_flare_protocol_data;
 		} else {
 			psmouse_dbg(psmouse,
 				    "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
--- alps.h	2016-06-19 01:34:46.745006525 +0200
+++ alps.h	2016-02-03 07:09:04.000000000 +0100
@@ -20,6 +20,7 @@
 #define ALPS_PROTO_V3_RUSHMORE	0x310
 #define ALPS_PROTO_V4		0x400
 #define ALPS_PROTO_V5		0x500
+#define ALPS_PROTO_FLARE	0x510
 #define ALPS_PROTO_V6		0x600
 #define ALPS_PROTO_V7		0x700	/* t3btl t4s */
 #define ALPS_PROTO_V8		0x800	/* SS4btl SS4s */
@@ -122,6 +123,58 @@ enum V7_PACKET_ID {
 	 V7_PACKET_ID_UNKNOWN,
 };
 
+/* Packet identification Macros for Flare Version2               */
+/* ------------------------------------------------------------- */
+/* FLARE_IS_1F_PACKET	= Recognizes 1-finger packet from others */
+/* FLARE_IS_2F_PACKET	= Recognizes 2-finger packet from others */
+#define	FLARE_IS_1F_PACKET(_b) ((((_b[3] >> 4) & 0x01) == 0) && (((_b[3] >> 5) & 0x01) == 0))
+#define	FLARE_IS_2F_PACKET(_b) ((((_b[3] >> 4) & 0x01) == 0x01) && (((_b[3] >> 5) & 0x01) == 0))
+#define	FLARE_1F_Z(_b) (((_b[5]     ) & 0x0F) |		\
+			((_b[5] >> 1) & 0x70) |		\
+			((_b[4]     ) & 0x80)		\
+			)
+
+
+#define	FLARE_1F_X(_b) ((_b[0] & 0x0007) |	  \
+			((_b[1] << 3) & 0x0078) | \
+			((_b[1] << 2) & 0x0380) | \
+			((_b[2] << 5) & 0x0C00)	  \
+			)
+#define	FLARE_1F_Y(_b) (((_b[2]     ) & 0x000F) |		\
+			((_b[3] >> 2) & 0x0030) |		\
+			((_b[4] << 6) & 0x03C0) |		\
+			((_b[4] << 5) & 0x0C00)			\
+			)
+
+#define	FLARE_1F_LFB(_b) (((_b[2] >> 4) & 0x01) == 0x01)
+#define	FLARE_MF_Z(_b, _i) (((_b[1 + _i * 3]     ) & 0x0001) |	\
+			    ((_b[1 + _i * 3] >> 1) & 0x0002)	\
+			    )
+#define	FLARE_MF_LF(_b, _i) ((_b[1 + _i * 3] & 0x0004) == 0x0004)
+
+/* Packet decoding macros of - Normal HW composition      */
+/* ------------------------------------------------------ */
+/* FLARE_STD_BTN	= 3-bit (; ---- ---- ---- -210 )  */
+/* FLARE_STD_MF_X	= 8-bit	(; ---- BA98 7654 ---- )  */
+/* FLARE_STD_MF_Y	= 8-bit	(; ---- BA98 7654 ---- )  */
+#define	FLARE_STD_BTN(_b) ((_b[0] >> 5 ) & 0x07)
+#define	FLARE_STD_MF_X(_b, _i) (((_b[0 + _i * 3] << 4) & 0x0070) |	\
+				((_b[1 + _i * 3] << 4) & 0x0F80)	\
+				)
+#define	FLARE_STD_MF_Y(_b, _i) (((_b[1 + _i * 3] << 3) & 0x0010) |	\
+				((_b[2 + _i * 3] << 5) & 0x01E0) |	\
+				((_b[2 + _i * 3] << 4) & 0x0E00)	\
+				)
+
+/* Packet decoding macros of  - Buttonless HW composition   */
+/* -------------------------------------------------------- */
+/* FLARE_BTL_MF_X	= 9-bit	(; ---- BA98 7654 3--- )    */
+/* FLARE_BTL_MF_Y	= 9-bit	(; ---- BA98 7654 3--- )    */
+#define	FLARE_BTL_MF_X(_b, _i) (FLARE_STD_MF_X(_b, _i) | ((_b[0 + _i * 3] >> 4) & 0x0008))
+#define	FLARE_BTL_MF_Y(_b, _i) (FLARE_STD_MF_Y(_b, _i) | ((_b[0 + _i * 3] >> 3) & 0x0008))
+
+
+
 /**
  * struct alps_protocol_info - information about protocol used by a device
  * @version: Indicates V1/V2/V3/...

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

             reply	other threads:[~2016-06-18 23:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-18 23:43 Pali Rohár [this message]
2016-06-20 10:16 ` Canonical has own Ubuntu driver for ALPS 73 03 28 devices Christoph Hellwig
2016-06-20 10:20   ` Pali Rohár
2016-06-20 10:20     ` Pali Rohár
2016-06-20 17:29     ` Anthony Wong
2016-06-20 17:29       ` Anthony Wong
2016-06-20 17:37       ` Dmitry Torokhov
2016-06-20 17:37         ` Dmitry Torokhov
2016-06-20 17:47         ` Pali Rohár
2016-06-21 13:42       ` One Thousand Gnomes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201606190143.46444@pali \
    --to=pali.rohar@gmail.com \
    --cc=Allen_Hung@dell.com \
    --cc=Ben_Morgan@dell.com \
    --cc=ben@smart-cactus.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=hdegoede@redhat.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masaki.ota@jp.alps.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.