imperfectism / rpms / kernel

Forked from rpms/kernel 4 years ago
Clone
f2c60e
From 33fc16fd8aa3684e19b1d1f0a712593e2e570ab1 Mon Sep 17 00:00:00 2001
f2c60e
From: Hans de Goede <hdegoede@redhat.com>
f2c60e
Date: Sun, 11 Jun 2017 21:24:50 +0200
f2c60e
Subject: [PATCH 10/16] Input: silead: Add support for capactive home button
f2c60e
 found on some x86 tablets
f2c60e
f2c60e
On some x86 tablets with a silead touchscreen the windows logo on the
f2c60e
front is a capacitive home button. Touching this button results in a touch
f2c60e
with bits 12-15 of the Y coordinates set, while normally only the lower 12
f2c60e
are used.
f2c60e
f2c60e
Detect this and report a KEY_LEFTMETA press when this happens. Note for
f2c60e
now we only respond to the Y coordinate bits 12-15 containing 0x01, on some
f2c60e
tablets *without* a capacative button I've noticed these bits containing
f2c60e
0x04 when crossing the edges of the screen.
f2c60e
f2c60e
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
f2c60e
---
f2c60e
 drivers/input/touchscreen/silead.c | 45 ++++++++++++++++++++++++++++----------
f2c60e
 1 file changed, 34 insertions(+), 11 deletions(-)
f2c60e
f2c60e
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
f2c60e
index 0dbcf105f7db..c0ba40c09699 100644
f2c60e
--- a/drivers/input/touchscreen/silead.c
f2c60e
+++ b/drivers/input/touchscreen/silead.c
f2c60e
@@ -56,7 +56,7 @@
f2c60e
 #define SILEAD_POINT_Y_MSB_OFF	0x01
f2c60e
 #define SILEAD_POINT_X_OFF	0x02
f2c60e
 #define SILEAD_POINT_X_MSB_OFF	0x03
f2c60e
-#define SILEAD_TOUCH_ID_MASK	0xF0
f2c60e
+#define SILEAD_EXTRA_DATA_MASK	0xF0
f2c60e
 
f2c60e
 #define SILEAD_CMD_SLEEP_MIN	10000
f2c60e
 #define SILEAD_CMD_SLEEP_MAX	20000
f2c60e
@@ -109,6 +109,8 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
f2c60e
 			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
f2c60e
 			    INPUT_MT_TRACK);
f2c60e
 
f2c60e
+	input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);
f2c60e
+
f2c60e
 	data->input->name = SILEAD_TS_NAME;
f2c60e
 	data->input->phys = "input/ts";
f2c60e
 	data->input->id.bustype = BUS_I2C;
f2c60e
@@ -139,7 +141,8 @@ static void silead_ts_read_data(struct i2c_client *client)
f2c60e
 	struct input_dev *input = data->input;
f2c60e
 	struct device *dev = &client->dev;
f2c60e
 	u8 *bufp, buf[SILEAD_TS_DATA_LEN];
f2c60e
-	int touch_nr, error, i;
f2c60e
+	int touch_nr, softbutton, error, i;
f2c60e
+	bool softbutton_pressed = false;
f2c60e
 
f2c60e
 	error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
f2c60e
 					      SILEAD_TS_DATA_LEN, buf);
f2c60e
@@ -148,21 +151,40 @@ static void silead_ts_read_data(struct i2c_client *client)
f2c60e
 		return;
f2c60e
 	}
f2c60e
 
f2c60e
-	touch_nr = buf[0];
f2c60e
-	if (touch_nr > data->max_fingers) {
f2c60e
+	if (buf[0] > data->max_fingers) {
f2c60e
 		dev_warn(dev, "More touches reported then supported %d > %d\n",
f2c60e
-			 touch_nr, data->max_fingers);
f2c60e
-		touch_nr = data->max_fingers;
f2c60e
+			 buf[0], data->max_fingers);
f2c60e
+		buf[0] = data->max_fingers;
f2c60e
 	}
f2c60e
 
f2c60e
+	touch_nr = 0;
f2c60e
 	bufp = buf + SILEAD_POINT_DATA_LEN;
f2c60e
-	for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) {
f2c60e
-		/* Bits 4-7 are the touch id */
f2c60e
-		data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] &
f2c60e
-			       SILEAD_TOUCH_ID_MASK) >> 4;
f2c60e
-		touchscreen_set_mt_pos(&data->pos[i], &data->prop,
f2c60e
+	for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) {
f2c60e
+		softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] &
f2c60e
+			      SILEAD_EXTRA_DATA_MASK) >> 4;
f2c60e
+
f2c60e
+		if (softbutton) {
f2c60e
+			/*
f2c60e
+			 * For now only respond to softbutton == 0x01, some
f2c60e
+			 * tablets *without* a capacative button send 0x04
f2c60e
+			 * when crossing the edges of the screen.
f2c60e
+			 */
f2c60e
+			if (softbutton == 0x01)
f2c60e
+				softbutton_pressed = true;
f2c60e
+
f2c60e
+			continue;
f2c60e
+		}
f2c60e
+
f2c60e
+		/*
f2c60e
+		 * Bits 4-7 are the touch id, note not all models have
f2c60e
+		 * hardware touch ids so atm we don't use these.
f2c60e
+		 */
f2c60e
+		data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] &
f2c60e
+				      SILEAD_EXTRA_DATA_MASK) >> 4;
f2c60e
+		touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop,
f2c60e
 			get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
f2c60e
 			get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
f2c60e
+		touch_nr++;
f2c60e
 	}
f2c60e
 
f2c60e
 	input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
f2c60e
@@ -178,6 +200,7 @@ static void silead_ts_read_data(struct i2c_client *client)
f2c60e
 	}
f2c60e
 
f2c60e
 	input_mt_sync_frame(input);
f2c60e
+	input_report_key(input, KEY_LEFTMETA, softbutton_pressed);
f2c60e
 	input_sync(input);
f2c60e
 }
f2c60e
 
f2c60e
-- 
f2c60e
2.13.0
f2c60e