2 # SPDX-License-Identifier: GPL-2.0
3 # -*- coding: utf-8 -*-
5 # Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com>
6 # Copyright (c) 2021 Red Hat, Inc.
12 from hidtools.util import BusType
16 from typing import Dict, Optional, Tuple
18 logger = logging.getLogger("hidtools.test.tablet")
22 """Represents whether the BTN_TOUCH event is set to True or False"""
29 PEN = libevdev.EV_KEY.BTN_TOOL_PEN
30 RUBBER = libevdev.EV_KEY.BTN_TOOL_RUBBER
33 class BtnPressed(Enum):
34 """Represents whether a button is pressed on the stylus"""
36 PRIMARY_PRESSED = libevdev.EV_KEY.BTN_STYLUS
37 SECONDARY_PRESSED = libevdev.EV_KEY.BTN_STYLUS2
41 """Pen states according to Microsoft reference:
42 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
44 We extend it with the various buttons when we need to check them.
47 PEN_IS_OUT_OF_RANGE = BtnTouch.UP, None, None
48 PEN_IS_IN_RANGE = BtnTouch.UP, ToolType.PEN, None
49 PEN_IS_IN_RANGE_WITH_BUTTON = BtnTouch.UP, ToolType.PEN, BtnPressed.PRIMARY_PRESSED
50 PEN_IS_IN_RANGE_WITH_SECOND_BUTTON = (
53 BtnPressed.SECONDARY_PRESSED,
55 PEN_IS_IN_CONTACT = BtnTouch.DOWN, ToolType.PEN, None
56 PEN_IS_IN_CONTACT_WITH_BUTTON = (
59 BtnPressed.PRIMARY_PRESSED,
61 PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON = (
64 BtnPressed.SECONDARY_PRESSED,
66 PEN_IS_IN_RANGE_WITH_ERASING_INTENT = BtnTouch.UP, ToolType.RUBBER, None
67 PEN_IS_IN_RANGE_WITH_ERASING_INTENT_WITH_BUTTON = (
70 BtnPressed.PRIMARY_PRESSED,
72 PEN_IS_IN_RANGE_WITH_ERASING_INTENT_WITH_SECOND_BUTTON = (
75 BtnPressed.SECONDARY_PRESSED,
77 PEN_IS_ERASING = BtnTouch.DOWN, ToolType.RUBBER, None
78 PEN_IS_ERASING_WITH_BUTTON = (
81 BtnPressed.PRIMARY_PRESSED,
83 PEN_IS_ERASING_WITH_SECOND_BUTTON = (
86 BtnPressed.SECONDARY_PRESSED,
89 def __init__(self, touch: BtnTouch, tool: Optional[ToolType], button: Optional[BtnPressed]):
95 def from_evdev(cls, evdev) -> "PenState":
96 touch = BtnTouch(evdev.value[libevdev.EV_KEY.BTN_TOUCH])
100 evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER]
101 and not evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN]
103 tool = ToolType(libevdev.EV_KEY.BTN_TOOL_RUBBER)
105 evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN]
106 and not evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER]
108 tool = ToolType(libevdev.EV_KEY.BTN_TOOL_PEN)
110 evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN]
111 or evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER]
113 raise ValueError("2 tools are not allowed")
115 # we take only the highest button in account
116 for b in [libevdev.EV_KEY.BTN_STYLUS, libevdev.EV_KEY.BTN_STYLUS2]:
117 if bool(evdev.value[b]):
120 # the kernel tends to insert an EV_SYN once removing the tool, so
121 # the button will be released after
125 return cls((touch, tool, button))
127 def apply(self, events) -> "PenState":
128 if libevdev.EV_SYN.SYN_REPORT in events:
129 raise ValueError("EV_SYN is in the event sequence")
138 if ev == libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH):
140 raise ValueError(f"duplicated BTN_TOUCH in {events}")
142 touch = BtnTouch(ev.value)
144 libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN),
145 libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_RUBBER),
148 raise ValueError(f"duplicated BTN_TOOL_* in {events}")
150 tool = ToolType(ev.code) if ev.value else None
152 libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS),
153 libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS2),
156 raise ValueError(f"duplicated BTN_STYLUS* in {events}")
158 button = ev.code if ev.value else None
160 # the kernel tends to insert an EV_SYN once removing the tool, so
161 # the button will be released after
165 new_state = PenState((touch, tool, button))
167 new_state in self.valid_transitions()
168 ), f"moving from {self} to {new_state} is forbidden"
172 def valid_transitions(self) -> Tuple["PenState", ...]:
173 """Following the state machine in the URL above, with a couple of addition
174 for skipping the in-range state, due to historical reasons.
176 Note that those transitions are from the evdev point of view, not HID"""
177 if self == PenState.PEN_IS_OUT_OF_RANGE:
179 PenState.PEN_IS_OUT_OF_RANGE,
180 PenState.PEN_IS_IN_RANGE,
181 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
182 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
183 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
184 PenState.PEN_IS_IN_CONTACT,
185 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
186 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
187 PenState.PEN_IS_ERASING,
190 if self == PenState.PEN_IS_IN_RANGE:
192 PenState.PEN_IS_IN_RANGE,
193 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
194 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
195 PenState.PEN_IS_OUT_OF_RANGE,
196 PenState.PEN_IS_IN_CONTACT,
199 if self == PenState.PEN_IS_IN_CONTACT:
201 PenState.PEN_IS_IN_CONTACT,
202 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
203 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
204 PenState.PEN_IS_IN_RANGE,
205 PenState.PEN_IS_OUT_OF_RANGE,
208 if self == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT:
210 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
211 PenState.PEN_IS_OUT_OF_RANGE,
212 PenState.PEN_IS_ERASING,
215 if self == PenState.PEN_IS_ERASING:
217 PenState.PEN_IS_ERASING,
218 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
219 PenState.PEN_IS_OUT_OF_RANGE,
222 if self == PenState.PEN_IS_IN_RANGE_WITH_BUTTON:
224 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
225 PenState.PEN_IS_IN_RANGE,
226 PenState.PEN_IS_OUT_OF_RANGE,
227 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
230 if self == PenState.PEN_IS_IN_CONTACT_WITH_BUTTON:
232 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
233 PenState.PEN_IS_IN_CONTACT,
234 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
235 PenState.PEN_IS_OUT_OF_RANGE,
238 if self == PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON:
240 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
241 PenState.PEN_IS_IN_RANGE,
242 PenState.PEN_IS_OUT_OF_RANGE,
243 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
246 if self == PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON:
248 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
249 PenState.PEN_IS_IN_CONTACT,
250 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
251 PenState.PEN_IS_OUT_OF_RANGE,
257 def legal_transitions() -> Dict[str, Tuple["PenState", ...]]:
258 """This is the first half of the Windows Pen Implementation state machine:
259 we don't have Invert nor Erase bits, so just move in/out-of-range or proximity.
260 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
263 "in-range": (PenState.PEN_IS_IN_RANGE,),
264 "in-range -> out-of-range": (
265 PenState.PEN_IS_IN_RANGE,
266 PenState.PEN_IS_OUT_OF_RANGE,
268 "in-range -> touch": (PenState.PEN_IS_IN_RANGE, PenState.PEN_IS_IN_CONTACT),
269 "in-range -> touch -> release": (
270 PenState.PEN_IS_IN_RANGE,
271 PenState.PEN_IS_IN_CONTACT,
272 PenState.PEN_IS_IN_RANGE,
274 "in-range -> touch -> release -> out-of-range": (
275 PenState.PEN_IS_IN_RANGE,
276 PenState.PEN_IS_IN_CONTACT,
277 PenState.PEN_IS_IN_RANGE,
278 PenState.PEN_IS_OUT_OF_RANGE,
283 def legal_transitions_with_invert() -> Dict[str, Tuple["PenState", ...]]:
284 """This is the second half of the Windows Pen Implementation state machine:
285 we now have Invert and Erase bits, so move in/out or proximity with the intend
287 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
290 "hover-erasing": (PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,),
291 "hover-erasing -> out-of-range": (
292 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
293 PenState.PEN_IS_OUT_OF_RANGE,
295 "hover-erasing -> erase": (
296 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
297 PenState.PEN_IS_ERASING,
299 "hover-erasing -> erase -> release": (
300 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
301 PenState.PEN_IS_ERASING,
302 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
304 "hover-erasing -> erase -> release -> out-of-range": (
305 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
306 PenState.PEN_IS_ERASING,
307 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
308 PenState.PEN_IS_OUT_OF_RANGE,
310 "hover-erasing -> in-range": (
311 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
312 PenState.PEN_IS_IN_RANGE,
314 "in-range -> hover-erasing": (
315 PenState.PEN_IS_IN_RANGE,
316 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
321 def legal_transitions_with_primary_button() -> Dict[str, Tuple["PenState", ...]]:
322 """We revisit the Windows Pen Implementation state machine:
323 we now have a primary button.
326 "hover-button": (PenState.PEN_IS_IN_RANGE_WITH_BUTTON,),
327 "hover-button -> out-of-range": (
328 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
329 PenState.PEN_IS_OUT_OF_RANGE,
331 "in-range -> button-press": (
332 PenState.PEN_IS_IN_RANGE,
333 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
335 "in-range -> button-press -> button-release": (
336 PenState.PEN_IS_IN_RANGE,
337 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
338 PenState.PEN_IS_IN_RANGE,
340 "in-range -> touch -> button-press -> button-release": (
341 PenState.PEN_IS_IN_RANGE,
342 PenState.PEN_IS_IN_CONTACT,
343 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
344 PenState.PEN_IS_IN_CONTACT,
346 "in-range -> touch -> button-press -> release -> button-release": (
347 PenState.PEN_IS_IN_RANGE,
348 PenState.PEN_IS_IN_CONTACT,
349 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
350 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
351 PenState.PEN_IS_IN_RANGE,
353 "in-range -> button-press -> touch -> release -> button-release": (
354 PenState.PEN_IS_IN_RANGE,
355 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
356 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
357 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
358 PenState.PEN_IS_IN_RANGE,
360 "in-range -> button-press -> touch -> button-release -> release": (
361 PenState.PEN_IS_IN_RANGE,
362 PenState.PEN_IS_IN_RANGE_WITH_BUTTON,
363 PenState.PEN_IS_IN_CONTACT_WITH_BUTTON,
364 PenState.PEN_IS_IN_CONTACT,
365 PenState.PEN_IS_IN_RANGE,
370 def legal_transitions_with_secondary_button() -> Dict[str, Tuple["PenState", ...]]:
371 """We revisit the Windows Pen Implementation state machine:
372 we now have a secondary button.
373 Note: we don't looks for 2 buttons interactions.
376 "hover-button": (PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,),
377 "hover-button -> out-of-range": (
378 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
379 PenState.PEN_IS_OUT_OF_RANGE,
381 "in-range -> button-press": (
382 PenState.PEN_IS_IN_RANGE,
383 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
385 "in-range -> button-press -> button-release": (
386 PenState.PEN_IS_IN_RANGE,
387 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
388 PenState.PEN_IS_IN_RANGE,
390 "in-range -> touch -> button-press -> button-release": (
391 PenState.PEN_IS_IN_RANGE,
392 PenState.PEN_IS_IN_CONTACT,
393 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
394 PenState.PEN_IS_IN_CONTACT,
396 "in-range -> touch -> button-press -> release -> button-release": (
397 PenState.PEN_IS_IN_RANGE,
398 PenState.PEN_IS_IN_CONTACT,
399 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
400 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
401 PenState.PEN_IS_IN_RANGE,
403 "in-range -> button-press -> touch -> release -> button-release": (
404 PenState.PEN_IS_IN_RANGE,
405 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
406 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
407 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
408 PenState.PEN_IS_IN_RANGE,
410 "in-range -> button-press -> touch -> button-release -> release": (
411 PenState.PEN_IS_IN_RANGE,
412 PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON,
413 PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON,
414 PenState.PEN_IS_IN_CONTACT,
415 PenState.PEN_IS_IN_RANGE,
420 def tolerated_transitions() -> Dict[str, Tuple["PenState", ...]]:
421 """This is not adhering to the Windows Pen Implementation state machine
422 but we should expect the kernel to behave properly, mostly for historical
425 "direct-in-contact": (PenState.PEN_IS_IN_CONTACT,),
426 "direct-in-contact -> out-of-range": (
427 PenState.PEN_IS_IN_CONTACT,
428 PenState.PEN_IS_OUT_OF_RANGE,
433 def tolerated_transitions_with_invert() -> Dict[str, Tuple["PenState", ...]]:
434 """This is the second half of the Windows Pen Implementation state machine:
435 we now have Invert and Erase bits, so move in/out or proximity with the intend
437 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
440 "direct-erase": (PenState.PEN_IS_ERASING,),
441 "direct-erase -> out-of-range": (
442 PenState.PEN_IS_ERASING,
443 PenState.PEN_IS_OUT_OF_RANGE,
448 def broken_transitions() -> Dict[str, Tuple["PenState", ...]]:
449 """Those tests are definitely not part of the Windows specification.
450 However, a half broken device might export those transitions.
451 For example, a pen that has the eraser button might wobble between
452 touching and erasing if the tablet doesn't enforce the Windows
455 "in-range -> touch -> erase -> hover-erase": (
456 PenState.PEN_IS_IN_RANGE,
457 PenState.PEN_IS_IN_CONTACT,
458 PenState.PEN_IS_ERASING,
459 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
461 "in-range -> erase -> hover-erase": (
462 PenState.PEN_IS_IN_RANGE,
463 PenState.PEN_IS_ERASING,
464 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
466 "hover-erase -> erase -> touch -> in-range": (
467 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
468 PenState.PEN_IS_ERASING,
469 PenState.PEN_IS_IN_CONTACT,
470 PenState.PEN_IS_IN_RANGE,
472 "hover-erase -> touch -> in-range": (
473 PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,
474 PenState.PEN_IS_IN_CONTACT,
475 PenState.PEN_IS_IN_RANGE,
477 "touch -> erase -> touch -> erase": (
478 PenState.PEN_IS_IN_CONTACT,
479 PenState.PEN_IS_ERASING,
480 PenState.PEN_IS_IN_CONTACT,
481 PenState.PEN_IS_ERASING,
487 def __init__(self, x, y):
490 self.tipswitch = False
491 self.tippressure = 15
496 self.barrelswitch = False
497 self.secondarybarrelswitch = False
503 self._old_values = None
504 self.current_state = None
507 if self._old_values is not None:
519 setattr(self, i, getattr(self._old_values, i))
522 self._old_values = copy.copy(self)
524 def __assert_axis(self, evdev, axis, value):
526 axis == libevdev.EV_KEY.BTN_TOOL_RUBBER
527 and evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] is None
532 evdev.value[axis] == value
533 ), f"assert evdev.value[{axis}] ({evdev.value[axis]}) != {value}"
535 def assert_expected_input_events(self, evdev):
536 assert evdev.value[libevdev.EV_ABS.ABS_X] == self.x
537 assert evdev.value[libevdev.EV_ABS.ABS_Y] == self.y
538 assert self.current_state == PenState.from_evdev(evdev)
541 class PenDigitizer(base.UHIDTestDevice):
549 input_info=(BusType.USB, 1, 2),
550 evdev_name_suffix=None,
552 super().__init__(name, application, rdesc_str, rdesc, input_info)
553 self.physical = physical
554 self.cur_application = application
555 if evdev_name_suffix is not None:
556 self.name += evdev_name_suffix
559 for r in self.parsed_rdesc.input_reports.values():
560 if r.application_name == self.application:
561 physicals = [f.physical_name for f in r]
562 if self.physical not in physicals and None not in physicals:
564 self.fields = [f.usage_name for f in r]
566 def move_to(self, pen, state):
567 # fill in the previous values
568 if pen.current_state == PenState.PEN_IS_OUT_OF_RANGE:
571 print(f"\n *** pen is moving to {state} ***")
573 if state == PenState.PEN_IS_OUT_OF_RANGE:
577 pen.tipswitch = False
588 pen.barrelswitch = False
589 pen.secondarybarrelswitch = False
590 elif state == PenState.PEN_IS_IN_RANGE:
591 pen.tipswitch = False
595 pen.barrelswitch = False
596 pen.secondarybarrelswitch = False
597 elif state == PenState.PEN_IS_IN_CONTACT:
602 pen.barrelswitch = False
603 pen.secondarybarrelswitch = False
604 elif state == PenState.PEN_IS_IN_RANGE_WITH_BUTTON:
605 pen.tipswitch = False
609 pen.barrelswitch = True
610 pen.secondarybarrelswitch = False
611 elif state == PenState.PEN_IS_IN_CONTACT_WITH_BUTTON:
616 pen.barrelswitch = True
617 pen.secondarybarrelswitch = False
618 elif state == PenState.PEN_IS_IN_RANGE_WITH_SECOND_BUTTON:
619 pen.tipswitch = False
623 pen.barrelswitch = False
624 pen.secondarybarrelswitch = True
625 elif state == PenState.PEN_IS_IN_CONTACT_WITH_SECOND_BUTTON:
630 pen.barrelswitch = False
631 pen.secondarybarrelswitch = True
632 elif state == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT:
633 pen.tipswitch = False
637 pen.barrelswitch = False
638 pen.secondarybarrelswitch = False
639 elif state == PenState.PEN_IS_ERASING:
640 pen.tipswitch = False
644 pen.barrelswitch = False
645 pen.secondarybarrelswitch = False
647 pen.current_state = state
649 def event(self, pen):
651 r = self.create_report(application=self.cur_application, data=pen)
652 self.call_input_event(r)
656 def get_report(self, req, rnum, rtype):
657 if rtype != self.UHID_FEATURE_REPORT:
661 for v in self.parsed_rdesc.feature_reports.values():
662 if v.report_ID == rnum:
670 def set_report(self, req, rnum, rtype, data):
671 if rtype != self.UHID_FEATURE_REPORT:
675 for v in self.parsed_rdesc.feature_reports.values():
676 if v.report_ID == rnum:
686 class TestTablet(base.BaseTestCase.TestUhid):
687 def create_device(self):
688 raise Exception("please reimplement me in subclasses")
690 def post(self, uhdev, pen):
692 events = uhdev.next_sync_events()
693 self.debug_reports(r, uhdev, events)
696 def validate_transitions(self, from_state, pen, evdev, events):
697 # check that the final state is correct
698 pen.assert_expected_input_events(evdev)
700 # check that the transitions are valid
702 while libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) in events:
703 # split the first EV_SYN from the list
704 idx = events.index(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT))
705 sync_events = events[:idx]
706 events = events[idx + 1 :]
708 # now check for a valid transition
709 from_state = from_state.apply(sync_events)
712 from_state = from_state.apply(sync_events)
714 def _test_states(self, state_list, scribble):
715 """Internal method to test against a list of
716 transition between states.
717 state_list is a list of PenState objects
718 scribble is a boolean which tells if we need
719 to wobble a little the X,Y coordinates of the pen
720 between each state transition."""
722 evdev = uhdev.get_evdev()
724 cur_state = PenState.PEN_IS_OUT_OF_RANGE
727 uhdev.move_to(p, PenState.PEN_IS_OUT_OF_RANGE)
728 events = self.post(uhdev, p)
729 self.validate_transitions(cur_state, p, evdev, events)
731 cur_state = p.current_state
733 for state in state_list:
734 if scribble and cur_state != PenState.PEN_IS_OUT_OF_RANGE:
737 events = self.post(uhdev, p)
738 self.validate_transitions(cur_state, p, evdev, events)
739 assert len(events) >= 3 # X, Y, SYN
740 uhdev.move_to(p, state)
741 if scribble and state != PenState.PEN_IS_OUT_OF_RANGE:
744 events = self.post(uhdev, p)
745 self.validate_transitions(cur_state, p, evdev, events)
746 cur_state = p.current_state
748 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
749 @pytest.mark.parametrize(
751 [pytest.param(v, id=k) for k, v in PenState.legal_transitions().items()],
753 def test_valid_pen_states(self, state_list, scribble):
754 """This is the first half of the Windows Pen Implementation state machine:
755 we don't have Invert nor Erase bits, so just move in/out-of-range or proximity.
756 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
758 self._test_states(state_list, scribble)
760 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
761 @pytest.mark.parametrize(
764 pytest.param(v, id=k)
765 for k, v in PenState.tolerated_transitions().items()
768 def test_tolerated_pen_states(self, state_list, scribble):
769 """This is not adhering to the Windows Pen Implementation state machine
770 but we should expect the kernel to behave properly, mostly for historical
772 self._test_states(state_list, scribble)
774 @pytest.mark.skip_if_uhdev(
775 lambda uhdev: "Barrel Switch" not in uhdev.fields,
776 "Device not compatible, missing Barrel Switch usage",
778 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
779 @pytest.mark.parametrize(
782 pytest.param(v, id=k)
783 for k, v in PenState.legal_transitions_with_primary_button().items()
786 def test_valid_primary_button_pen_states(self, state_list, scribble):
787 """Rework the transition state machine by adding the primary button."""
788 self._test_states(state_list, scribble)
790 @pytest.mark.skip_if_uhdev(
791 lambda uhdev: "Secondary Barrel Switch" not in uhdev.fields,
792 "Device not compatible, missing Secondary Barrel Switch usage",
794 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
795 @pytest.mark.parametrize(
798 pytest.param(v, id=k)
799 for k, v in PenState.legal_transitions_with_secondary_button().items()
802 def test_valid_secondary_button_pen_states(self, state_list, scribble):
803 """Rework the transition state machine by adding the secondary button."""
804 self._test_states(state_list, scribble)
806 @pytest.mark.skip_if_uhdev(
807 lambda uhdev: "Invert" not in uhdev.fields,
808 "Device not compatible, missing Invert usage",
810 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
811 @pytest.mark.parametrize(
814 pytest.param(v, id=k)
815 for k, v in PenState.legal_transitions_with_invert().items()
818 def test_valid_invert_pen_states(self, state_list, scribble):
819 """This is the second half of the Windows Pen Implementation state machine:
820 we now have Invert and Erase bits, so move in/out or proximity with the intend
822 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
824 self._test_states(state_list, scribble)
826 @pytest.mark.skip_if_uhdev(
827 lambda uhdev: "Invert" not in uhdev.fields,
828 "Device not compatible, missing Invert usage",
830 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
831 @pytest.mark.parametrize(
834 pytest.param(v, id=k)
835 for k, v in PenState.tolerated_transitions_with_invert().items()
838 def test_tolerated_invert_pen_states(self, state_list, scribble):
839 """This is the second half of the Windows Pen Implementation state machine:
840 we now have Invert and Erase bits, so move in/out or proximity with the intend
842 https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states
844 self._test_states(state_list, scribble)
846 @pytest.mark.skip_if_uhdev(
847 lambda uhdev: "Invert" not in uhdev.fields,
848 "Device not compatible, missing Invert usage",
850 @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"])
851 @pytest.mark.parametrize(
853 [pytest.param(v, id=k) for k, v in PenState.broken_transitions().items()],
855 def test_tolerated_broken_pen_states(self, state_list, scribble):
856 """Those tests are definitely not part of the Windows specification.
857 However, a half broken device might export those transitions.
858 For example, a pen that has the eraser button might wobble between
859 touching and erasing if the tablet doesn't enforce the Windows
861 self._test_states(state_list, scribble)
864 class GXTP_pen(PenDigitizer):
865 def event(self, pen):
866 if not hasattr(self, "prev_tip_state"):
867 self.prev_tip_state = False
869 internal_pen = copy.copy(pen)
871 # bug in the controller: when the pen touches the
872 # surface, in-range stays to 1, but when
873 # the pen moves in-range gets reverted to 0
874 if pen.tipswitch and self.prev_tip_state:
875 internal_pen.inrange = False
877 self.prev_tip_state = pen.tipswitch
879 # another bug in the controller: when the pen is
880 # inverted, invert is set to 1, but as soon as
881 # the pen touches the surface, eraser is correctly
882 # set to 1 but invert is released
884 internal_pen.invert = False
886 return super().event(internal_pen)
889 class USIPen(PenDigitizer):
893 ################################################################################
895 # Windows 7 compatible devices
897 ################################################################################
898 # class TestEgalax_capacitive_0eef_7224(BaseTest.TestTablet):
899 # def create_device(self):
900 # return PenDigitizer('uhid test egalax-capacitive_0eef_7224',
901 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
902 # input_info=(BusType.USB, 0x0eef, 0x7224),
903 # evdev_name_suffix=' Touchscreen')
906 # class TestEgalax_capacitive_0eef_72fa(BaseTest.TestTablet):
907 # def create_device(self):
908 # return PenDigitizer('uhid test egalax-capacitive_0eef_72fa',
909 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 72 22 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 87 13 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 72 22 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 87 13 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
910 # input_info=(BusType.USB, 0x0eef, 0x72fa),
911 # evdev_name_suffix=' Touchscreen')
914 # class TestEgalax_capacitive_0eef_7336(BaseTest.TestTablet):
915 # def create_device(self):
916 # return PenDigitizer('uhid test egalax-capacitive_0eef_7336',
917 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 c1 20 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c2 18 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 c1 20 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c2 18 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
918 # input_info=(BusType.USB, 0x0eef, 0x7336),
919 # evdev_name_suffix=' Touchscreen')
922 # class TestEgalax_capacitive_0eef_7337(BaseTest.TestTablet):
923 # def create_device(self):
924 # return PenDigitizer('uhid test egalax-capacitive_0eef_7337',
925 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 ae 17 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c3 0e 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 ae 17 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c3 0e 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
926 # input_info=(BusType.USB, 0x0eef, 0x7337),
927 # evdev_name_suffix=' Touchscreen')
930 # class TestEgalax_capacitive_0eef_7349(BaseTest.TestTablet):
931 # def create_device(self):
932 # return PenDigitizer('uhid test egalax-capacitive_0eef_7349',
933 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
934 # input_info=(BusType.USB, 0x0eef, 0x7349),
935 # evdev_name_suffix=' Touchscreen')
938 # class TestEgalax_capacitive_0eef_73f4(BaseTest.TestTablet):
939 # def create_device(self):
940 # return PenDigitizer('uhid test egalax-capacitive_0eef_73f4',
941 # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 96 4e 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 23 2c 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 96 4e 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 23 2c 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0',
942 # input_info=(BusType.USB, 0x0eef, 0x73f4),
943 # evdev_name_suffix=' Touchscreen')
945 # bogus: BTN_TOOL_PEN is not emitted
946 # class TestIrtouch_6615_0070(BaseTest.TestTablet):
947 # def create_device(self):
948 # return PenDigitizer('uhid test irtouch_6615_0070',
949 # rdesc='05 01 09 02 a1 01 85 10 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 09 30 09 31 15 00 26 ff 7f 75 10 95 02 81 02 c0 c0 05 0d 09 04 a1 01 85 30 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 05 0d 09 54 15 00 26 02 00 75 08 95 01 81 02 85 03 09 55 15 00 26 ff 00 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 02 09 52 09 53 15 00 26 ff 00 75 08 95 02 b1 02 c0 05 0d 09 02 a1 01 85 20 09 20 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 85 01 06 00 ff 09 01 75 08 95 01 b1 02 c0 c0',
950 # input_info=(BusType.USB, 0x6615, 0x0070))
953 class TestNexio_1870_0100(BaseTest.TestTablet):
954 def create_device(self):
956 "uhid test nexio_1870_0100",
957 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 02 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 40 81 00 19 01 29 40 91 00 c0",
958 input_info=(BusType.USB, 0x1870, 0x0100),
962 class TestNexio_1870_010d(BaseTest.TestTablet):
963 def create_device(self):
965 "uhid test nexio_1870_010d",
966 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0",
967 input_info=(BusType.USB, 0x1870, 0x010D),
971 class TestNexio_1870_0119(BaseTest.TestTablet):
972 def create_device(self):
974 "uhid test nexio_1870_0119",
975 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0",
976 input_info=(BusType.USB, 0x1870, 0x0119),
980 ################################################################################
982 # Windows 8 compatible devices
984 ################################################################################
986 # bogus: application is 'undefined'
987 # class Testatmel_03eb_8409(BaseTest.TestTablet):
988 # def create_device(self):
989 # return PenDigitizer('uhid test atmel_03eb_8409', rdesc='05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 00 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 46 18 06 26 77 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0')
992 class Testatmel_03eb_840b(BaseTest.TestTablet):
993 def create_device(self):
995 "uhid test atmel_03eb_840b",
996 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 00 0a 26 ff 0f 09 30 81 02 46 a0 05 26 ff 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0",
1000 class Testn_trig_1b96_0c01(BaseTest.TestTablet):
1001 def create_device(self):
1002 return PenDigitizer(
1003 "uhid test n_trig_1b96_0c01",
1004 rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0",
1008 class Testn_trig_1b96_0c03(BaseTest.TestTablet):
1009 def create_device(self):
1010 return PenDigitizer(
1011 "uhid test n_trig_1b96_0c03",
1012 rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0",
1016 class Testn_trig_1b96_0f00(BaseTest.TestTablet):
1017 def create_device(self):
1018 return PenDigitizer(
1019 "uhid test n_trig_1b96_0f00",
1020 rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0",
1024 class Testn_trig_1b96_0f04(BaseTest.TestTablet):
1025 def create_device(self):
1026 return PenDigitizer(
1027 "uhid test n_trig_1b96_0f04",
1028 rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0",
1032 class Testn_trig_1b96_1000(BaseTest.TestTablet):
1033 def create_device(self):
1034 return PenDigitizer(
1035 "uhid test n_trig_1b96_1000",
1036 rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0",
1040 class TestGXTP_27c6_0113(BaseTest.TestTablet):
1041 def create_device(self):
1043 "uhid test GXTP_27c6_0113",
1044 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 55 0e 65 11 35 00 15 00 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 01 75 08 09 51 95 01 81 02 05 01 26 00 14 75 10 55 0e 65 11 09 30 35 00 46 1f 07 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 01 75 08 09 51 95 01 81 02 05 01 26 00 14 75 10 55 0e 65 11 09 30 35 00 46 1f 07 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 54 15 00 25 7f 75 08 95 01 81 02 85 02 09 55 95 01 25 0a b1 02 85 03 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 85 08 09 20 a1 00 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 04 81 02 95 01 81 03 09 32 81 02 95 02 81 03 95 01 75 08 09 51 81 02 05 01 09 30 75 10 95 01 a4 55 0e 65 11 35 00 26 00 14 46 1f 07 81 42 09 31 26 80 0c 46 77 04 81 42 b4 05 0d 09 30 26 ff 0f 81 02 09 3d 65 14 55 0e 36 d8 dc 46 28 23 16 d8 dc 26 28 23 81 02 09 3e 81 02 c0 c0 06 f0 ff 09 01 a1 01 85 0e 09 01 15 00 25 ff 75 08 95 40 91 02 09 01 15 00 25 ff 75 08 95 40 81 02 c0 05 01 09 06 a1 01 85 04 05 07 09 e3 15 00 25 01 75 01 95 01 81 02 95 07 81 03 c0",
1048 ################################################################################
1050 # Windows 8 compatible devices with USI Pen
1052 ################################################################################
1055 class TestElan_04f3_2A49(BaseTest.TestTablet):
1056 def create_device(self):
1058 "uhid test Elan_04f3_2A49",
1059 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 54 25 7f 96 01 00 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 16 00 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 16 00 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 20 09 01 91 02 c0 06 00 ff 09 01 a1 01 85 06 09 03 75 08 95 12 91 02 09 04 75 08 95 03 b1 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0 05 0d 09 02 a1 01 85 07 35 00 09 20 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0f 65 11 46 26 01 26 1c 48 81 42 09 31 46 a6 00 26 bc 2f 81 42 b4 05 0d 09 30 26 00 10 81 02 75 08 95 01 09 3b 25 64 81 42 09 38 15 00 25 02 81 02 09 5c 26 ff 00 81 02 09 5e 81 02 09 70 a1 02 15 01 25 06 09 72 09 73 09 74 09 75 09 76 09 77 81 20 09 5b 25 ff 75 40 81 02 c0 06 00 ff 75 08 95 02 09 01 81 02 c0 05 0d 85 60 09 81 a1 02 09 38 75 08 95 01 15 00 25 02 81 02 09 81 15 01 25 04 09 82 09 83 09 84 09 85 81 20 c0 85 61 09 5c a1 02 15 00 26 ff 00 75 08 95 01 09 38 b1 02 09 5c 26 ff 00 b1 02 09 5d 75 01 95 01 25 01 b1 02 95 07 b1 03 c0 85 62 09 5e a1 02 09 38 15 00 25 02 75 08 95 01 b1 02 09 5e 26 ff 00 b1 02 09 5f 75 01 25 01 b1 02 75 07 b1 03 c0 85 63 09 70 a1 02 75 08 95 01 15 00 25 02 09 38 b1 02 09 70 a1 02 25 06 09 72 09 73 09 74 09 75 09 76 09 77 b1 20 c0 09 71 75 01 25 01 b1 02 75 07 b1 03 c0 85 64 09 80 15 00 25 ff 75 40 95 01 b1 02 85 65 09 44 a1 02 09 38 75 08 95 01 25 02 b1 02 15 01 25 03 09 44 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 5a a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 45 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 c0 85 66 75 08 95 01 05 0d 09 90 a1 02 09 38 25 02 b1 02 09 91 75 10 26 ff 0f b1 02 09 92 75 40 25 ff b1 02 05 06 09 2a 75 08 26 ff 00 a1 02 09 2d b1 02 09 2e b1 02 c0 c0 85 67 05 06 09 2b a1 02 05 0d 25 02 09 38 b1 02 05 06 09 2b a1 02 09 2d 26 ff 00 b1 02 09 2e b1 02 c0 c0 85 68 06 00 ff 09 01 a1 02 05 0d 09 38 75 08 95 01 25 02 b1 02 06 00 ff 09 01 75 10 27 ff ff 00 00 b1 02 c0 85 69 05 0d 09 38 75 08 95 01 15 00 25 02 b1 02 c0 06 00 ff 09 81 a1 01 85 17 75 08 95 1f 09 05 81 02 c0",
1060 input_info=(BusType.I2C, 0x04F3, 0x2A49),
1064 class TestGoodix_27c6_0e00(BaseTest.TestTablet):
1065 def create_device(self):
1067 "uhid test Elan_04f3_2A49",
1068 rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 55 0e 65 11 35 00 15 00 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 75 08 09 51 95 01 81 02 05 01 26 04 20 75 10 55 0e 65 11 09 30 35 00 46 e6 09 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 75 08 09 51 95 01 81 02 05 01 26 04 20 75 10 55 0e 65 11 09 30 35 00 46 e6 09 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 54 15 00 25 7f 75 08 95 01 81 02 85 02 09 55 95 01 25 0a b1 02 85 03 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 09 20 a1 00 85 08 05 01 a4 09 30 35 00 46 e6 09 15 00 26 04 20 55 0d 65 13 75 10 95 01 81 02 09 31 46 9a 06 26 60 15 81 02 b4 05 0d 09 38 95 01 75 08 15 00 25 01 81 02 09 30 75 10 26 ff 0f 81 02 09 31 81 02 09 42 09 44 09 5a 09 3c 09 45 09 32 75 01 95 06 25 01 81 02 95 02 81 03 09 3d 55 0e 65 14 36 d8 dc 46 28 23 16 d8 dc 26 28 23 95 01 75 10 81 02 09 3e 81 02 09 41 15 00 27 a0 8c 00 00 35 00 47 a0 8c 00 00 81 02 05 20 0a 53 04 65 00 16 01 f8 26 ff 07 75 10 95 01 81 02 0a 54 04 81 02 0a 55 04 81 02 0a 57 04 81 02 0a 58 04 81 02 0a 59 04 81 02 0a 72 04 81 02 0a 73 04 81 02 0a 74 04 81 02 05 0d 09 3b 15 00 25 64 75 08 81 02 09 5b 25 ff 75 40 81 02 06 00 ff 09 5b 75 20 81 02 05 0d 09 5c 26 ff 00 75 08 81 02 09 5e 81 02 09 70 a1 02 15 01 25 06 09 72 09 73 09 74 09 75 09 76 09 77 81 20 c0 06 00 ff 09 01 15 00 27 ff ff 00 00 75 10 95 01 81 02 85 09 09 81 a1 02 09 81 15 01 25 04 09 82 09 83 09 84 09 85 81 20 c0 85 10 09 5c a1 02 15 00 25 01 75 08 95 01 09 38 b1 02 09 5c 26 ff 00 b1 02 09 5d 75 01 95 01 25 01 b1 02 95 07 b1 03 c0 85 11 09 5e a1 02 09 38 15 00 25 01 75 08 95 01 b1 02 09 5e 26 ff 00 b1 02 09 5f 75 01 25 01 b1 02 75 07 b1 03 c0 85 12 09 70 a1 02 75 08 95 01 15 00 25 01 09 38 b1 02 09 70 a1 02 25 06 09 72 09 73 09 74 09 75 09 76 09 77 b1 20 c0 09 71 75 01 25 01 b1 02 75 07 b1 03 c0 85 13 09 80 15 00 25 ff 75 40 95 01 b1 02 85 14 09 44 a1 02 09 38 75 08 95 01 25 01 b1 02 15 01 25 03 09 44 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 5a a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 45 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 c0 85 15 75 08 95 01 05 0d 09 90 a1 02 09 38 25 01 b1 02 09 91 75 10 26 ff 0f b1 02 09 92 75 40 25 ff b1 02 05 06 09 2a 75 08 26 ff 00 a1 02 09 2d b1 02 09 2e b1 02 c0 c0 85 16 05 06 09 2b a1 02 05 0d 25 01 09 38 b1 02 05 06 09 2b a1 02 09 2d 26 ff 00 b1 02 09 2e b1 02 c0 c0 85 17 06 00 ff 09 01 a1 02 05 0d 09 38 75 08 95 01 25 01 b1 02 06 00 ff 09 01 75 10 27 ff ff 00 00 b1 02 c0 85 18 05 0d 09 38 75 08 95 01 15 00 25 01 b1 02 c0 c0 06 f0 ff 09 01 a1 01 85 0e 09 01 15 00 25 ff 75 08 95 40 91 02 09 01 15 00 25 ff 75 08 95 40 81 02 c0",
1069 input_info=(BusType.I2C, 0x27C6, 0x0E00),