aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPing Cheng <pinglinux@gmail.com>2015-02-20 17:27:30 -0500
committerJiri Kosina <jkosina@suse.cz>2015-03-02 18:27:10 -0500
commite0d41fd435ad71b86380f27195aa117400439f37 (patch)
tree9a488d9eaa758469a13c5c712884204e71bfb2b7
parent486b908d4412510d66ee348ba765de8d93441345 (diff)
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: Ping Cheng <pingc@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/wacom_wac.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 69827c928e50..cf767419cdc4 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1046,27 +1046,28 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
1046 struct input_dev *input = wacom->input; 1046 struct input_dev *input = wacom->input;
1047 unsigned char *data = wacom->data; 1047 unsigned char *data = wacom->data;
1048 int i; 1048 int i;
1049 int current_num_contacts = 0; 1049 int current_num_contacts = data[61];
1050 int contacts_to_send = 0; 1050 int contacts_to_send = 0;
1051 int num_contacts_left = 4; /* maximum contacts per packet */ 1051 int num_contacts_left = 4; /* maximum contacts per packet */
1052 int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET; 1052 int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
1053 int y_offset = 2; 1053 int y_offset = 2;
1054 static int contact_with_no_pen_down_count = 0;
1054 1055
1055 if (wacom->features.type == WACOM_27QHDT) { 1056 if (wacom->features.type == WACOM_27QHDT) {
1056 current_num_contacts = data[63]; 1057 current_num_contacts = data[63];
1057 num_contacts_left = 10; 1058 num_contacts_left = 10;
1058 byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET; 1059 byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
1059 y_offset = 0; 1060 y_offset = 0;
1060 } else {
1061 current_num_contacts = data[61];
1062 } 1061 }
1063 1062
1064 /* 1063 /*
1065 * First packet resets the counter since only the first 1064 * First packet resets the counter since only the first
1066 * packet in series will have non-zero current_num_contacts. 1065 * packet in series will have non-zero current_num_contacts.
1067 */ 1066 */
1068 if (current_num_contacts) 1067 if (current_num_contacts) {
1069 wacom->num_contacts_left = current_num_contacts; 1068 wacom->num_contacts_left = current_num_contacts;
1069 contact_with_no_pen_down_count = 0;
1070 }
1070 1071
1071 contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); 1072 contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
1072 1073
@@ -1099,15 +1100,16 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
1099 input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); 1100 input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
1100 input_report_abs(input, ABS_MT_ORIENTATION, w > h); 1101 input_report_abs(input, ABS_MT_ORIENTATION, w > h);
1101 } 1102 }
1103 contact_with_no_pen_down_count++;
1102 } 1104 }
1103 } 1105 }
1104 input_mt_report_pointer_emulation(input, true); 1106 input_mt_report_pointer_emulation(input, true);
1105 1107
1106 wacom->num_contacts_left -= contacts_to_send; 1108 wacom->num_contacts_left -= contacts_to_send;
1107 if (wacom->num_contacts_left <= 0) 1109 if (wacom->num_contacts_left <= 0) {
1108 wacom->num_contacts_left = 0; 1110 wacom->num_contacts_left = 0;
1109 1111 wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
1110 wacom->shared->touch_down = (wacom->num_contacts_left > 0); 1112 }
1111 return 1; 1113 return 1;
1112} 1114}
1113 1115
@@ -1119,6 +1121,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
1119 int current_num_contacts = data[2]; 1121 int current_num_contacts = data[2];
1120 int contacts_to_send = 0; 1122 int contacts_to_send = 0;
1121 int x_offset = 0; 1123 int x_offset = 0;
1124 static int contact_with_no_pen_down_count = 0;
1122 1125
1123 /* MTTPC does not support Height and Width */ 1126 /* MTTPC does not support Height and Width */
1124 if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B) 1127 if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
@@ -1128,8 +1131,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
1128 * First packet resets the counter since only the first 1131 * First packet resets the counter since only the first
1129 * packet in series will have non-zero current_num_contacts. 1132 * packet in series will have non-zero current_num_contacts.
1130 */ 1133 */
1131 if (current_num_contacts) 1134 if (current_num_contacts) {
1132 wacom->num_contacts_left = current_num_contacts; 1135 wacom->num_contacts_left = current_num_contacts;
1136 contact_with_no_pen_down_count = 0;
1137 }
1133 1138
1134 /* There are at most 5 contacts per packet */ 1139 /* There are at most 5 contacts per packet */
1135 contacts_to_send = min(5, wacom->num_contacts_left); 1140 contacts_to_send = min(5, wacom->num_contacts_left);
@@ -1150,15 +1155,16 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
1150 int y = get_unaligned_le16(&data[offset + x_offset + 9]); 1155 int y = get_unaligned_le16(&data[offset + x_offset + 9]);
1151 input_report_abs(input, ABS_MT_POSITION_X, x); 1156 input_report_abs(input, ABS_MT_POSITION_X, x);
1152 input_report_abs(input, ABS_MT_POSITION_Y, y); 1157 input_report_abs(input, ABS_MT_POSITION_Y, y);
1158 contact_with_no_pen_down_count++;
1153 } 1159 }
1154 } 1160 }
1155 input_mt_report_pointer_emulation(input, true); 1161 input_mt_report_pointer_emulation(input, true);
1156 1162
1157 wacom->num_contacts_left -= contacts_to_send; 1163 wacom->num_contacts_left -= contacts_to_send;
1158 if (wacom->num_contacts_left < 0) 1164 if (wacom->num_contacts_left <= 0) {
1159 wacom->num_contacts_left = 0; 1165 wacom->num_contacts_left = 0;
1160 1166 wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
1161 wacom->shared->touch_down = (wacom->num_contacts_left > 0); 1167 }
1162 return 1; 1168 return 1;
1163} 1169}
1164 1170
@@ -1196,29 +1202,25 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
1196{ 1202{
1197 unsigned char *data = wacom->data; 1203 unsigned char *data = wacom->data;
1198 struct input_dev *input = wacom->input; 1204 struct input_dev *input = wacom->input;
1199 bool prox; 1205 bool prox = !wacom->shared->stylus_in_proximity;
1200 int x = 0, y = 0; 1206 int x = 0, y = 0;
1201 1207
1202 if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) 1208 if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
1203 return 0; 1209 return 0;
1204 1210
1205 if (!wacom->shared->stylus_in_proximity) { 1211 if (len == WACOM_PKGLEN_TPC1FG) {
1206 if (len == WACOM_PKGLEN_TPC1FG) { 1212 prox = prox && (data[0] & 0x01);
1207 prox = data[0] & 0x01; 1213 x = get_unaligned_le16(&data[1]);
1208 x = get_unaligned_le16(&data[1]); 1214 y = get_unaligned_le16(&data[3]);
1209 y = get_unaligned_le16(&data[3]); 1215 } else if (len == WACOM_PKGLEN_TPC1FG_B) {
1210 } else if (len == WACOM_PKGLEN_TPC1FG_B) { 1216 prox = prox && (data[2] & 0x01);
1211 prox = data[2] & 0x01; 1217 x = get_unaligned_le16(&data[3]);
1212 x = get_unaligned_le16(&data[3]); 1218 y = get_unaligned_le16(&data[5]);
1213 y = get_unaligned_le16(&data[5]); 1219 } else {
1214 } else { 1220 prox = prox && (data[1] & 0x01);
1215 prox = data[1] & 0x01; 1221 x = le16_to_cpup((__le16 *)&data[2]);
1216 x = le16_to_cpup((__le16 *)&data[2]); 1222 y = le16_to_cpup((__le16 *)&data[4]);
1217 y = le16_to_cpup((__le16 *)&data[4]); 1223 }
1218 }
1219 } else
1220 /* force touch out when pen is in prox */
1221 prox = 0;
1222 1224
1223 if (prox) { 1225 if (prox) {
1224 input_report_abs(input, ABS_X, x); 1226 input_report_abs(input, ABS_X, x);
@@ -1616,6 +1618,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
1616 struct input_dev *pad_input = wacom->pad_input; 1618 struct input_dev *pad_input = wacom->pad_input;
1617 unsigned char *data = wacom->data; 1619 unsigned char *data = wacom->data;
1618 int i; 1620 int i;
1621 int contact_with_no_pen_down_count = 0;
1619 1622
1620 if (data[0] != 0x02) 1623 if (data[0] != 0x02)
1621 return 0; 1624 return 0;
@@ -1643,6 +1646,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
1643 } 1646 }
1644 input_report_abs(input, ABS_MT_POSITION_X, x); 1647 input_report_abs(input, ABS_MT_POSITION_X, x);
1645 input_report_abs(input, ABS_MT_POSITION_Y, y); 1648 input_report_abs(input, ABS_MT_POSITION_Y, y);
1649 contact_with_no_pen_down_count++;
1646 } 1650 }
1647 } 1651 }
1648 1652
@@ -1652,11 +1656,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
1652 input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0); 1656 input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
1653 input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0); 1657 input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
1654 input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0); 1658 input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
1659 wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
1655 1660
1656 return 1; 1661 return 1;
1657} 1662}
1658 1663
1659static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) 1664static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
1660{ 1665{
1661 struct wacom_features *features = &wacom->features; 1666 struct wacom_features *features = &wacom->features;
1662 struct input_dev *input = wacom->input; 1667 struct input_dev *input = wacom->input;
@@ -1664,7 +1669,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
1664 int slot = input_mt_get_slot_by_key(input, data[0]); 1669 int slot = input_mt_get_slot_by_key(input, data[0]);
1665 1670
1666 if (slot < 0) 1671 if (slot < 0)
1667 return; 1672 return 0;
1668 1673
1669 touch = touch && !wacom->shared->stylus_in_proximity; 1674 touch = touch && !wacom->shared->stylus_in_proximity;
1670 1675
@@ -1696,7 +1701,9 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
1696 input_report_abs(input, ABS_MT_POSITION_Y, y); 1701 input_report_abs(input, ABS_MT_POSITION_Y, y);
1697 input_report_abs(input, ABS_MT_TOUCH_MAJOR, width); 1702 input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
1698 input_report_abs(input, ABS_MT_TOUCH_MINOR, height); 1703 input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
1704 last_touch_count++;
1699 } 1705 }
1706 return last_touch_count;
1700} 1707}
1701 1708
1702static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) 1709static 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)
1721 unsigned char *data = wacom->data; 1728 unsigned char *data = wacom->data;
1722 int count = data[1] & 0x07; 1729 int count = data[1] & 0x07;
1723 int i; 1730 int i;
1731 int contact_with_no_pen_down_count = 0;
1724 1732
1725 if (data[0] != 0x02) 1733 if (data[0] != 0x02)
1726 return 0; 1734 return 0;
@@ -1731,12 +1739,15 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
1731 int msg_id = data[offset]; 1739 int msg_id = data[offset];
1732 1740
1733 if (msg_id >= 2 && msg_id <= 17) 1741 if (msg_id >= 2 && msg_id <= 17)
1734 wacom_bpt3_touch_msg(wacom, data + offset); 1742 contact_with_no_pen_down_count =
1743 wacom_bpt3_touch_msg(wacom, data + offset,
1744 contact_with_no_pen_down_count);
1735 else if (msg_id == 128) 1745 else if (msg_id == 128)
1736 wacom_bpt3_button_msg(wacom, data + offset); 1746 wacom_bpt3_button_msg(wacom, data + offset);
1737 1747
1738 } 1748 }
1739 input_mt_report_pointer_emulation(input, true); 1749 input_mt_report_pointer_emulation(input, true);
1750 wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
1740 1751
1741 return 1; 1752 return 1;
1742} 1753}