1*0bb3ed71SBenjamin Tissoires#!/bin/env python3 2*0bb3ed71SBenjamin Tissoires# SPDX-License-Identifier: GPL-2.0 3*0bb3ed71SBenjamin Tissoires# -*- coding: utf-8 -*- 4*0bb3ed71SBenjamin Tissoires# 5*0bb3ed71SBenjamin Tissoires# Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6*0bb3ed71SBenjamin Tissoires# Copyright (c) 2021 Red Hat, Inc. 7*0bb3ed71SBenjamin Tissoires# 8*0bb3ed71SBenjamin Tissoires 9*0bb3ed71SBenjamin Tissoiresfrom . import base 10*0bb3ed71SBenjamin Tissoiresimport copy 11*0bb3ed71SBenjamin Tissoiresfrom enum import Enum 12*0bb3ed71SBenjamin Tissoiresfrom hidtools.util import BusType 13*0bb3ed71SBenjamin Tissoiresimport libevdev 14*0bb3ed71SBenjamin Tissoiresimport logging 15*0bb3ed71SBenjamin Tissoiresimport pytest 16*0bb3ed71SBenjamin Tissoiresfrom typing import Dict, Tuple 17*0bb3ed71SBenjamin Tissoires 18*0bb3ed71SBenjamin Tissoireslogger = logging.getLogger("hidtools.test.tablet") 19*0bb3ed71SBenjamin Tissoires 20*0bb3ed71SBenjamin Tissoires 21*0bb3ed71SBenjamin Tissoiresclass PenState(Enum): 22*0bb3ed71SBenjamin Tissoires """Pen states according to Microsoft reference: 23*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 24*0bb3ed71SBenjamin Tissoires """ 25*0bb3ed71SBenjamin Tissoires 26*0bb3ed71SBenjamin Tissoires PEN_IS_OUT_OF_RANGE = (False, None) 27*0bb3ed71SBenjamin Tissoires PEN_IS_IN_RANGE = (False, libevdev.EV_KEY.BTN_TOOL_PEN) 28*0bb3ed71SBenjamin Tissoires PEN_IS_IN_CONTACT = (True, libevdev.EV_KEY.BTN_TOOL_PEN) 29*0bb3ed71SBenjamin Tissoires PEN_IS_IN_RANGE_WITH_ERASING_INTENT = (False, libevdev.EV_KEY.BTN_TOOL_RUBBER) 30*0bb3ed71SBenjamin Tissoires PEN_IS_ERASING = (True, libevdev.EV_KEY.BTN_TOOL_RUBBER) 31*0bb3ed71SBenjamin Tissoires 32*0bb3ed71SBenjamin Tissoires def __init__(self, touch, tool): 33*0bb3ed71SBenjamin Tissoires self.touch = touch 34*0bb3ed71SBenjamin Tissoires self.tool = tool 35*0bb3ed71SBenjamin Tissoires 36*0bb3ed71SBenjamin Tissoires @classmethod 37*0bb3ed71SBenjamin Tissoires def from_evdev(cls, evdev) -> "PenState": 38*0bb3ed71SBenjamin Tissoires touch = bool(evdev.value[libevdev.EV_KEY.BTN_TOUCH]) 39*0bb3ed71SBenjamin Tissoires tool = None 40*0bb3ed71SBenjamin Tissoires if ( 41*0bb3ed71SBenjamin Tissoires evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 42*0bb3ed71SBenjamin Tissoires and not evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 43*0bb3ed71SBenjamin Tissoires ): 44*0bb3ed71SBenjamin Tissoires tool = libevdev.EV_KEY.BTN_TOOL_RUBBER 45*0bb3ed71SBenjamin Tissoires elif ( 46*0bb3ed71SBenjamin Tissoires evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 47*0bb3ed71SBenjamin Tissoires and not evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 48*0bb3ed71SBenjamin Tissoires ): 49*0bb3ed71SBenjamin Tissoires tool = libevdev.EV_KEY.BTN_TOOL_PEN 50*0bb3ed71SBenjamin Tissoires elif ( 51*0bb3ed71SBenjamin Tissoires evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 52*0bb3ed71SBenjamin Tissoires or evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 53*0bb3ed71SBenjamin Tissoires ): 54*0bb3ed71SBenjamin Tissoires raise ValueError("2 tools are not allowed") 55*0bb3ed71SBenjamin Tissoires 56*0bb3ed71SBenjamin Tissoires return cls((touch, tool)) 57*0bb3ed71SBenjamin Tissoires 58*0bb3ed71SBenjamin Tissoires def apply(self, events) -> "PenState": 59*0bb3ed71SBenjamin Tissoires if libevdev.EV_SYN.SYN_REPORT in events: 60*0bb3ed71SBenjamin Tissoires raise ValueError("EV_SYN is in the event sequence") 61*0bb3ed71SBenjamin Tissoires touch = self.touch 62*0bb3ed71SBenjamin Tissoires touch_found = False 63*0bb3ed71SBenjamin Tissoires tool = self.tool 64*0bb3ed71SBenjamin Tissoires tool_found = False 65*0bb3ed71SBenjamin Tissoires 66*0bb3ed71SBenjamin Tissoires for ev in events: 67*0bb3ed71SBenjamin Tissoires if ev == libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH): 68*0bb3ed71SBenjamin Tissoires if touch_found: 69*0bb3ed71SBenjamin Tissoires raise ValueError(f"duplicated BTN_TOUCH in {events}") 70*0bb3ed71SBenjamin Tissoires touch_found = True 71*0bb3ed71SBenjamin Tissoires touch = bool(ev.value) 72*0bb3ed71SBenjamin Tissoires elif ev in ( 73*0bb3ed71SBenjamin Tissoires libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN), 74*0bb3ed71SBenjamin Tissoires libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_RUBBER), 75*0bb3ed71SBenjamin Tissoires ): 76*0bb3ed71SBenjamin Tissoires if tool_found: 77*0bb3ed71SBenjamin Tissoires raise ValueError(f"duplicated BTN_TOOL_* in {events}") 78*0bb3ed71SBenjamin Tissoires tool_found = True 79*0bb3ed71SBenjamin Tissoires if ev.value: 80*0bb3ed71SBenjamin Tissoires tool = ev.code 81*0bb3ed71SBenjamin Tissoires else: 82*0bb3ed71SBenjamin Tissoires tool = None 83*0bb3ed71SBenjamin Tissoires 84*0bb3ed71SBenjamin Tissoires new_state = PenState((touch, tool)) 85*0bb3ed71SBenjamin Tissoires assert ( 86*0bb3ed71SBenjamin Tissoires new_state in self.valid_transitions() 87*0bb3ed71SBenjamin Tissoires ), f"moving from {self} to {new_state} is forbidden" 88*0bb3ed71SBenjamin Tissoires 89*0bb3ed71SBenjamin Tissoires return new_state 90*0bb3ed71SBenjamin Tissoires 91*0bb3ed71SBenjamin Tissoires def valid_transitions(self) -> Tuple["PenState", ...]: 92*0bb3ed71SBenjamin Tissoires """Following the state machine in the URL above, with a couple of addition 93*0bb3ed71SBenjamin Tissoires for skipping the in-range state, due to historical reasons. 94*0bb3ed71SBenjamin Tissoires 95*0bb3ed71SBenjamin Tissoires Note that those transitions are from the evdev point of view, not HID""" 96*0bb3ed71SBenjamin Tissoires if self == PenState.PEN_IS_OUT_OF_RANGE: 97*0bb3ed71SBenjamin Tissoires return ( 98*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 99*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 100*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 101*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 102*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 103*0bb3ed71SBenjamin Tissoires ) 104*0bb3ed71SBenjamin Tissoires 105*0bb3ed71SBenjamin Tissoires if self == PenState.PEN_IS_IN_RANGE: 106*0bb3ed71SBenjamin Tissoires return ( 107*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 108*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 109*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 110*0bb3ed71SBenjamin Tissoires ) 111*0bb3ed71SBenjamin Tissoires 112*0bb3ed71SBenjamin Tissoires if self == PenState.PEN_IS_IN_CONTACT: 113*0bb3ed71SBenjamin Tissoires return ( 114*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 115*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 116*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 117*0bb3ed71SBenjamin Tissoires ) 118*0bb3ed71SBenjamin Tissoires 119*0bb3ed71SBenjamin Tissoires if self == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT: 120*0bb3ed71SBenjamin Tissoires return ( 121*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 122*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 123*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 124*0bb3ed71SBenjamin Tissoires ) 125*0bb3ed71SBenjamin Tissoires 126*0bb3ed71SBenjamin Tissoires if self == PenState.PEN_IS_ERASING: 127*0bb3ed71SBenjamin Tissoires return ( 128*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 129*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 130*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 131*0bb3ed71SBenjamin Tissoires ) 132*0bb3ed71SBenjamin Tissoires 133*0bb3ed71SBenjamin Tissoires return tuple() 134*0bb3ed71SBenjamin Tissoires 135*0bb3ed71SBenjamin Tissoires 136*0bb3ed71SBenjamin Tissoiresclass Data(object): 137*0bb3ed71SBenjamin Tissoires pass 138*0bb3ed71SBenjamin Tissoires 139*0bb3ed71SBenjamin Tissoires 140*0bb3ed71SBenjamin Tissoiresclass Pen(object): 141*0bb3ed71SBenjamin Tissoires def __init__(self, x, y): 142*0bb3ed71SBenjamin Tissoires self.x = x 143*0bb3ed71SBenjamin Tissoires self.y = y 144*0bb3ed71SBenjamin Tissoires self.tipswitch = False 145*0bb3ed71SBenjamin Tissoires self.tippressure = 15 146*0bb3ed71SBenjamin Tissoires self.azimuth = 0 147*0bb3ed71SBenjamin Tissoires self.inrange = False 148*0bb3ed71SBenjamin Tissoires self.width = 10 149*0bb3ed71SBenjamin Tissoires self.height = 10 150*0bb3ed71SBenjamin Tissoires self.barrelswitch = False 151*0bb3ed71SBenjamin Tissoires self.invert = False 152*0bb3ed71SBenjamin Tissoires self.eraser = False 153*0bb3ed71SBenjamin Tissoires self.x_tilt = 0 154*0bb3ed71SBenjamin Tissoires self.y_tilt = 0 155*0bb3ed71SBenjamin Tissoires self.twist = 0 156*0bb3ed71SBenjamin Tissoires self._old_values = None 157*0bb3ed71SBenjamin Tissoires self.current_state = None 158*0bb3ed71SBenjamin Tissoires 159*0bb3ed71SBenjamin Tissoires def _restore(self): 160*0bb3ed71SBenjamin Tissoires if self._old_values is not None: 161*0bb3ed71SBenjamin Tissoires for i in [ 162*0bb3ed71SBenjamin Tissoires "x", 163*0bb3ed71SBenjamin Tissoires "y", 164*0bb3ed71SBenjamin Tissoires "tippressure", 165*0bb3ed71SBenjamin Tissoires "azimuth", 166*0bb3ed71SBenjamin Tissoires "width", 167*0bb3ed71SBenjamin Tissoires "height", 168*0bb3ed71SBenjamin Tissoires "twist", 169*0bb3ed71SBenjamin Tissoires "x_tilt", 170*0bb3ed71SBenjamin Tissoires "y_tilt", 171*0bb3ed71SBenjamin Tissoires ]: 172*0bb3ed71SBenjamin Tissoires setattr(self, i, getattr(self._old_values, i)) 173*0bb3ed71SBenjamin Tissoires 174*0bb3ed71SBenjamin Tissoires def move_to(self, state): 175*0bb3ed71SBenjamin Tissoires # fill in the previous values 176*0bb3ed71SBenjamin Tissoires if self.current_state == PenState.PEN_IS_OUT_OF_RANGE: 177*0bb3ed71SBenjamin Tissoires self._restore() 178*0bb3ed71SBenjamin Tissoires 179*0bb3ed71SBenjamin Tissoires print(f"\n *** pen is moving to {state} ***") 180*0bb3ed71SBenjamin Tissoires 181*0bb3ed71SBenjamin Tissoires if state == PenState.PEN_IS_OUT_OF_RANGE: 182*0bb3ed71SBenjamin Tissoires self._old_values = copy.copy(self) 183*0bb3ed71SBenjamin Tissoires self.x = 0 184*0bb3ed71SBenjamin Tissoires self.y = 0 185*0bb3ed71SBenjamin Tissoires self.tipswitch = False 186*0bb3ed71SBenjamin Tissoires self.tippressure = 0 187*0bb3ed71SBenjamin Tissoires self.azimuth = 0 188*0bb3ed71SBenjamin Tissoires self.inrange = False 189*0bb3ed71SBenjamin Tissoires self.width = 0 190*0bb3ed71SBenjamin Tissoires self.height = 0 191*0bb3ed71SBenjamin Tissoires self.invert = False 192*0bb3ed71SBenjamin Tissoires self.eraser = False 193*0bb3ed71SBenjamin Tissoires self.x_tilt = 0 194*0bb3ed71SBenjamin Tissoires self.y_tilt = 0 195*0bb3ed71SBenjamin Tissoires self.twist = 0 196*0bb3ed71SBenjamin Tissoires elif state == PenState.PEN_IS_IN_RANGE: 197*0bb3ed71SBenjamin Tissoires self.tipswitch = False 198*0bb3ed71SBenjamin Tissoires self.inrange = True 199*0bb3ed71SBenjamin Tissoires self.invert = False 200*0bb3ed71SBenjamin Tissoires self.eraser = False 201*0bb3ed71SBenjamin Tissoires elif state == PenState.PEN_IS_IN_CONTACT: 202*0bb3ed71SBenjamin Tissoires self.tipswitch = True 203*0bb3ed71SBenjamin Tissoires self.inrange = True 204*0bb3ed71SBenjamin Tissoires self.invert = False 205*0bb3ed71SBenjamin Tissoires self.eraser = False 206*0bb3ed71SBenjamin Tissoires elif state == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT: 207*0bb3ed71SBenjamin Tissoires self.tipswitch = False 208*0bb3ed71SBenjamin Tissoires self.inrange = True 209*0bb3ed71SBenjamin Tissoires self.invert = True 210*0bb3ed71SBenjamin Tissoires self.eraser = False 211*0bb3ed71SBenjamin Tissoires elif state == PenState.PEN_IS_ERASING: 212*0bb3ed71SBenjamin Tissoires self.tipswitch = False 213*0bb3ed71SBenjamin Tissoires self.inrange = True 214*0bb3ed71SBenjamin Tissoires self.invert = True 215*0bb3ed71SBenjamin Tissoires self.eraser = True 216*0bb3ed71SBenjamin Tissoires 217*0bb3ed71SBenjamin Tissoires self.current_state = state 218*0bb3ed71SBenjamin Tissoires 219*0bb3ed71SBenjamin Tissoires def __assert_axis(self, evdev, axis, value): 220*0bb3ed71SBenjamin Tissoires if ( 221*0bb3ed71SBenjamin Tissoires axis == libevdev.EV_KEY.BTN_TOOL_RUBBER 222*0bb3ed71SBenjamin Tissoires and evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] is None 223*0bb3ed71SBenjamin Tissoires ): 224*0bb3ed71SBenjamin Tissoires return 225*0bb3ed71SBenjamin Tissoires 226*0bb3ed71SBenjamin Tissoires assert ( 227*0bb3ed71SBenjamin Tissoires evdev.value[axis] == value 228*0bb3ed71SBenjamin Tissoires ), f"assert evdev.value[{axis}] ({evdev.value[axis]}) != {value}" 229*0bb3ed71SBenjamin Tissoires 230*0bb3ed71SBenjamin Tissoires def assert_expected_input_events(self, evdev): 231*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_X] == self.x 232*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_Y] == self.y 233*0bb3ed71SBenjamin Tissoires assert self.current_state == PenState.from_evdev(evdev) 234*0bb3ed71SBenjamin Tissoires 235*0bb3ed71SBenjamin Tissoires @staticmethod 236*0bb3ed71SBenjamin Tissoires def legal_transitions() -> Dict[str, Tuple[PenState, ...]]: 237*0bb3ed71SBenjamin Tissoires """This is the first half of the Windows Pen Implementation state machine: 238*0bb3ed71SBenjamin Tissoires we don't have Invert nor Erase bits, so just move in/out-of-range or proximity. 239*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 240*0bb3ed71SBenjamin Tissoires """ 241*0bb3ed71SBenjamin Tissoires return { 242*0bb3ed71SBenjamin Tissoires "in-range": (PenState.PEN_IS_IN_RANGE,), 243*0bb3ed71SBenjamin Tissoires "in-range -> out-of-range": ( 244*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 245*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 246*0bb3ed71SBenjamin Tissoires ), 247*0bb3ed71SBenjamin Tissoires "in-range -> touch": (PenState.PEN_IS_IN_RANGE, PenState.PEN_IS_IN_CONTACT), 248*0bb3ed71SBenjamin Tissoires "in-range -> touch -> release": ( 249*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 250*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 251*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 252*0bb3ed71SBenjamin Tissoires ), 253*0bb3ed71SBenjamin Tissoires "in-range -> touch -> release -> out-of-range": ( 254*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 255*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 256*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 257*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 258*0bb3ed71SBenjamin Tissoires ), 259*0bb3ed71SBenjamin Tissoires } 260*0bb3ed71SBenjamin Tissoires 261*0bb3ed71SBenjamin Tissoires @staticmethod 262*0bb3ed71SBenjamin Tissoires def legal_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]: 263*0bb3ed71SBenjamin Tissoires """This is the second half of the Windows Pen Implementation state machine: 264*0bb3ed71SBenjamin Tissoires we now have Invert and Erase bits, so move in/out or proximity with the intend 265*0bb3ed71SBenjamin Tissoires to erase. 266*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 267*0bb3ed71SBenjamin Tissoires """ 268*0bb3ed71SBenjamin Tissoires return { 269*0bb3ed71SBenjamin Tissoires "hover-erasing": (PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,), 270*0bb3ed71SBenjamin Tissoires "hover-erasing -> out-of-range": ( 271*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 272*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 273*0bb3ed71SBenjamin Tissoires ), 274*0bb3ed71SBenjamin Tissoires "hover-erasing -> erase": ( 275*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 276*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 277*0bb3ed71SBenjamin Tissoires ), 278*0bb3ed71SBenjamin Tissoires "hover-erasing -> erase -> release": ( 279*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 280*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 281*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 282*0bb3ed71SBenjamin Tissoires ), 283*0bb3ed71SBenjamin Tissoires "hover-erasing -> erase -> release -> out-of-range": ( 284*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 285*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 286*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 287*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 288*0bb3ed71SBenjamin Tissoires ), 289*0bb3ed71SBenjamin Tissoires "hover-erasing -> in-range": ( 290*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 291*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 292*0bb3ed71SBenjamin Tissoires ), 293*0bb3ed71SBenjamin Tissoires "in-range -> hover-erasing": ( 294*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 295*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 296*0bb3ed71SBenjamin Tissoires ), 297*0bb3ed71SBenjamin Tissoires } 298*0bb3ed71SBenjamin Tissoires 299*0bb3ed71SBenjamin Tissoires @staticmethod 300*0bb3ed71SBenjamin Tissoires def tolerated_transitions() -> Dict[str, Tuple[PenState, ...]]: 301*0bb3ed71SBenjamin Tissoires """This is not adhering to the Windows Pen Implementation state machine 302*0bb3ed71SBenjamin Tissoires but we should expect the kernel to behave properly, mostly for historical 303*0bb3ed71SBenjamin Tissoires reasons.""" 304*0bb3ed71SBenjamin Tissoires return { 305*0bb3ed71SBenjamin Tissoires "direct-in-contact": (PenState.PEN_IS_IN_CONTACT,), 306*0bb3ed71SBenjamin Tissoires "direct-in-contact -> out-of-range": ( 307*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 308*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 309*0bb3ed71SBenjamin Tissoires ), 310*0bb3ed71SBenjamin Tissoires } 311*0bb3ed71SBenjamin Tissoires 312*0bb3ed71SBenjamin Tissoires @staticmethod 313*0bb3ed71SBenjamin Tissoires def tolerated_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]: 314*0bb3ed71SBenjamin Tissoires """This is the second half of the Windows Pen Implementation state machine: 315*0bb3ed71SBenjamin Tissoires we now have Invert and Erase bits, so move in/out or proximity with the intend 316*0bb3ed71SBenjamin Tissoires to erase. 317*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 318*0bb3ed71SBenjamin Tissoires """ 319*0bb3ed71SBenjamin Tissoires return { 320*0bb3ed71SBenjamin Tissoires "direct-erase": (PenState.PEN_IS_ERASING,), 321*0bb3ed71SBenjamin Tissoires "direct-erase -> out-of-range": ( 322*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 323*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_OUT_OF_RANGE, 324*0bb3ed71SBenjamin Tissoires ), 325*0bb3ed71SBenjamin Tissoires } 326*0bb3ed71SBenjamin Tissoires 327*0bb3ed71SBenjamin Tissoires @staticmethod 328*0bb3ed71SBenjamin Tissoires def broken_transitions() -> Dict[str, Tuple[PenState, ...]]: 329*0bb3ed71SBenjamin Tissoires """Those tests are definitely not part of the Windows specification. 330*0bb3ed71SBenjamin Tissoires However, a half broken device might export those transitions. 331*0bb3ed71SBenjamin Tissoires For example, a pen that has the eraser button might wobble between 332*0bb3ed71SBenjamin Tissoires touching and erasing if the tablet doesn't enforce the Windows 333*0bb3ed71SBenjamin Tissoires state machine.""" 334*0bb3ed71SBenjamin Tissoires return { 335*0bb3ed71SBenjamin Tissoires "in-range -> touch -> erase -> hover-erase": ( 336*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 337*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 338*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 339*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 340*0bb3ed71SBenjamin Tissoires ), 341*0bb3ed71SBenjamin Tissoires "in-range -> erase -> hover-erase": ( 342*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 343*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 344*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 345*0bb3ed71SBenjamin Tissoires ), 346*0bb3ed71SBenjamin Tissoires "hover-erase -> erase -> touch -> in-range": ( 347*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 348*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 349*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 350*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 351*0bb3ed71SBenjamin Tissoires ), 352*0bb3ed71SBenjamin Tissoires "hover-erase -> touch -> in-range": ( 353*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 354*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 355*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_RANGE, 356*0bb3ed71SBenjamin Tissoires ), 357*0bb3ed71SBenjamin Tissoires "touch -> erase -> touch -> erase": ( 358*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 359*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 360*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_IN_CONTACT, 361*0bb3ed71SBenjamin Tissoires PenState.PEN_IS_ERASING, 362*0bb3ed71SBenjamin Tissoires ), 363*0bb3ed71SBenjamin Tissoires } 364*0bb3ed71SBenjamin Tissoires 365*0bb3ed71SBenjamin Tissoires 366*0bb3ed71SBenjamin Tissoiresclass PenDigitizer(base.UHIDTestDevice): 367*0bb3ed71SBenjamin Tissoires def __init__( 368*0bb3ed71SBenjamin Tissoires self, 369*0bb3ed71SBenjamin Tissoires name, 370*0bb3ed71SBenjamin Tissoires rdesc_str=None, 371*0bb3ed71SBenjamin Tissoires rdesc=None, 372*0bb3ed71SBenjamin Tissoires application="Pen", 373*0bb3ed71SBenjamin Tissoires physical="Stylus", 374*0bb3ed71SBenjamin Tissoires input_info=(BusType.USB, 1, 2), 375*0bb3ed71SBenjamin Tissoires evdev_name_suffix=None, 376*0bb3ed71SBenjamin Tissoires ): 377*0bb3ed71SBenjamin Tissoires super().__init__(name, application, rdesc_str, rdesc, input_info) 378*0bb3ed71SBenjamin Tissoires self.physical = physical 379*0bb3ed71SBenjamin Tissoires self.cur_application = application 380*0bb3ed71SBenjamin Tissoires if evdev_name_suffix is not None: 381*0bb3ed71SBenjamin Tissoires self.name += evdev_name_suffix 382*0bb3ed71SBenjamin Tissoires 383*0bb3ed71SBenjamin Tissoires self.fields = [] 384*0bb3ed71SBenjamin Tissoires for r in self.parsed_rdesc.input_reports.values(): 385*0bb3ed71SBenjamin Tissoires if r.application_name == self.application: 386*0bb3ed71SBenjamin Tissoires physicals = [f.physical_name for f in r] 387*0bb3ed71SBenjamin Tissoires if self.physical not in physicals and None not in physicals: 388*0bb3ed71SBenjamin Tissoires continue 389*0bb3ed71SBenjamin Tissoires self.fields = [f.usage_name for f in r] 390*0bb3ed71SBenjamin Tissoires 391*0bb3ed71SBenjamin Tissoires def event(self, pen): 392*0bb3ed71SBenjamin Tissoires rs = [] 393*0bb3ed71SBenjamin Tissoires r = self.create_report(application=self.cur_application, data=pen) 394*0bb3ed71SBenjamin Tissoires self.call_input_event(r) 395*0bb3ed71SBenjamin Tissoires rs.append(r) 396*0bb3ed71SBenjamin Tissoires return rs 397*0bb3ed71SBenjamin Tissoires 398*0bb3ed71SBenjamin Tissoires def get_report(self, req, rnum, rtype): 399*0bb3ed71SBenjamin Tissoires if rtype != self.UHID_FEATURE_REPORT: 400*0bb3ed71SBenjamin Tissoires return (1, []) 401*0bb3ed71SBenjamin Tissoires 402*0bb3ed71SBenjamin Tissoires rdesc = None 403*0bb3ed71SBenjamin Tissoires for v in self.parsed_rdesc.feature_reports.values(): 404*0bb3ed71SBenjamin Tissoires if v.report_ID == rnum: 405*0bb3ed71SBenjamin Tissoires rdesc = v 406*0bb3ed71SBenjamin Tissoires 407*0bb3ed71SBenjamin Tissoires if rdesc is None: 408*0bb3ed71SBenjamin Tissoires return (1, []) 409*0bb3ed71SBenjamin Tissoires 410*0bb3ed71SBenjamin Tissoires return (1, []) 411*0bb3ed71SBenjamin Tissoires 412*0bb3ed71SBenjamin Tissoires def set_report(self, req, rnum, rtype, data): 413*0bb3ed71SBenjamin Tissoires if rtype != self.UHID_FEATURE_REPORT: 414*0bb3ed71SBenjamin Tissoires return 1 415*0bb3ed71SBenjamin Tissoires 416*0bb3ed71SBenjamin Tissoires rdesc = None 417*0bb3ed71SBenjamin Tissoires for v in self.parsed_rdesc.feature_reports.values(): 418*0bb3ed71SBenjamin Tissoires if v.report_ID == rnum: 419*0bb3ed71SBenjamin Tissoires rdesc = v 420*0bb3ed71SBenjamin Tissoires 421*0bb3ed71SBenjamin Tissoires if rdesc is None: 422*0bb3ed71SBenjamin Tissoires return 1 423*0bb3ed71SBenjamin Tissoires 424*0bb3ed71SBenjamin Tissoires return 1 425*0bb3ed71SBenjamin Tissoires 426*0bb3ed71SBenjamin Tissoires 427*0bb3ed71SBenjamin Tissoiresclass BaseTest: 428*0bb3ed71SBenjamin Tissoires class TestTablet(base.BaseTestCase.TestUhid): 429*0bb3ed71SBenjamin Tissoires def create_device(self): 430*0bb3ed71SBenjamin Tissoires raise Exception("please reimplement me in subclasses") 431*0bb3ed71SBenjamin Tissoires 432*0bb3ed71SBenjamin Tissoires def post(self, uhdev, pen): 433*0bb3ed71SBenjamin Tissoires r = uhdev.event(pen) 434*0bb3ed71SBenjamin Tissoires events = uhdev.next_sync_events() 435*0bb3ed71SBenjamin Tissoires self.debug_reports(r, uhdev, events) 436*0bb3ed71SBenjamin Tissoires return events 437*0bb3ed71SBenjamin Tissoires 438*0bb3ed71SBenjamin Tissoires def validate_transitions(self, from_state, pen, evdev, events): 439*0bb3ed71SBenjamin Tissoires # check that the final state is correct 440*0bb3ed71SBenjamin Tissoires pen.assert_expected_input_events(evdev) 441*0bb3ed71SBenjamin Tissoires 442*0bb3ed71SBenjamin Tissoires # check that the transitions are valid 443*0bb3ed71SBenjamin Tissoires sync_events = [] 444*0bb3ed71SBenjamin Tissoires while libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) in events: 445*0bb3ed71SBenjamin Tissoires # split the first EV_SYN from the list 446*0bb3ed71SBenjamin Tissoires idx = events.index(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT)) 447*0bb3ed71SBenjamin Tissoires sync_events = events[:idx] 448*0bb3ed71SBenjamin Tissoires events = events[idx + 1 :] 449*0bb3ed71SBenjamin Tissoires 450*0bb3ed71SBenjamin Tissoires # now check for a valid transition 451*0bb3ed71SBenjamin Tissoires from_state = from_state.apply(sync_events) 452*0bb3ed71SBenjamin Tissoires 453*0bb3ed71SBenjamin Tissoires if events: 454*0bb3ed71SBenjamin Tissoires from_state = from_state.apply(sync_events) 455*0bb3ed71SBenjamin Tissoires 456*0bb3ed71SBenjamin Tissoires def _test_states(self, state_list, scribble): 457*0bb3ed71SBenjamin Tissoires """Internal method to test against a list of 458*0bb3ed71SBenjamin Tissoires transition between states. 459*0bb3ed71SBenjamin Tissoires state_list is a list of PenState objects 460*0bb3ed71SBenjamin Tissoires scribble is a boolean which tells if we need 461*0bb3ed71SBenjamin Tissoires to wobble a little the X,Y coordinates of the pen 462*0bb3ed71SBenjamin Tissoires between each state transition.""" 463*0bb3ed71SBenjamin Tissoires uhdev = self.uhdev 464*0bb3ed71SBenjamin Tissoires evdev = uhdev.get_evdev() 465*0bb3ed71SBenjamin Tissoires 466*0bb3ed71SBenjamin Tissoires cur_state = PenState.PEN_IS_OUT_OF_RANGE 467*0bb3ed71SBenjamin Tissoires 468*0bb3ed71SBenjamin Tissoires p = Pen(50, 60) 469*0bb3ed71SBenjamin Tissoires p.move_to(PenState.PEN_IS_OUT_OF_RANGE) 470*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 471*0bb3ed71SBenjamin Tissoires self.validate_transitions(cur_state, p, evdev, events) 472*0bb3ed71SBenjamin Tissoires 473*0bb3ed71SBenjamin Tissoires cur_state = p.current_state 474*0bb3ed71SBenjamin Tissoires 475*0bb3ed71SBenjamin Tissoires for state in state_list: 476*0bb3ed71SBenjamin Tissoires if scribble and cur_state != PenState.PEN_IS_OUT_OF_RANGE: 477*0bb3ed71SBenjamin Tissoires p.x += 1 478*0bb3ed71SBenjamin Tissoires p.y -= 1 479*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 480*0bb3ed71SBenjamin Tissoires self.validate_transitions(cur_state, p, evdev, events) 481*0bb3ed71SBenjamin Tissoires assert len(events) >= 3 # X, Y, SYN 482*0bb3ed71SBenjamin Tissoires p.move_to(state) 483*0bb3ed71SBenjamin Tissoires if scribble and state != PenState.PEN_IS_OUT_OF_RANGE: 484*0bb3ed71SBenjamin Tissoires p.x += 1 485*0bb3ed71SBenjamin Tissoires p.y -= 1 486*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 487*0bb3ed71SBenjamin Tissoires self.validate_transitions(cur_state, p, evdev, events) 488*0bb3ed71SBenjamin Tissoires cur_state = p.current_state 489*0bb3ed71SBenjamin Tissoires 490*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 491*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize( 492*0bb3ed71SBenjamin Tissoires "state_list", 493*0bb3ed71SBenjamin Tissoires [pytest.param(v, id=k) for k, v in Pen.legal_transitions().items()], 494*0bb3ed71SBenjamin Tissoires ) 495*0bb3ed71SBenjamin Tissoires def test_valid_pen_states(self, state_list, scribble): 496*0bb3ed71SBenjamin Tissoires """This is the first half of the Windows Pen Implementation state machine: 497*0bb3ed71SBenjamin Tissoires we don't have Invert nor Erase bits, so just move in/out-of-range or proximity. 498*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 499*0bb3ed71SBenjamin Tissoires """ 500*0bb3ed71SBenjamin Tissoires self._test_states(state_list, scribble) 501*0bb3ed71SBenjamin Tissoires 502*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 503*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize( 504*0bb3ed71SBenjamin Tissoires "state_list", 505*0bb3ed71SBenjamin Tissoires [pytest.param(v, id=k) for k, v in Pen.tolerated_transitions().items()], 506*0bb3ed71SBenjamin Tissoires ) 507*0bb3ed71SBenjamin Tissoires def test_tolerated_pen_states(self, state_list, scribble): 508*0bb3ed71SBenjamin Tissoires """This is not adhering to the Windows Pen Implementation state machine 509*0bb3ed71SBenjamin Tissoires but we should expect the kernel to behave properly, mostly for historical 510*0bb3ed71SBenjamin Tissoires reasons.""" 511*0bb3ed71SBenjamin Tissoires self._test_states(state_list, scribble) 512*0bb3ed71SBenjamin Tissoires 513*0bb3ed71SBenjamin Tissoires @pytest.mark.skip_if_uhdev( 514*0bb3ed71SBenjamin Tissoires lambda uhdev: "Invert" not in uhdev.fields, 515*0bb3ed71SBenjamin Tissoires "Device not compatible, missing Invert usage", 516*0bb3ed71SBenjamin Tissoires ) 517*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 518*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize( 519*0bb3ed71SBenjamin Tissoires "state_list", 520*0bb3ed71SBenjamin Tissoires [ 521*0bb3ed71SBenjamin Tissoires pytest.param(v, id=k) 522*0bb3ed71SBenjamin Tissoires for k, v in Pen.legal_transitions_with_invert().items() 523*0bb3ed71SBenjamin Tissoires ], 524*0bb3ed71SBenjamin Tissoires ) 525*0bb3ed71SBenjamin Tissoires def test_valid_invert_pen_states(self, state_list, scribble): 526*0bb3ed71SBenjamin Tissoires """This is the second half of the Windows Pen Implementation state machine: 527*0bb3ed71SBenjamin Tissoires we now have Invert and Erase bits, so move in/out or proximity with the intend 528*0bb3ed71SBenjamin Tissoires to erase. 529*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 530*0bb3ed71SBenjamin Tissoires """ 531*0bb3ed71SBenjamin Tissoires self._test_states(state_list, scribble) 532*0bb3ed71SBenjamin Tissoires 533*0bb3ed71SBenjamin Tissoires @pytest.mark.skip_if_uhdev( 534*0bb3ed71SBenjamin Tissoires lambda uhdev: "Invert" not in uhdev.fields, 535*0bb3ed71SBenjamin Tissoires "Device not compatible, missing Invert usage", 536*0bb3ed71SBenjamin Tissoires ) 537*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 538*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize( 539*0bb3ed71SBenjamin Tissoires "state_list", 540*0bb3ed71SBenjamin Tissoires [ 541*0bb3ed71SBenjamin Tissoires pytest.param(v, id=k) 542*0bb3ed71SBenjamin Tissoires for k, v in Pen.tolerated_transitions_with_invert().items() 543*0bb3ed71SBenjamin Tissoires ], 544*0bb3ed71SBenjamin Tissoires ) 545*0bb3ed71SBenjamin Tissoires def test_tolerated_invert_pen_states(self, state_list, scribble): 546*0bb3ed71SBenjamin Tissoires """This is the second half of the Windows Pen Implementation state machine: 547*0bb3ed71SBenjamin Tissoires we now have Invert and Erase bits, so move in/out or proximity with the intend 548*0bb3ed71SBenjamin Tissoires to erase. 549*0bb3ed71SBenjamin Tissoires https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 550*0bb3ed71SBenjamin Tissoires """ 551*0bb3ed71SBenjamin Tissoires self._test_states(state_list, scribble) 552*0bb3ed71SBenjamin Tissoires 553*0bb3ed71SBenjamin Tissoires @pytest.mark.skip_if_uhdev( 554*0bb3ed71SBenjamin Tissoires lambda uhdev: "Invert" not in uhdev.fields, 555*0bb3ed71SBenjamin Tissoires "Device not compatible, missing Invert usage", 556*0bb3ed71SBenjamin Tissoires ) 557*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 558*0bb3ed71SBenjamin Tissoires @pytest.mark.parametrize( 559*0bb3ed71SBenjamin Tissoires "state_list", 560*0bb3ed71SBenjamin Tissoires [pytest.param(v, id=k) for k, v in Pen.broken_transitions().items()], 561*0bb3ed71SBenjamin Tissoires ) 562*0bb3ed71SBenjamin Tissoires def test_tolerated_broken_pen_states(self, state_list, scribble): 563*0bb3ed71SBenjamin Tissoires """Those tests are definitely not part of the Windows specification. 564*0bb3ed71SBenjamin Tissoires However, a half broken device might export those transitions. 565*0bb3ed71SBenjamin Tissoires For example, a pen that has the eraser button might wobble between 566*0bb3ed71SBenjamin Tissoires touching and erasing if the tablet doesn't enforce the Windows 567*0bb3ed71SBenjamin Tissoires state machine.""" 568*0bb3ed71SBenjamin Tissoires self._test_states(state_list, scribble) 569*0bb3ed71SBenjamin Tissoires 570*0bb3ed71SBenjamin Tissoires @pytest.mark.skip_if_uhdev( 571*0bb3ed71SBenjamin Tissoires lambda uhdev: "Barrel Switch" not in uhdev.fields, 572*0bb3ed71SBenjamin Tissoires "Device not compatible, missing Barrel Switch usage", 573*0bb3ed71SBenjamin Tissoires ) 574*0bb3ed71SBenjamin Tissoires def test_primary_button(self): 575*0bb3ed71SBenjamin Tissoires """Primary button (stylus) pressed, reports as pressed even while hovering. 576*0bb3ed71SBenjamin Tissoires Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 577*0bb3ed71SBenjamin Tissoires { 0, 0, 1 } <- hover 578*0bb3ed71SBenjamin Tissoires { 0, 1, 1 } <- primary button pressed 579*0bb3ed71SBenjamin Tissoires { 0, 1, 1 } <- liftoff 580*0bb3ed71SBenjamin Tissoires { 0, 0, 0 } <- leaves 581*0bb3ed71SBenjamin Tissoires """ 582*0bb3ed71SBenjamin Tissoires 583*0bb3ed71SBenjamin Tissoires uhdev = self.uhdev 584*0bb3ed71SBenjamin Tissoires evdev = uhdev.get_evdev() 585*0bb3ed71SBenjamin Tissoires 586*0bb3ed71SBenjamin Tissoires p = Pen(50, 60) 587*0bb3ed71SBenjamin Tissoires p.inrange = True 588*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 589*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 590*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 591*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 592*0bb3ed71SBenjamin Tissoires assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 593*0bb3ed71SBenjamin Tissoires 594*0bb3ed71SBenjamin Tissoires p.barrelswitch = True 595*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 596*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 597*0bb3ed71SBenjamin Tissoires 598*0bb3ed71SBenjamin Tissoires p.x += 1 599*0bb3ed71SBenjamin Tissoires p.y -= 1 600*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 601*0bb3ed71SBenjamin Tissoires assert len(events) == 3 # X, Y, SYN 602*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 603*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 604*0bb3ed71SBenjamin Tissoires 605*0bb3ed71SBenjamin Tissoires p.barrelswitch = False 606*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 607*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 608*0bb3ed71SBenjamin Tissoires 609*0bb3ed71SBenjamin Tissoires p.inrange = False 610*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 611*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 612*0bb3ed71SBenjamin Tissoires 613*0bb3ed71SBenjamin Tissoires @pytest.mark.skip_if_uhdev( 614*0bb3ed71SBenjamin Tissoires lambda uhdev: "Barrel Switch" not in uhdev.fields, 615*0bb3ed71SBenjamin Tissoires "Device not compatible, missing Barrel Switch usage", 616*0bb3ed71SBenjamin Tissoires ) 617*0bb3ed71SBenjamin Tissoires def test_contact_primary_button(self): 618*0bb3ed71SBenjamin Tissoires """Primary button (stylus) pressed, reports as pressed even while hovering. 619*0bb3ed71SBenjamin Tissoires Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 620*0bb3ed71SBenjamin Tissoires { 0, 0, 1 } <- hover 621*0bb3ed71SBenjamin Tissoires { 0, 1, 1 } <- primary button pressed 622*0bb3ed71SBenjamin Tissoires { 1, 1, 1 } <- touch-down 623*0bb3ed71SBenjamin Tissoires { 1, 1, 1 } <- still touch, scribble on the screen 624*0bb3ed71SBenjamin Tissoires { 0, 1, 1 } <- liftoff 625*0bb3ed71SBenjamin Tissoires { 0, 0, 0 } <- leaves 626*0bb3ed71SBenjamin Tissoires """ 627*0bb3ed71SBenjamin Tissoires 628*0bb3ed71SBenjamin Tissoires uhdev = self.uhdev 629*0bb3ed71SBenjamin Tissoires evdev = uhdev.get_evdev() 630*0bb3ed71SBenjamin Tissoires 631*0bb3ed71SBenjamin Tissoires p = Pen(50, 60) 632*0bb3ed71SBenjamin Tissoires p.inrange = True 633*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 634*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 635*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 636*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 637*0bb3ed71SBenjamin Tissoires assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 638*0bb3ed71SBenjamin Tissoires 639*0bb3ed71SBenjamin Tissoires p.barrelswitch = True 640*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 641*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 642*0bb3ed71SBenjamin Tissoires 643*0bb3ed71SBenjamin Tissoires p.tipswitch = True 644*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 645*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 646*0bb3ed71SBenjamin Tissoires assert evdev.value[libevdev.EV_KEY.BTN_STYLUS] 647*0bb3ed71SBenjamin Tissoires 648*0bb3ed71SBenjamin Tissoires p.x += 1 649*0bb3ed71SBenjamin Tissoires p.y -= 1 650*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 651*0bb3ed71SBenjamin Tissoires assert len(events) == 3 # X, Y, SYN 652*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 653*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 654*0bb3ed71SBenjamin Tissoires 655*0bb3ed71SBenjamin Tissoires p.tipswitch = False 656*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 657*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 658*0bb3ed71SBenjamin Tissoires 659*0bb3ed71SBenjamin Tissoires p.barrelswitch = False 660*0bb3ed71SBenjamin Tissoires p.inrange = False 661*0bb3ed71SBenjamin Tissoires events = self.post(uhdev, p) 662*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 663*0bb3ed71SBenjamin Tissoires assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 664*0bb3ed71SBenjamin Tissoires 665*0bb3ed71SBenjamin Tissoires 666*0bb3ed71SBenjamin Tissoiresclass GXTP_pen(PenDigitizer): 667*0bb3ed71SBenjamin Tissoires def event(self, pen): 668*0bb3ed71SBenjamin Tissoires if not hasattr(self, "prev_tip_state"): 669*0bb3ed71SBenjamin Tissoires self.prev_tip_state = False 670*0bb3ed71SBenjamin Tissoires 671*0bb3ed71SBenjamin Tissoires internal_pen = copy.copy(pen) 672*0bb3ed71SBenjamin Tissoires 673*0bb3ed71SBenjamin Tissoires # bug in the controller: when the pen touches the 674*0bb3ed71SBenjamin Tissoires # surface, in-range stays to 1, but when 675*0bb3ed71SBenjamin Tissoires # the pen moves in-range gets reverted to 0 676*0bb3ed71SBenjamin Tissoires if pen.tipswitch and self.prev_tip_state: 677*0bb3ed71SBenjamin Tissoires internal_pen.inrange = False 678*0bb3ed71SBenjamin Tissoires 679*0bb3ed71SBenjamin Tissoires self.prev_tip_state = pen.tipswitch 680*0bb3ed71SBenjamin Tissoires 681*0bb3ed71SBenjamin Tissoires # another bug in the controller: when the pen is 682*0bb3ed71SBenjamin Tissoires # inverted, invert is set to 1, but as soon as 683*0bb3ed71SBenjamin Tissoires # the pen touches the surface, eraser is correctly 684*0bb3ed71SBenjamin Tissoires # set to 1 but invert is released 685*0bb3ed71SBenjamin Tissoires if pen.eraser: 686*0bb3ed71SBenjamin Tissoires internal_pen.invert = False 687*0bb3ed71SBenjamin Tissoires 688*0bb3ed71SBenjamin Tissoires return super().event(internal_pen) 689*0bb3ed71SBenjamin Tissoires 690*0bb3ed71SBenjamin Tissoires 691*0bb3ed71SBenjamin Tissoiresclass USIPen(PenDigitizer): 692*0bb3ed71SBenjamin Tissoires pass 693*0bb3ed71SBenjamin Tissoires 694*0bb3ed71SBenjamin Tissoires 695*0bb3ed71SBenjamin Tissoires################################################################################ 696*0bb3ed71SBenjamin Tissoires# 697*0bb3ed71SBenjamin Tissoires# Windows 7 compatible devices 698*0bb3ed71SBenjamin Tissoires# 699*0bb3ed71SBenjamin Tissoires################################################################################ 700*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_7224(BaseTest.TestTablet): 701*0bb3ed71SBenjamin Tissoires# def create_device(self): 702*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_7224', 703*0bb3ed71SBenjamin Tissoires# 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', 704*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x7224), 705*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 706*0bb3ed71SBenjamin Tissoires# 707*0bb3ed71SBenjamin Tissoires# 708*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_72fa(BaseTest.TestTablet): 709*0bb3ed71SBenjamin Tissoires# def create_device(self): 710*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_72fa', 711*0bb3ed71SBenjamin Tissoires# 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', 712*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x72fa), 713*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 714*0bb3ed71SBenjamin Tissoires# 715*0bb3ed71SBenjamin Tissoires# 716*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_7336(BaseTest.TestTablet): 717*0bb3ed71SBenjamin Tissoires# def create_device(self): 718*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_7336', 719*0bb3ed71SBenjamin Tissoires# 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', 720*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x7336), 721*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 722*0bb3ed71SBenjamin Tissoires# 723*0bb3ed71SBenjamin Tissoires# 724*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_7337(BaseTest.TestTablet): 725*0bb3ed71SBenjamin Tissoires# def create_device(self): 726*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_7337', 727*0bb3ed71SBenjamin Tissoires# 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', 728*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x7337), 729*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 730*0bb3ed71SBenjamin Tissoires# 731*0bb3ed71SBenjamin Tissoires# 732*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_7349(BaseTest.TestTablet): 733*0bb3ed71SBenjamin Tissoires# def create_device(self): 734*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_7349', 735*0bb3ed71SBenjamin Tissoires# 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', 736*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x7349), 737*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 738*0bb3ed71SBenjamin Tissoires# 739*0bb3ed71SBenjamin Tissoires# 740*0bb3ed71SBenjamin Tissoires# class TestEgalax_capacitive_0eef_73f4(BaseTest.TestTablet): 741*0bb3ed71SBenjamin Tissoires# def create_device(self): 742*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test egalax-capacitive_0eef_73f4', 743*0bb3ed71SBenjamin Tissoires# 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', 744*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x0eef, 0x73f4), 745*0bb3ed71SBenjamin Tissoires# evdev_name_suffix=' Touchscreen') 746*0bb3ed71SBenjamin Tissoires# 747*0bb3ed71SBenjamin Tissoires# bogus: BTN_TOOL_PEN is not emitted 748*0bb3ed71SBenjamin Tissoires# class TestIrtouch_6615_0070(BaseTest.TestTablet): 749*0bb3ed71SBenjamin Tissoires# def create_device(self): 750*0bb3ed71SBenjamin Tissoires# return PenDigitizer('uhid test irtouch_6615_0070', 751*0bb3ed71SBenjamin Tissoires# 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', 752*0bb3ed71SBenjamin Tissoires# input_info=(BusType.USB, 0x6615, 0x0070)) 753*0bb3ed71SBenjamin Tissoires 754*0bb3ed71SBenjamin Tissoires 755*0bb3ed71SBenjamin Tissoiresclass TestNexio_1870_0100(BaseTest.TestTablet): 756*0bb3ed71SBenjamin Tissoires def create_device(self): 757*0bb3ed71SBenjamin Tissoires return PenDigitizer( 758*0bb3ed71SBenjamin Tissoires "uhid test nexio_1870_0100", 759*0bb3ed71SBenjamin Tissoires 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", 760*0bb3ed71SBenjamin Tissoires input_info=(BusType.USB, 0x1870, 0x0100), 761*0bb3ed71SBenjamin Tissoires ) 762*0bb3ed71SBenjamin Tissoires 763*0bb3ed71SBenjamin Tissoires 764*0bb3ed71SBenjamin Tissoiresclass TestNexio_1870_010d(BaseTest.TestTablet): 765*0bb3ed71SBenjamin Tissoires def create_device(self): 766*0bb3ed71SBenjamin Tissoires return PenDigitizer( 767*0bb3ed71SBenjamin Tissoires "uhid test nexio_1870_010d", 768*0bb3ed71SBenjamin Tissoires 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", 769*0bb3ed71SBenjamin Tissoires input_info=(BusType.USB, 0x1870, 0x010D), 770*0bb3ed71SBenjamin Tissoires ) 771*0bb3ed71SBenjamin Tissoires 772*0bb3ed71SBenjamin Tissoires 773*0bb3ed71SBenjamin Tissoiresclass TestNexio_1870_0119(BaseTest.TestTablet): 774*0bb3ed71SBenjamin Tissoires def create_device(self): 775*0bb3ed71SBenjamin Tissoires return PenDigitizer( 776*0bb3ed71SBenjamin Tissoires "uhid test nexio_1870_0119", 777*0bb3ed71SBenjamin Tissoires 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", 778*0bb3ed71SBenjamin Tissoires input_info=(BusType.USB, 0x1870, 0x0119), 779*0bb3ed71SBenjamin Tissoires ) 780*0bb3ed71SBenjamin Tissoires 781*0bb3ed71SBenjamin Tissoires 782*0bb3ed71SBenjamin Tissoires################################################################################ 783*0bb3ed71SBenjamin Tissoires# 784*0bb3ed71SBenjamin Tissoires# Windows 8 compatible devices 785*0bb3ed71SBenjamin Tissoires# 786*0bb3ed71SBenjamin Tissoires################################################################################ 787*0bb3ed71SBenjamin Tissoires 788*0bb3ed71SBenjamin Tissoires# bogus: application is 'undefined' 789*0bb3ed71SBenjamin Tissoires# class Testatmel_03eb_8409(BaseTest.TestTablet): 790*0bb3ed71SBenjamin Tissoires# def create_device(self): 791*0bb3ed71SBenjamin Tissoires# 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') 792*0bb3ed71SBenjamin Tissoires 793*0bb3ed71SBenjamin Tissoires 794*0bb3ed71SBenjamin Tissoiresclass Testatmel_03eb_840b(BaseTest.TestTablet): 795*0bb3ed71SBenjamin Tissoires def create_device(self): 796*0bb3ed71SBenjamin Tissoires return PenDigitizer( 797*0bb3ed71SBenjamin Tissoires "uhid test atmel_03eb_840b", 798*0bb3ed71SBenjamin Tissoires 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", 799*0bb3ed71SBenjamin Tissoires ) 800*0bb3ed71SBenjamin Tissoires 801*0bb3ed71SBenjamin Tissoires 802*0bb3ed71SBenjamin Tissoiresclass Testn_trig_1b96_0c01(BaseTest.TestTablet): 803*0bb3ed71SBenjamin Tissoires def create_device(self): 804*0bb3ed71SBenjamin Tissoires return PenDigitizer( 805*0bb3ed71SBenjamin Tissoires "uhid test n_trig_1b96_0c01", 806*0bb3ed71SBenjamin Tissoires 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", 807*0bb3ed71SBenjamin Tissoires ) 808*0bb3ed71SBenjamin Tissoires 809*0bb3ed71SBenjamin Tissoires 810*0bb3ed71SBenjamin Tissoiresclass Testn_trig_1b96_0c03(BaseTest.TestTablet): 811*0bb3ed71SBenjamin Tissoires def create_device(self): 812*0bb3ed71SBenjamin Tissoires return PenDigitizer( 813*0bb3ed71SBenjamin Tissoires "uhid test n_trig_1b96_0c03", 814*0bb3ed71SBenjamin Tissoires 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", 815*0bb3ed71SBenjamin Tissoires ) 816*0bb3ed71SBenjamin Tissoires 817*0bb3ed71SBenjamin Tissoires 818*0bb3ed71SBenjamin Tissoiresclass Testn_trig_1b96_0f00(BaseTest.TestTablet): 819*0bb3ed71SBenjamin Tissoires def create_device(self): 820*0bb3ed71SBenjamin Tissoires return PenDigitizer( 821*0bb3ed71SBenjamin Tissoires "uhid test n_trig_1b96_0f00", 822*0bb3ed71SBenjamin Tissoires 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", 823*0bb3ed71SBenjamin Tissoires ) 824*0bb3ed71SBenjamin Tissoires 825*0bb3ed71SBenjamin Tissoires 826*0bb3ed71SBenjamin Tissoiresclass Testn_trig_1b96_0f04(BaseTest.TestTablet): 827*0bb3ed71SBenjamin Tissoires def create_device(self): 828*0bb3ed71SBenjamin Tissoires return PenDigitizer( 829*0bb3ed71SBenjamin Tissoires "uhid test n_trig_1b96_0f04", 830*0bb3ed71SBenjamin Tissoires 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", 831*0bb3ed71SBenjamin Tissoires ) 832*0bb3ed71SBenjamin Tissoires 833*0bb3ed71SBenjamin Tissoires 834*0bb3ed71SBenjamin Tissoiresclass Testn_trig_1b96_1000(BaseTest.TestTablet): 835*0bb3ed71SBenjamin Tissoires def create_device(self): 836*0bb3ed71SBenjamin Tissoires return PenDigitizer( 837*0bb3ed71SBenjamin Tissoires "uhid test n_trig_1b96_1000", 838*0bb3ed71SBenjamin Tissoires 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", 839*0bb3ed71SBenjamin Tissoires ) 840*0bb3ed71SBenjamin Tissoires 841*0bb3ed71SBenjamin Tissoires 842*0bb3ed71SBenjamin Tissoiresclass TestGXTP_27c6_0113(BaseTest.TestTablet): 843*0bb3ed71SBenjamin Tissoires def create_device(self): 844*0bb3ed71SBenjamin Tissoires return GXTP_pen( 845*0bb3ed71SBenjamin Tissoires "uhid test GXTP_27c6_0113", 846*0bb3ed71SBenjamin Tissoires 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", 847*0bb3ed71SBenjamin Tissoires ) 848*0bb3ed71SBenjamin Tissoires 849*0bb3ed71SBenjamin Tissoires 850*0bb3ed71SBenjamin Tissoires################################################################################ 851*0bb3ed71SBenjamin Tissoires# 852*0bb3ed71SBenjamin Tissoires# Windows 8 compatible devices with USI Pen 853*0bb3ed71SBenjamin Tissoires# 854*0bb3ed71SBenjamin Tissoires################################################################################ 855*0bb3ed71SBenjamin Tissoires 856*0bb3ed71SBenjamin Tissoires 857*0bb3ed71SBenjamin Tissoiresclass TestElan_04f3_2A49(BaseTest.TestTablet): 858*0bb3ed71SBenjamin Tissoires def create_device(self): 859*0bb3ed71SBenjamin Tissoires return USIPen( 860*0bb3ed71SBenjamin Tissoires "uhid test Elan_04f3_2A49", 861*0bb3ed71SBenjamin Tissoires 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", 862*0bb3ed71SBenjamin Tissoires input_info=(BusType.I2C, 0x04F3, 0x2A49), 863*0bb3ed71SBenjamin Tissoires ) 864*0bb3ed71SBenjamin Tissoires 865*0bb3ed71SBenjamin Tissoires 866*0bb3ed71SBenjamin Tissoiresclass TestGoodix_27c6_0e00(BaseTest.TestTablet): 867*0bb3ed71SBenjamin Tissoires def create_device(self): 868*0bb3ed71SBenjamin Tissoires return USIPen( 869*0bb3ed71SBenjamin Tissoires "uhid test Elan_04f3_2A49", 870*0bb3ed71SBenjamin Tissoires 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", 871*0bb3ed71SBenjamin Tissoires input_info=(BusType.I2C, 0x27C6, 0x0E00), 872*0bb3ed71SBenjamin Tissoires ) 873