|
|
|
@@ -27,6 +27,7 @@ from .descriptors_wacom import (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
import attr
|
|
|
|
|
from collections import namedtuple
|
|
|
|
|
from enum import Enum
|
|
|
|
|
from hidtools.hut import HUT
|
|
|
|
|
from hidtools.hid import HidUnit
|
|
|
|
@@ -862,6 +863,8 @@ class TestPTHX60_Pen(TestOpaqueCTLTablet):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest):
|
|
|
|
|
ContactIds = namedtuple("ContactIds", "contact_id, tracking_id, slot_num")
|
|
|
|
|
|
|
|
|
|
def create_device(self):
|
|
|
|
|
return test_multitouch.Digitizer(
|
|
|
|
|
"DTH 2452",
|
|
|
|
@@ -869,6 +872,57 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|
|
|
|
input_info=(0x3, 0x056A, 0x0383),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def make_contact(self, contact_id=0, t=0):
|
|
|
|
|
"""
|
|
|
|
|
Make a single touch contact that can move over time.
|
|
|
|
|
|
|
|
|
|
Creates a touch object that has a well-known position in space that
|
|
|
|
|
does not overlap with other contacts. The value of `t` may be
|
|
|
|
|
incremented over time to move the point along a linear path.
|
|
|
|
|
"""
|
|
|
|
|
x = 50 + 10 * contact_id + t
|
|
|
|
|
y = 100 + 100 * contact_id + t
|
|
|
|
|
return test_multitouch.Touch(contact_id, x, y)
|
|
|
|
|
|
|
|
|
|
def make_contacts(self, n, t=0):
|
|
|
|
|
"""
|
|
|
|
|
Make multiple touch contacts that can move over time.
|
|
|
|
|
|
|
|
|
|
Returns a list of `n` touch objects that are positioned at well-known
|
|
|
|
|
locations. The value of `t` may be incremented over time to move the
|
|
|
|
|
points along a linear path.
|
|
|
|
|
"""
|
|
|
|
|
return [ self.make_contact(id, t) for id in range(0, n) ]
|
|
|
|
|
|
|
|
|
|
def assert_contact(self, uhdev, evdev, contact_ids, t=0):
|
|
|
|
|
"""
|
|
|
|
|
Assert properties of a contact generated by make_contact.
|
|
|
|
|
"""
|
|
|
|
|
contact_id = contact_ids.contact_id
|
|
|
|
|
tracking_id = contact_ids.tracking_id
|
|
|
|
|
slot_num = contact_ids.slot_num
|
|
|
|
|
|
|
|
|
|
x = 50 + 10 * contact_id + t
|
|
|
|
|
y = 100 + 100 * contact_id + t
|
|
|
|
|
|
|
|
|
|
# If the data isn't supposed to be stored in any slots, there is
|
|
|
|
|
# nothing we can check for in the evdev stream.
|
|
|
|
|
if slot_num is None:
|
|
|
|
|
assert tracking_id == -1
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == tracking_id
|
|
|
|
|
if tracking_id != -1:
|
|
|
|
|
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_X] == x
|
|
|
|
|
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_Y] == y
|
|
|
|
|
|
|
|
|
|
def assert_contacts(self, uhdev, evdev, data, t=0):
|
|
|
|
|
"""
|
|
|
|
|
Assert properties of a list of contacts generated by make_contacts.
|
|
|
|
|
"""
|
|
|
|
|
for contact_ids in data:
|
|
|
|
|
self.assert_contact(uhdev, evdev, contact_ids, t)
|
|
|
|
|
|
|
|
|
|
def test_contact_id_0(self):
|
|
|
|
|
"""
|
|
|
|
|
Bring a finger in contact with the tablet, then hold it down and remove it.
|
|
|
|
@@ -920,3 +974,225 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|
|
|
|
_slot = self.get_slot(uhdev, t0, 0)
|
|
|
|
|
|
|
|
|
|
assert not events
|
|
|
|
|
|
|
|
|
|
def test_confidence_multitouch(self):
|
|
|
|
|
"""
|
|
|
|
|
Bring multiple fingers in contact with the tablet, some with the
|
|
|
|
|
confidence bit set, and some without.
|
|
|
|
|
|
|
|
|
|
Ensure that all confident touches are reported and that all non-
|
|
|
|
|
confident touches are ignored.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
touches = self.make_contacts(5)
|
|
|
|
|
touches[0].confidence = False
|
|
|
|
|
touches[2].confidence = False
|
|
|
|
|
touches[4].confidence = False
|
|
|
|
|
|
|
|
|
|
r = uhdev.event(touches)
|
|
|
|
|
events = uhdev.next_sync_events()
|
|
|
|
|
self.debug_reports(r, uhdev, events)
|
|
|
|
|
|
|
|
|
|
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
|
|
|
|
|
|
|
|
|
|
self.assert_contacts(uhdev, evdev,
|
|
|
|
|
[ self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None),
|
|
|
|
|
self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0),
|
|
|
|
|
self.ContactIds(contact_id = 2, tracking_id = -1, slot_num = None),
|
|
|
|
|
self.ContactIds(contact_id = 3, tracking_id = 1, slot_num = 1),
|
|
|
|
|
self.ContactIds(contact_id = 4, tracking_id = -1, slot_num = None) ])
|
|
|
|
|
|
|
|
|
|
def confidence_change_assert_playback(self, uhdev, evdev, timeline):
|
|
|
|
|
"""
|
|
|
|
|
Assert proper behavior of contacts that move and change tipswitch /
|
|
|
|
|
confidence status over time.
|
|
|
|
|
|
|
|
|
|
Given a `timeline` list of touch states to iterate over, verify
|
|
|
|
|
that the contacts move and are reported as up/down as expected
|
|
|
|
|
by the state of the tipswitch and confidence bits.
|
|
|
|
|
"""
|
|
|
|
|
t = 0
|
|
|
|
|
|
|
|
|
|
for state in timeline:
|
|
|
|
|
touches = self.make_contacts(len(state), t)
|
|
|
|
|
|
|
|
|
|
for item in zip(touches, state):
|
|
|
|
|
item[0].tipswitch = item[1][1]
|
|
|
|
|
item[0].confidence = item[1][2]
|
|
|
|
|
|
|
|
|
|
r = uhdev.event(touches)
|
|
|
|
|
events = uhdev.next_sync_events()
|
|
|
|
|
self.debug_reports(r, uhdev, events)
|
|
|
|
|
|
|
|
|
|
ids = [ x[0] for x in state ]
|
|
|
|
|
self.assert_contacts(uhdev, evdev, ids, t)
|
|
|
|
|
|
|
|
|
|
t += 1
|
|
|
|
|
|
|
|
|
|
def test_confidence_loss_a(self):
|
|
|
|
|
"""
|
|
|
|
|
Transition a confident contact to a non-confident contact by
|
|
|
|
|
first clearing the tipswitch.
|
|
|
|
|
|
|
|
|
|
Ensure that the driver reports the transitioned contact as
|
|
|
|
|
being removed and that other contacts continue to report
|
|
|
|
|
normally. This mode of confidence loss is used by the
|
|
|
|
|
DTH-2452.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
self.confidence_change_assert_playback(uhdev, evdev, [
|
|
|
|
|
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# Both fingers confidently in contact
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=1: Contact 0 == !Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger looses confidence and clears only the tipswitch flag
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def test_confidence_loss_b(self):
|
|
|
|
|
"""
|
|
|
|
|
Transition a confident contact to a non-confident contact by
|
|
|
|
|
cleraing both tipswitch and confidence bits simultaneously.
|
|
|
|
|
|
|
|
|
|
Ensure that the driver reports the transitioned contact as
|
|
|
|
|
being removed and that other contacts continue to report
|
|
|
|
|
normally. This mode of confidence loss is used by some
|
|
|
|
|
AES devices.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
self.confidence_change_assert_playback(uhdev, evdev, [
|
|
|
|
|
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# Both fingers confidently in contact
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=1: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger looses confidence and has both flags cleared simultaneously
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def test_confidence_loss_c(self):
|
|
|
|
|
"""
|
|
|
|
|
Transition a confident contact to a non-confident contact by
|
|
|
|
|
clearing only the confidence bit.
|
|
|
|
|
|
|
|
|
|
Ensure that the driver reports the transitioned contact as
|
|
|
|
|
being removed and that other contacts continue to report
|
|
|
|
|
normally.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
self.confidence_change_assert_playback(uhdev, evdev, [
|
|
|
|
|
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# Both fingers confidently in contact
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger looses confidence and clears only the confidence flag
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger has lost confidence and has both flags cleared
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def test_confidence_gain_a(self):
|
|
|
|
|
"""
|
|
|
|
|
Transition a contact that was always non-confident to confident.
|
|
|
|
|
|
|
|
|
|
Ensure that the confident contact is reported normally.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
self.confidence_change_assert_playback(uhdev, evdev, [
|
|
|
|
|
# t=0: Contact 0 == Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# Only second finger is confidently in contact
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger gains confidence
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=2: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger remains confident
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=3: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger remains confident
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)]
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def test_confidence_gain_b(self):
|
|
|
|
|
"""
|
|
|
|
|
Transition a contact from non-confident to confident.
|
|
|
|
|
|
|
|
|
|
Ensure that the confident contact is reported normally.
|
|
|
|
|
"""
|
|
|
|
|
uhdev = self.uhdev
|
|
|
|
|
evdev = uhdev.get_evdev()
|
|
|
|
|
|
|
|
|
|
self.confidence_change_assert_playback(uhdev, evdev, [
|
|
|
|
|
# t=0: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First and second finger confidently in contact
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident
|
|
|
|
|
# Firtst finger looses confidence
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=2: Contact 0 == Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger gains confidence
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = 2, slot_num = 0), True, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)],
|
|
|
|
|
|
|
|
|
|
# t=3: Contact 0 == !Down + confident; Contact 1 == Down + confident
|
|
|
|
|
# First finger goes up
|
|
|
|
|
[(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True),
|
|
|
|
|
(self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)]
|
|
|
|
|
])
|
|
|
|
|