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

Commit e0d41fd4 authored by Ping Cheng's avatar Ping Cheng Committed by Jiri Kosina
Browse files

HID: wacom: rely on actual touch down count to decide touch_down



touch_down is a flag to indicate if there are touches on tablet
or not. Since one set of touch events may be posted over more
than one data packet/touch frame, and pen may come in proximity
while touch events are partially sent, counting all touch events
for the set reflects the actual status of touch_down.

Signed-off-by: default avatarPing Cheng <pingc@wacom.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 486b908d
Loading
Loading
Loading
Loading
+43 −32
Original line number Original line Diff line number Diff line
@@ -1046,27 +1046,28 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
	struct input_dev *input = wacom->input;
	struct input_dev *input = wacom->input;
	unsigned char *data = wacom->data;
	unsigned char *data = wacom->data;
	int i;
	int i;
	int current_num_contacts = 0;
	int current_num_contacts = data[61];
	int contacts_to_send = 0;
	int contacts_to_send = 0;
	int num_contacts_left = 4; /* maximum contacts per packet */
	int num_contacts_left = 4; /* maximum contacts per packet */
	int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
	int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
	int y_offset = 2;
	int y_offset = 2;
	static int contact_with_no_pen_down_count = 0;


	if (wacom->features.type == WACOM_27QHDT) {
	if (wacom->features.type == WACOM_27QHDT) {
		current_num_contacts = data[63];
		current_num_contacts = data[63];
		num_contacts_left = 10;
		num_contacts_left = 10;
		byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
		byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
		y_offset = 0;
		y_offset = 0;
	} else {
		current_num_contacts = data[61];
	}
	}


	/*
	/*
	 * First packet resets the counter since only the first
	 * First packet resets the counter since only the first
	 * packet in series will have non-zero current_num_contacts.
	 * packet in series will have non-zero current_num_contacts.
	 */
	 */
	if (current_num_contacts)
	if (current_num_contacts) {
		wacom->num_contacts_left = current_num_contacts;
		wacom->num_contacts_left = current_num_contacts;
		contact_with_no_pen_down_count = 0;
	}


	contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
	contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);


@@ -1099,15 +1100,16 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
				input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
				input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
				input_report_abs(input, ABS_MT_ORIENTATION, w > h);
				input_report_abs(input, ABS_MT_ORIENTATION, w > h);
			}
			}
			contact_with_no_pen_down_count++;
		}
		}
	}
	}
	input_mt_report_pointer_emulation(input, true);
	input_mt_report_pointer_emulation(input, true);


	wacom->num_contacts_left -= contacts_to_send;
	wacom->num_contacts_left -= contacts_to_send;
	if (wacom->num_contacts_left <= 0)
	if (wacom->num_contacts_left <= 0) {
		wacom->num_contacts_left = 0;
		wacom->num_contacts_left = 0;

		wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
	wacom->shared->touch_down = (wacom->num_contacts_left > 0);
	}
	return 1;
	return 1;
}
}


@@ -1119,6 +1121,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
	int current_num_contacts = data[2];
	int current_num_contacts = data[2];
	int contacts_to_send = 0;
	int contacts_to_send = 0;
	int x_offset = 0;
	int x_offset = 0;
	static int contact_with_no_pen_down_count = 0;


	/* MTTPC does not support Height and Width */
	/* MTTPC does not support Height and Width */
	if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
	if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
@@ -1128,8 +1131,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
	 * First packet resets the counter since only the first
	 * First packet resets the counter since only the first
	 * packet in series will have non-zero current_num_contacts.
	 * packet in series will have non-zero current_num_contacts.
	 */
	 */
	if (current_num_contacts)
	if (current_num_contacts) {
		wacom->num_contacts_left = current_num_contacts;
		wacom->num_contacts_left = current_num_contacts;
		contact_with_no_pen_down_count = 0;
	}


	/* There are at most 5 contacts per packet */
	/* There are at most 5 contacts per packet */
	contacts_to_send = min(5, wacom->num_contacts_left);
	contacts_to_send = min(5, wacom->num_contacts_left);
@@ -1150,15 +1155,16 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
			int y = get_unaligned_le16(&data[offset + x_offset + 9]);
			int y = get_unaligned_le16(&data[offset + x_offset + 9]);
			input_report_abs(input, ABS_MT_POSITION_X, x);
			input_report_abs(input, ABS_MT_POSITION_X, x);
			input_report_abs(input, ABS_MT_POSITION_Y, y);
			input_report_abs(input, ABS_MT_POSITION_Y, y);
			contact_with_no_pen_down_count++;
		}
		}
	}
	}
	input_mt_report_pointer_emulation(input, true);
	input_mt_report_pointer_emulation(input, true);


	wacom->num_contacts_left -= contacts_to_send;
	wacom->num_contacts_left -= contacts_to_send;
	if (wacom->num_contacts_left < 0)
	if (wacom->num_contacts_left <= 0) {
		wacom->num_contacts_left = 0;
		wacom->num_contacts_left = 0;

		wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
	wacom->shared->touch_down = (wacom->num_contacts_left > 0);
	}
	return 1;
	return 1;
}
}


