Skip to content

Commit b0fb904

Browse files
jigpuJiri Kosina
authored andcommitted
HID: wacom: Add additional tests of confidence behavior
Test for proper driver behavior when the touch confidence bit is set or cleared. Test the three flavors of touch confidence loss (tipswitch cleared before confidence, tipswitch and confidence cleared at the same time, and tipswitch only cleared when touch is actually removed). Also test two flavors of touch confidence gain (confidence added to a touch that was "never" confident, and confidence added to a touch that was previously confident). Signed-off-by: Jason Gerecke <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 5022960 commit b0fb904

File tree

1 file changed

+277
-1
lines changed

1 file changed

+277
-1
lines changed

tools/testing/selftests/hid/tests/test_wacom_generic.py

Lines changed: 277 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
)
2828

2929
import attr
30+
from collections import namedtuple
3031
from enum import Enum
3132
from hidtools.hut import HUT
3233
from hidtools.hid import HidUnit
@@ -862,13 +863,66 @@ def offset_rotation(value):
862863

863864

864865
class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest):
866+
ContactIds = namedtuple("ContactIds", "contact_id, tracking_id, slot_num")
867+
865868
def create_device(self):
866869
return test_multitouch.Digitizer(
867870
"DTH 2452",
868871
rdesc="05 0d 09 04 a1 01 85 0c 95 01 75 08 15 00 26 ff 00 81 03 09 54 81 02 09 22 a1 02 05 0d 95 01 75 01 25 01 09 42 81 02 81 03 09 47 81 02 95 05 81 03 09 51 26 ff 00 75 10 95 01 81 02 35 00 65 11 55 0e 05 01 09 30 26 a0 44 46 96 14 81 42 09 31 26 9a 26 46 95 0b 81 42 05 0d 75 08 95 01 15 00 09 48 26 5f 00 46 7c 14 81 02 09 49 25 35 46 7d 0b 81 02 45 00 65 00 55 00 c0 05 0d 09 22 a1 02 05 0d 95 01 75 01 25 01 09 42 81 02 81 03 09 47 81 02 95 05 81 03 09 51 26 ff 00 75 10 95 01 81 02 35 00 65 11 55 0e 05 01 09 30 26 a0 44 46 96 14 81 42 09 31 26 9a 26 46 95 0b 81 42 05 0d 75 08 95 01 15 00 09 48 26 5f 00 46 7c 14 81 02 09 49 25 35 46 7d 0b 81 02 45 00 65 00 55 00 c0 05 0d 09 22 a1 02 05 0d 95 01 75 01 25 01 09 42 81 02 81 03 09 47 81 02 95 05 81 03 09 51 26 ff 00 75 10 95 01 81 02 35 00 65 11 55 0e 05 01 09 30 26 a0 44 46 96 14 81 42 09 31 26 9a 26 46 95 0b 81 42 05 0d 75 08 95 01 15 00 09 48 26 5f 00 46 7c 14 81 02 09 49 25 35 46 7d 0b 81 02 45 00 65 00 55 00 c0 05 0d 09 22 a1 02 05 0d 95 01 75 01 25 01 09 42 81 02 81 03 09 47 81 02 95 05 81 03 09 51 26 ff 00 75 10 95 01 81 02 35 00 65 11 55 0e 05 01 09 30 26 a0 44 46 96 14 81 42 09 31 26 9a 26 46 95 0b 81 42 05 0d 75 08 95 01 15 00 09 48 26 5f 00 46 7c 14 81 02 09 49 25 35 46 7d 0b 81 02 45 00 65 00 55 00 c0 05 0d 09 22 a1 02 05 0d 95 01 75 01 25 01 09 42 81 02 81 03 09 47 81 02 95 05 81 03 09 51 26 ff 00 75 10 95 01 81 02 35 00 65 11 55 0e 05 01 09 30 26 a0 44 46 96 14 81 42 09 31 26 9a 26 46 95 0b 81 42 05 0d 75 08 95 01 15 00 09 48 26 5f 00 46 7c 14 81 02 09 49 25 35 46 7d 0b 81 02 45 00 65 00 55 00 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 75 08 95 0e 81 03 09 55 26 ff 00 75 08 b1 02 85 0a 06 00 ff 09 c5 96 00 01 b1 02 c0 06 00 ff 09 01 a1 01 09 01 85 13 15 00 26 ff 00 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0",
869872
input_info=(0x3, 0x056A, 0x0383),
870873
)
871874

