diff options
author | Ping Cheng <pinglinux@gmail.com> | 2015-02-20 17:27:30 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-03-02 18:27:10 -0500 |
commit | e0d41fd435ad71b86380f27195aa117400439f37 (patch) | |
tree | 9a488d9eaa758469a13c5c712884204e71bfb2b7 | |
parent | 486b908d4412510d66ee348ba765de8d93441345 (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.c | 75 |
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 | ||
1659 | static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) | 1664 | static 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 | ||
1702 | static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) | 1709 | 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) | |||
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 | } |