@@ -1196,29 +1202,25 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
{
{
	unsigned char *data = wacom->data;
	unsigned char *data = wacom->data;
	struct input_dev *input = wacom->input;
	struct input_dev *input = wacom->input;
	bool prox;
	bool prox = !wacom->shared->stylus_in_proximity;
	int x = 0, y = 0;
	int x = 0, y = 0;


	if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
	if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
		return 0;
		return 0;


	if (!wacom->shared->stylus_in_proximity) {
	if (len == WACOM_PKGLEN_TPC1FG) {
	if (len == WACOM_PKGLEN_TPC1FG) {
			prox = data[0] & 0x01;
		prox = prox && (data[0] & 0x01);
		x = get_unaligned_le16(&data[1]);
		x = get_unaligned_le16(&data[1]);
		y = get_unaligned_le16(&data[3]);
		y = get_unaligned_le16(&data[3]);
	} else if (len == WACOM_PKGLEN_TPC1FG_B) {
	} else if (len == WACOM_PKGLEN_TPC1FG_B) {
			prox = data[2] & 0x01;
		prox = prox && (data[2] & 0x01);
		x = get_unaligned_le16(&data[3]);
		x = get_unaligned_le16(&data[3]);
		y = get_unaligned_le16(&data[5]);
		y = get_unaligned_le16(&data[5]);
	} else {
	} else {
			prox = data[1] & 0x01;
		prox = prox && (data[1] & 0x01);
		x = le16_to_cpup((__le16 *)&data[2]);
		x = le16_to_cpup((__le16 *)&data[2]);
		y = le16_to_cpup((__le16 *)&data[4]);
		y = le16_to_cpup((__le16 *)&data[4]);
	}
	}
	} else
		/* force touch out when pen is in prox */
		prox = 0;


	if (prox) {
	if (prox) {
		input_report_abs(input, ABS_X, x);
		input_report_abs(input, ABS_X, x);
@@ -1616,6 +1618,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
	struct input_dev *pad_input = wacom->pad_input;
	struct input_dev *pad_input = wacom->pad_input;
	unsigned char *data = wacom->data;
	unsigned char *data = wacom->data;
	int i;
	int i;
	int contact_with_no_pen_down_count = 0;


	if (data[0] != 0x02)
	if (data[0] != 0x02)
	    return 0;
	    return 0;
@@ -1643,6 +1646,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
			}
			}
			input_report_abs(input, ABS_MT_POSITION_X, x);
			input_report_abs(input, ABS_MT_POSITION_X, x);
			input_report_abs(input, ABS_MT_POSITION_Y, y);
			input_report_abs(input, ABS_MT_POSITION_Y, y);
			contact_with_no_pen_down_count++;
		}
		}
	}
	}


@@ -1652,11 +1656,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
	input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
	input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
	input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
	input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
	input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
	input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);


	return 1;
	return 1;
}
}


static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
{
{
	struct wacom_features *features = &wacom->features;
	struct wacom_features *features = &wacom->features;
	struct input_dev *input = wacom->input;
	struct input_dev *input = wacom->input;
@@ -1664,7 +1669,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
	int slot = input_mt_get_slot_by_key(input, data[0]);
	int slot = input_mt_get_slot_by_key(input, data[0]);


	if (slot < 0)
	if (slot < 0)
		return;
		return 0;


	touch = touch && !wacom->shared->stylus_in_proximity;
	touch = touch && !wacom->shared->stylus_in_proximity;


@@ -1696,7 +1701,9 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
		input_report_abs(input, ABS_MT_POSITION_Y, y);
		input_report_abs(input, ABS_MT_POSITION_Y, y);
		input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
		input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
		input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
		input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
		last_touch_count++;
	}
	}
	return last_touch_count;
}
}


static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
@@ -1721,6 +1728,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
	unsigned char *data = wacom->data;
	unsigned char *data = wacom->data;
	int count = data[1] & 0x07;
	int count = data[1] & 0x07;
	int i;
	int i;
	int contact_with_no_pen_down_count = 0;


	if (data[0] != 0x02)
	if (data[0] != 0x02)
	    return 0;
	    return 0;
@@ -1731,12 +1739,15 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
		int msg_id = data[offset];
		int msg_id = data[offset];


		if (msg_id >= 2 && msg_id <= 17)
		if (msg_id >= 2 && msg_id <= 17)
			wacom_bpt3_touch_msg(wacom, data + offset);
			contact_with_no_pen_down_count = 
			    wacom_bpt3_touch_msg(wacom, data + offset,
						 contact_with_no_pen_down_count);
		else if (msg_id == 128)
		else if (msg_id == 128)
			wacom_bpt3_button_msg(wacom, data + offset);
			wacom_bpt3_button_msg(wacom, data + offset);


	}
	}
	input_mt_report_pointer_emulation(input, true);
	input_mt_report_pointer_emulation(input, true);
	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);


	return 1;
	return 1;
}
}