875+
def make_contact(self, contact_id=0, t=0):
876+
"""
877+
Make a single touch contact that can move over time.
878+
879+
Creates a touch object that has a well-known position in space that
880+
does not overlap with other contacts. The value of `t` may be
881+
incremented over time to move the point along a linear path.
882+
"""
883+
x = 50 + 10 * contact_id + t
884+
y = 100 + 100 * contact_id + t
885+
return test_multitouch.Touch(contact_id, x, y)
886+
887+
def make_contacts(self, n, t=0):
888+
"""
889+
Make multiple touch contacts that can move over time.
890+
891+
Returns a list of `n` touch objects that are positioned at well-known
892+
locations. The value of `t` may be incremented over time to move the
893+
points along a linear path.
894+
"""
895+
return [ self.make_contact(id, t) for id in range(0, n) ]
896+
897+
def assert_contact(self, uhdev, evdev, contact_ids, t=0):
898+
"""
899+
Assert properties of a contact generated by make_contact.
900+
"""
901+
contact_id = contact_ids.contact_id
902+
tracking_id = contact_ids.tracking_id
903+
slot_num = contact_ids.slot_num
904+
905+
x = 50 + 10 * contact_id + t
906+
y = 100 + 100 * contact_id + t
907+
908+
# If the data isn't supposed to be stored in any slots, there is
909+
# nothing we can check for in the evdev stream.
910+
if slot_num is None:
911+
assert tracking_id == -1
912+
return
913+
914+
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == tracking_id
915+
if tracking_id != -1:
916+
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_X] == x
917+
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_Y] == y
918+
919+
def assert_contacts(self, uhdev, evdev, data, t=0):
920+
"""
921+
Assert properties of a list of contacts generated by make_contacts.
922+
"""
923+
for contact_ids in data:
924+
self.assert_contact(uhdev, evdev, contact_ids, t)
925+
872926
def test_contact_id_0(self):
873927
"""
874928
Bring a finger in contact with the tablet, then hold it down and remove it.
@@ -919,4 +973,226 @@ def test_confidence_false(self):
919973

920974
slot = self.get_slot(uhdev, t0, 0)
921975

922-
assert not events
976+
assert not events
977+
978+
def test_confidence_multitouch(self):
979+
"""
980+
Bring multiple fingers in contact with the tablet, some with the
981+
confidence bit set, and some without.
982+
983+
Ensure that all confident touches are reported and that all non-
984+
confident touches are ignored.
985+
"""
986+
uhdev = self.uhdev
987+
evdev = uhdev.get_evdev()
988+
989+
touches = self.make_contacts(5)
990+
touches[0].confidence = False
991+
touches[2].confidence = False
992+
touches[4].confidence = False
993+
994+
r = uhdev.event(touches)
995+
events = uhdev.next_sync_events()
996+
self.debug_reports(r, uhdev, events)
997+
998+
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
999+
1000+
self.assert_contacts(uhdev, evdev,
1001+
[ self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None),
1002+
self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0),
1003+
self.ContactIds(contact_id = 2, tracking_id = -1, slot_num = None),
1004+
self.ContactIds(contact_id = 3, tracking_id = 1, slot_num = 1),
1005+
self.ContactIds(contact_id = 4, tracking_id = -1, slot_num = None) ])
1006+
1007+
def confidence_change_assert_playback(self, uhdev, evdev, timeline):
1008+
"""
1009+
Assert proper behavior of contacts that move and change tipswitch /
1010+
confidence status over time.
1011+
1012+
Given a `timeline` list of touch states to iterate over, verify
1013+
that the contacts move and are reported as up/down as expected
1014+
by the state of the tipswitch and confidence bits.
1015+
"""
1016+
t = 0
1017+
1018+
for state in timeline:
1019+
touches = self.make_contacts(len(state), t)
1020+
1021+
for item in zip(touches, state):
1022+
item[0].tipswitch = item[1][1]
1023+
item[0].confidence = item[1][2]
1024+
1025+
r = uhdev.event(touches)
1026+
events = uhdev.next_sync_events()
1027+
self.debug_reports(r, uhdev, events)
1028+
1029+
ids = [ x[0] for x in state ]
1030+
self.assert_contacts(uhdev, evdev, ids, t)
1031+
1032+
t += 1
1033+
1034+
def test_confidence_loss_a(self):
1035+
"""
1036+
Transition a confident contact to a non-confident contact by
1037+
first clearing the tipswitch.
1038+
1039+
Ensure that the driver reports the transitioned contact as
1040+
being removed and that other contacts continue to report
1041+
normally. This mode of confidence loss is used by the
1042+
DTH-2452.
1043+
"""
1044+
uhdev = self.uhdev
1045+
evdev = uhdev.get_evdev()
1046+
1047+
self.confidence_change_assert_playback(uhdev, evdev, [
1048+
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
1049+
# Both fingers confidently in contact
1050+
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
1051+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1052+
1053+
# t=1: Contact 0 == !Down + confident; Contact 1 == Down + confident
1054+
# First finger looses confidence and clears only the tipswitch flag
1055+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True),
1056+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1057+
1058+
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1059+
# First finger has lost confidence and has both flags cleared
1060+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1061+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1062+
1063+
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1064+
# First finger has lost confidence and has both flags cleared
1065+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1066+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
1067+
])
1068+
1069+
def test_confidence_loss_b(self):
1070+
"""
1071+
Transition a confident contact to a non-confident contact by
1072+
cleraing both tipswitch and confidence bits simultaneously.
1073+
1074+
Ensure that the driver reports the transitioned contact as
1075+
being removed and that other contacts continue to report
1076+
normally. This mode of confidence loss is used by some
1077+
AES devices.
1078+
"""
1079+
uhdev = self.uhdev
1080+
evdev = uhdev.get_evdev()
1081+
1082+
self.confidence_change_assert_playback(uhdev, evdev, [
1083+
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
1084+
# Both fingers confidently in contact
1085+
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
1086+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1087+
1088+
# t=1: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1089+
# First finger looses confidence and has both flags cleared simultaneously
1090+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1091+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1092+
1093+
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1094+
# First finger has lost confidence and has both flags cleared
1095+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1096+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1097+
1098+
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1099+
# First finger has lost confidence and has both flags cleared
1100+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1101+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
1102+
])
1103+
1104+
def test_confidence_loss_c(self):
1105+
"""
1106+
Transition a confident contact to a non-confident contact by
1107+
clearing only the confidence bit.
1108+
1109+
Ensure that the driver reports the transitioned contact as
1110+
being removed and that other contacts continue to report
1111+
normally.
1112+
"""
1113+
uhdev = self.uhdev
1114+
evdev = uhdev.get_evdev()
1115+
1116+
self.confidence_change_assert_playback(uhdev, evdev, [
1117+
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
1118+
# Both fingers confidently in contact
1119+
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
1120+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1121+
1122+
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
1123+
# First finger looses confidence and clears only the confidence flag
1124+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False),
1125+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1126+
1127+
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1128+
# First finger has lost confidence and has both flags cleared
1129+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1130+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1131+
1132+
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
1133+
# First finger has lost confidence and has both flags cleared
1134+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
1135+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
1136+
])
1137+
1138+
def test_confidence_gain_a(self):
1139+
"""
1140+
Transition a contact that was always non-confident to confident.
1141+
1142+
Ensure that the confident contact is reported normally.
1143+
"""
1144+
uhdev = self.uhdev
1145+
evdev = uhdev.get_evdev()
1146+
1147+
self.confidence_change_assert_playback(uhdev, evdev, [
1148+
# t=0: Contact 0 == Down + !confident; Contact 1 == Down + confident
1149+
# Only second finger is confidently in contact
1150+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False),
1151+
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
1152+
1153+
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
1154+
# First finger gains confidence
1155+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False),
1156+
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
1157+
1158+
# t=2: Contact 0 == Down + confident; Contact 1 == Down + confident
1159+
# First finger remains confident
1160+
[(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True),
1161+
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
1162+
1163+
# t=3: Contact 0 == Down + confident; Contact 1 == Down + confident
1164+
# First finger remains confident
1165+
[(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True),
1166+
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)]
1167+
])
1168+
1169+
def test_confidence_gain_b(self):
1170+
"""
1171+
Transition a contact from non-confident to confident.
1172+
1173+
Ensure that the confident contact is reported normally.
1174+
"""
1175+
uhdev = self.uhdev
1176+
evdev = uhdev.get_evdev()
1177+
1178+
self.confidence_change_assert_playback(uhdev, evdev, [
1179+
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
1180+
# First and second finger confidently in contact
1181+
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
1182+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1183+
1184+
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
1185+
# Firtst finger looses confidence
1186+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False),
1187+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1188+
1189+
# t=2: Contact 0 == Down + confident; Contact 1 == Down + confident
1190+
# First finger gains confidence
1191+
[(self.ContactIds(contact_id = 0, tracking_id = 2, slot_num = 0), True, True),
1192+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
1193+
1194+
# t=3: Contact 0 == !Down + confident; Contact 1 == Down + confident
1195+
# First finger goes up
1196+
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True),
1197+
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
1198+
])

0 commit comments

Comments
 (0)