162306a36Sopenharmony_ci#!/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# -*- coding: utf-8 -*- 462306a36Sopenharmony_ci# 562306a36Sopenharmony_ci# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 662306a36Sopenharmony_ci# Copyright (c) 2017 Red Hat, Inc. 762306a36Sopenharmony_ci# 862306a36Sopenharmony_ci 962306a36Sopenharmony_cifrom . import base 1062306a36Sopenharmony_ciimport hidtools.hid 1162306a36Sopenharmony_cifrom hidtools.util import BusType 1262306a36Sopenharmony_ciimport libevdev 1362306a36Sopenharmony_ciimport logging 1462306a36Sopenharmony_ciimport pytest 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cilogger = logging.getLogger("hidtools.test.mouse") 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci# workaround https://gitlab.freedesktop.org/libevdev/python-libevdev/issues/6 1962306a36Sopenharmony_citry: 2062306a36Sopenharmony_ci libevdev.EV_REL.REL_WHEEL_HI_RES 2162306a36Sopenharmony_ciexcept AttributeError: 2262306a36Sopenharmony_ci libevdev.EV_REL.REL_WHEEL_HI_RES = libevdev.EV_REL.REL_0B 2362306a36Sopenharmony_ci libevdev.EV_REL.REL_HWHEEL_HI_RES = libevdev.EV_REL.REL_0C 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciclass InvalidHIDCommunication(Exception): 2762306a36Sopenharmony_ci pass 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciclass MouseData(object): 3162306a36Sopenharmony_ci pass 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciclass BaseMouse(base.UHIDTestDevice): 3562306a36Sopenharmony_ci def __init__(self, rdesc, name=None, input_info=None): 3662306a36Sopenharmony_ci assert rdesc is not None 3762306a36Sopenharmony_ci super().__init__(name, "Mouse", input_info=input_info, rdesc=rdesc) 3862306a36Sopenharmony_ci self.left = False 3962306a36Sopenharmony_ci self.right = False 4062306a36Sopenharmony_ci self.middle = False 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci def create_report(self, x, y, buttons=None, wheels=None, reportID=None): 4362306a36Sopenharmony_ci """ 4462306a36Sopenharmony_ci Return an input report for this device. 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci :param x: relative x 4762306a36Sopenharmony_ci :param y: relative y 4862306a36Sopenharmony_ci :param buttons: a (l, r, m) tuple of bools for the button states, 4962306a36Sopenharmony_ci where ``None`` is "leave unchanged" 5062306a36Sopenharmony_ci :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for 5162306a36Sopenharmony_ci the two wheels 5262306a36Sopenharmony_ci :param reportID: the numeric report ID for this report, if needed 5362306a36Sopenharmony_ci """ 5462306a36Sopenharmony_ci if buttons is not None: 5562306a36Sopenharmony_ci l, r, m = buttons 5662306a36Sopenharmony_ci if l is not None: 5762306a36Sopenharmony_ci self.left = l 5862306a36Sopenharmony_ci if r is not None: 5962306a36Sopenharmony_ci self.right = r 6062306a36Sopenharmony_ci if m is not None: 6162306a36Sopenharmony_ci self.middle = m 6262306a36Sopenharmony_ci left = self.left 6362306a36Sopenharmony_ci right = self.right 6462306a36Sopenharmony_ci middle = self.middle 6562306a36Sopenharmony_ci # Note: the BaseMouse doesn't actually have a wheel but the 6662306a36Sopenharmony_ci # create_report magic only fills in those fields exist, so let's 6762306a36Sopenharmony_ci # make this generic here. 6862306a36Sopenharmony_ci wheel, acpan = 0, 0 6962306a36Sopenharmony_ci if wheels is not None: 7062306a36Sopenharmony_ci if isinstance(wheels, tuple): 7162306a36Sopenharmony_ci wheel = wheels[0] 7262306a36Sopenharmony_ci acpan = wheels[1] 7362306a36Sopenharmony_ci else: 7462306a36Sopenharmony_ci wheel = wheels 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci reportID = reportID or self.default_reportID 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci mouse = MouseData() 7962306a36Sopenharmony_ci mouse.b1 = int(left) 8062306a36Sopenharmony_ci mouse.b2 = int(right) 8162306a36Sopenharmony_ci mouse.b3 = int(middle) 8262306a36Sopenharmony_ci mouse.x = x 8362306a36Sopenharmony_ci mouse.y = y 8462306a36Sopenharmony_ci mouse.wheel = wheel 8562306a36Sopenharmony_ci mouse.acpan = acpan 8662306a36Sopenharmony_ci return super().create_report(mouse, reportID=reportID) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci def event(self, x, y, buttons=None, wheels=None): 8962306a36Sopenharmony_ci """ 9062306a36Sopenharmony_ci Send an input event on the default report ID. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci :param x: relative x 9362306a36Sopenharmony_ci :param y: relative y 9462306a36Sopenharmony_ci :param buttons: a (l, r, m) tuple of bools for the button states, 9562306a36Sopenharmony_ci where ``None`` is "leave unchanged" 9662306a36Sopenharmony_ci :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for 9762306a36Sopenharmony_ci the two wheels 9862306a36Sopenharmony_ci """ 9962306a36Sopenharmony_ci r = self.create_report(x, y, buttons, wheels) 10062306a36Sopenharmony_ci self.call_input_event(r) 10162306a36Sopenharmony_ci return [r] 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciclass ButtonMouse(BaseMouse): 10562306a36Sopenharmony_ci # fmt: off 10662306a36Sopenharmony_ci report_descriptor = [ 10762306a36Sopenharmony_ci 0x05, 0x01, # .Usage Page (Generic Desktop) 0 10862306a36Sopenharmony_ci 0x09, 0x02, # .Usage (Mouse) 2 10962306a36Sopenharmony_ci 0xa1, 0x01, # .Collection (Application) 4 11062306a36Sopenharmony_ci 0x09, 0x02, # ..Usage (Mouse) 6 11162306a36Sopenharmony_ci 0xa1, 0x02, # ..Collection (Logical) 8 11262306a36Sopenharmony_ci 0x09, 0x01, # ...Usage (Pointer) 10 11362306a36Sopenharmony_ci 0xa1, 0x00, # ...Collection (Physical) 12 11462306a36Sopenharmony_ci 0x05, 0x09, # ....Usage Page (Button) 14 11562306a36Sopenharmony_ci 0x19, 0x01, # ....Usage Minimum (1) 16 11662306a36Sopenharmony_ci 0x29, 0x03, # ....Usage Maximum (3) 18 11762306a36Sopenharmony_ci 0x15, 0x00, # ....Logical Minimum (0) 20 11862306a36Sopenharmony_ci 0x25, 0x01, # ....Logical Maximum (1) 22 11962306a36Sopenharmony_ci 0x75, 0x01, # ....Report Size (1) 24 12062306a36Sopenharmony_ci 0x95, 0x03, # ....Report Count (3) 26 12162306a36Sopenharmony_ci 0x81, 0x02, # ....Input (Data,Var,Abs) 28 12262306a36Sopenharmony_ci 0x75, 0x05, # ....Report Size (5) 30 12362306a36Sopenharmony_ci 0x95, 0x01, # ....Report Count (1) 32 12462306a36Sopenharmony_ci 0x81, 0x03, # ....Input (Cnst,Var,Abs) 34 12562306a36Sopenharmony_ci 0x05, 0x01, # ....Usage Page (Generic Desktop) 36 12662306a36Sopenharmony_ci 0x09, 0x30, # ....Usage (X) 38 12762306a36Sopenharmony_ci 0x09, 0x31, # ....Usage (Y) 40 12862306a36Sopenharmony_ci 0x15, 0x81, # ....Logical Minimum (-127) 42 12962306a36Sopenharmony_ci 0x25, 0x7f, # ....Logical Maximum (127) 44 13062306a36Sopenharmony_ci 0x75, 0x08, # ....Report Size (8) 46 13162306a36Sopenharmony_ci 0x95, 0x02, # ....Report Count (2) 48 13262306a36Sopenharmony_ci 0x81, 0x06, # ....Input (Data,Var,Rel) 50 13362306a36Sopenharmony_ci 0xc0, # ...End Collection 52 13462306a36Sopenharmony_ci 0xc0, # ..End Collection 53 13562306a36Sopenharmony_ci 0xc0, # .End Collection 54 13662306a36Sopenharmony_ci ] 13762306a36Sopenharmony_ci # fmt: on 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 14062306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci def fake_report(self, x, y, buttons): 14362306a36Sopenharmony_ci if buttons is not None: 14462306a36Sopenharmony_ci left, right, middle = buttons 14562306a36Sopenharmony_ci if left is None: 14662306a36Sopenharmony_ci left = self.left 14762306a36Sopenharmony_ci if right is None: 14862306a36Sopenharmony_ci right = self.right 14962306a36Sopenharmony_ci if middle is None: 15062306a36Sopenharmony_ci middle = self.middle 15162306a36Sopenharmony_ci else: 15262306a36Sopenharmony_ci left = self.left 15362306a36Sopenharmony_ci right = self.right 15462306a36Sopenharmony_ci middle = self.middle 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci button_mask = sum(1 << i for i, b in enumerate([left, right, middle]) if b) 15762306a36Sopenharmony_ci x = max(-127, min(127, x)) 15862306a36Sopenharmony_ci y = max(-127, min(127, y)) 15962306a36Sopenharmony_ci x = hidtools.util.to_twos_comp(x, 8) 16062306a36Sopenharmony_ci y = hidtools.util.to_twos_comp(y, 8) 16162306a36Sopenharmony_ci return [button_mask, x, y] 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciclass WheelMouse(ButtonMouse): 16562306a36Sopenharmony_ci # fmt: off 16662306a36Sopenharmony_ci report_descriptor = [ 16762306a36Sopenharmony_ci 0x05, 0x01, # Usage Page (Generic Desktop) 0 16862306a36Sopenharmony_ci 0x09, 0x02, # Usage (Mouse) 2 16962306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 4 17062306a36Sopenharmony_ci 0x05, 0x09, # .Usage Page (Button) 6 17162306a36Sopenharmony_ci 0x19, 0x01, # .Usage Minimum (1) 8 17262306a36Sopenharmony_ci 0x29, 0x03, # .Usage Maximum (3) 10 17362306a36Sopenharmony_ci 0x15, 0x00, # .Logical Minimum (0) 12 17462306a36Sopenharmony_ci 0x25, 0x01, # .Logical Maximum (1) 14 17562306a36Sopenharmony_ci 0x95, 0x03, # .Report Count (3) 16 17662306a36Sopenharmony_ci 0x75, 0x01, # .Report Size (1) 18 17762306a36Sopenharmony_ci 0x81, 0x02, # .Input (Data,Var,Abs) 20 17862306a36Sopenharmony_ci 0x95, 0x01, # .Report Count (1) 22 17962306a36Sopenharmony_ci 0x75, 0x05, # .Report Size (5) 24 18062306a36Sopenharmony_ci 0x81, 0x03, # .Input (Cnst,Var,Abs) 26 18162306a36Sopenharmony_ci 0x05, 0x01, # .Usage Page (Generic Desktop) 28 18262306a36Sopenharmony_ci 0x09, 0x01, # .Usage (Pointer) 30 18362306a36Sopenharmony_ci 0xa1, 0x00, # .Collection (Physical) 32 18462306a36Sopenharmony_ci 0x09, 0x30, # ..Usage (X) 34 18562306a36Sopenharmony_ci 0x09, 0x31, # ..Usage (Y) 36 18662306a36Sopenharmony_ci 0x15, 0x81, # ..Logical Minimum (-127) 38 18762306a36Sopenharmony_ci 0x25, 0x7f, # ..Logical Maximum (127) 40 18862306a36Sopenharmony_ci 0x75, 0x08, # ..Report Size (8) 42 18962306a36Sopenharmony_ci 0x95, 0x02, # ..Report Count (2) 44 19062306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 46 19162306a36Sopenharmony_ci 0xc0, # .End Collection 48 19262306a36Sopenharmony_ci 0x09, 0x38, # .Usage (Wheel) 49 19362306a36Sopenharmony_ci 0x15, 0x81, # .Logical Minimum (-127) 51 19462306a36Sopenharmony_ci 0x25, 0x7f, # .Logical Maximum (127) 53 19562306a36Sopenharmony_ci 0x75, 0x08, # .Report Size (8) 55 19662306a36Sopenharmony_ci 0x95, 0x01, # .Report Count (1) 57 19762306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 59 19862306a36Sopenharmony_ci 0xc0, # End Collection 61 19962306a36Sopenharmony_ci ] 20062306a36Sopenharmony_ci # fmt: on 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 20362306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 20462306a36Sopenharmony_ci self.wheel_multiplier = 1 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciclass TwoWheelMouse(WheelMouse): 20862306a36Sopenharmony_ci # fmt: off 20962306a36Sopenharmony_ci report_descriptor = [ 21062306a36Sopenharmony_ci 0x05, 0x01, # Usage Page (Generic Desktop) 0 21162306a36Sopenharmony_ci 0x09, 0x02, # Usage (Mouse) 2 21262306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 4 21362306a36Sopenharmony_ci 0x09, 0x01, # .Usage (Pointer) 6 21462306a36Sopenharmony_ci 0xa1, 0x00, # .Collection (Physical) 8 21562306a36Sopenharmony_ci 0x05, 0x09, # ..Usage Page (Button) 10 21662306a36Sopenharmony_ci 0x19, 0x01, # ..Usage Minimum (1) 12 21762306a36Sopenharmony_ci 0x29, 0x10, # ..Usage Maximum (16) 14 21862306a36Sopenharmony_ci 0x15, 0x00, # ..Logical Minimum (0) 16 21962306a36Sopenharmony_ci 0x25, 0x01, # ..Logical Maximum (1) 18 22062306a36Sopenharmony_ci 0x95, 0x10, # ..Report Count (16) 20 22162306a36Sopenharmony_ci 0x75, 0x01, # ..Report Size (1) 22 22262306a36Sopenharmony_ci 0x81, 0x02, # ..Input (Data,Var,Abs) 24 22362306a36Sopenharmony_ci 0x05, 0x01, # ..Usage Page (Generic Desktop) 26 22462306a36Sopenharmony_ci 0x16, 0x01, 0x80, # ..Logical Minimum (-32767) 28 22562306a36Sopenharmony_ci 0x26, 0xff, 0x7f, # ..Logical Maximum (32767) 31 22662306a36Sopenharmony_ci 0x75, 0x10, # ..Report Size (16) 34 22762306a36Sopenharmony_ci 0x95, 0x02, # ..Report Count (2) 36 22862306a36Sopenharmony_ci 0x09, 0x30, # ..Usage (X) 38 22962306a36Sopenharmony_ci 0x09, 0x31, # ..Usage (Y) 40 23062306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 42 23162306a36Sopenharmony_ci 0x15, 0x81, # ..Logical Minimum (-127) 44 23262306a36Sopenharmony_ci 0x25, 0x7f, # ..Logical Maximum (127) 46 23362306a36Sopenharmony_ci 0x75, 0x08, # ..Report Size (8) 48 23462306a36Sopenharmony_ci 0x95, 0x01, # ..Report Count (1) 50 23562306a36Sopenharmony_ci 0x09, 0x38, # ..Usage (Wheel) 52 23662306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 54 23762306a36Sopenharmony_ci 0x05, 0x0c, # ..Usage Page (Consumer Devices) 56 23862306a36Sopenharmony_ci 0x0a, 0x38, 0x02, # ..Usage (AC Pan) 58 23962306a36Sopenharmony_ci 0x95, 0x01, # ..Report Count (1) 61 24062306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 63 24162306a36Sopenharmony_ci 0xc0, # .End Collection 65 24262306a36Sopenharmony_ci 0xc0, # End Collection 66 24362306a36Sopenharmony_ci ] 24462306a36Sopenharmony_ci # fmt: on 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 24762306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 24862306a36Sopenharmony_ci self.hwheel_multiplier = 1 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ciclass MIDongleMIWirelessMouse(TwoWheelMouse): 25262306a36Sopenharmony_ci # fmt: off 25362306a36Sopenharmony_ci report_descriptor = [ 25462306a36Sopenharmony_ci 0x05, 0x01, # Usage Page (Generic Desktop) 25562306a36Sopenharmony_ci 0x09, 0x02, # Usage (Mouse) 25662306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 25762306a36Sopenharmony_ci 0x85, 0x01, # .Report ID (1) 25862306a36Sopenharmony_ci 0x09, 0x01, # .Usage (Pointer) 25962306a36Sopenharmony_ci 0xa1, 0x00, # .Collection (Physical) 26062306a36Sopenharmony_ci 0x95, 0x05, # ..Report Count (5) 26162306a36Sopenharmony_ci 0x75, 0x01, # ..Report Size (1) 26262306a36Sopenharmony_ci 0x05, 0x09, # ..Usage Page (Button) 26362306a36Sopenharmony_ci 0x19, 0x01, # ..Usage Minimum (1) 26462306a36Sopenharmony_ci 0x29, 0x05, # ..Usage Maximum (5) 26562306a36Sopenharmony_ci 0x15, 0x00, # ..Logical Minimum (0) 26662306a36Sopenharmony_ci 0x25, 0x01, # ..Logical Maximum (1) 26762306a36Sopenharmony_ci 0x81, 0x02, # ..Input (Data,Var,Abs) 26862306a36Sopenharmony_ci 0x95, 0x01, # ..Report Count (1) 26962306a36Sopenharmony_ci 0x75, 0x03, # ..Report Size (3) 27062306a36Sopenharmony_ci 0x81, 0x01, # ..Input (Cnst,Arr,Abs) 27162306a36Sopenharmony_ci 0x75, 0x08, # ..Report Size (8) 27262306a36Sopenharmony_ci 0x95, 0x01, # ..Report Count (1) 27362306a36Sopenharmony_ci 0x05, 0x01, # ..Usage Page (Generic Desktop) 27462306a36Sopenharmony_ci 0x09, 0x38, # ..Usage (Wheel) 27562306a36Sopenharmony_ci 0x15, 0x81, # ..Logical Minimum (-127) 27662306a36Sopenharmony_ci 0x25, 0x7f, # ..Logical Maximum (127) 27762306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 27862306a36Sopenharmony_ci 0x05, 0x0c, # ..Usage Page (Consumer Devices) 27962306a36Sopenharmony_ci 0x0a, 0x38, 0x02, # ..Usage (AC Pan) 28062306a36Sopenharmony_ci 0x95, 0x01, # ..Report Count (1) 28162306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 28262306a36Sopenharmony_ci 0xc0, # .End Collection 28362306a36Sopenharmony_ci 0x85, 0x02, # .Report ID (2) 28462306a36Sopenharmony_ci 0x09, 0x01, # .Usage (Consumer Control) 28562306a36Sopenharmony_ci 0xa1, 0x00, # .Collection (Physical) 28662306a36Sopenharmony_ci 0x75, 0x0c, # ..Report Size (12) 28762306a36Sopenharmony_ci 0x95, 0x02, # ..Report Count (2) 28862306a36Sopenharmony_ci 0x05, 0x01, # ..Usage Page (Generic Desktop) 28962306a36Sopenharmony_ci 0x09, 0x30, # ..Usage (X) 29062306a36Sopenharmony_ci 0x09, 0x31, # ..Usage (Y) 29162306a36Sopenharmony_ci 0x16, 0x01, 0xf8, # ..Logical Minimum (-2047) 29262306a36Sopenharmony_ci 0x26, 0xff, 0x07, # ..Logical Maximum (2047) 29362306a36Sopenharmony_ci 0x81, 0x06, # ..Input (Data,Var,Rel) 29462306a36Sopenharmony_ci 0xc0, # .End Collection 29562306a36Sopenharmony_ci 0xc0, # End Collection 29662306a36Sopenharmony_ci 0x05, 0x0c, # Usage Page (Consumer Devices) 29762306a36Sopenharmony_ci 0x09, 0x01, # Usage (Consumer Control) 29862306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 29962306a36Sopenharmony_ci 0x85, 0x03, # .Report ID (3) 30062306a36Sopenharmony_ci 0x15, 0x00, # .Logical Minimum (0) 30162306a36Sopenharmony_ci 0x25, 0x01, # .Logical Maximum (1) 30262306a36Sopenharmony_ci 0x75, 0x01, # .Report Size (1) 30362306a36Sopenharmony_ci 0x95, 0x01, # .Report Count (1) 30462306a36Sopenharmony_ci 0x09, 0xcd, # .Usage (Play/Pause) 30562306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 30662306a36Sopenharmony_ci 0x0a, 0x83, 0x01, # .Usage (AL Consumer Control Config) 30762306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 30862306a36Sopenharmony_ci 0x09, 0xb5, # .Usage (Scan Next Track) 30962306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 31062306a36Sopenharmony_ci 0x09, 0xb6, # .Usage (Scan Previous Track) 31162306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 31262306a36Sopenharmony_ci 0x09, 0xea, # .Usage (Volume Down) 31362306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 31462306a36Sopenharmony_ci 0x09, 0xe9, # .Usage (Volume Up) 31562306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 31662306a36Sopenharmony_ci 0x0a, 0x25, 0x02, # .Usage (AC Forward) 31762306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 31862306a36Sopenharmony_ci 0x0a, 0x24, 0x02, # .Usage (AC Back) 31962306a36Sopenharmony_ci 0x81, 0x06, # .Input (Data,Var,Rel) 32062306a36Sopenharmony_ci 0xc0, # End Collection 32162306a36Sopenharmony_ci ] 32262306a36Sopenharmony_ci # fmt: on 32362306a36Sopenharmony_ci device_input_info = (BusType.USB, 0x2717, 0x003B) 32462306a36Sopenharmony_ci device_name = "uhid test MI Dongle MI Wireless Mouse" 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci def __init__( 32762306a36Sopenharmony_ci self, rdesc=report_descriptor, name=device_name, input_info=device_input_info 32862306a36Sopenharmony_ci ): 32962306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci def event(self, x, y, buttons=None, wheels=None): 33262306a36Sopenharmony_ci # this mouse spreads the relative pointer and the mouse buttons 33362306a36Sopenharmony_ci # onto 2 distinct reports 33462306a36Sopenharmony_ci rs = [] 33562306a36Sopenharmony_ci r = self.create_report(x, y, buttons, wheels, reportID=1) 33662306a36Sopenharmony_ci self.call_input_event(r) 33762306a36Sopenharmony_ci rs.append(r) 33862306a36Sopenharmony_ci r = self.create_report(x, y, buttons, reportID=2) 33962306a36Sopenharmony_ci self.call_input_event(r) 34062306a36Sopenharmony_ci rs.append(r) 34162306a36Sopenharmony_ci return rs 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ciclass ResolutionMultiplierMouse(TwoWheelMouse): 34562306a36Sopenharmony_ci # fmt: off 34662306a36Sopenharmony_ci report_descriptor = [ 34762306a36Sopenharmony_ci 0x05, 0x01, # Usage Page (Generic Desktop) 83 34862306a36Sopenharmony_ci 0x09, 0x02, # Usage (Mouse) 85 34962306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 87 35062306a36Sopenharmony_ci 0x05, 0x01, # .Usage Page (Generic Desktop) 89 35162306a36Sopenharmony_ci 0x09, 0x02, # .Usage (Mouse) 91 35262306a36Sopenharmony_ci 0xa1, 0x02, # .Collection (Logical) 93 35362306a36Sopenharmony_ci 0x85, 0x11, # ..Report ID (17) 95 35462306a36Sopenharmony_ci 0x09, 0x01, # ..Usage (Pointer) 97 35562306a36Sopenharmony_ci 0xa1, 0x00, # ..Collection (Physical) 99 35662306a36Sopenharmony_ci 0x05, 0x09, # ...Usage Page (Button) 101 35762306a36Sopenharmony_ci 0x19, 0x01, # ...Usage Minimum (1) 103 35862306a36Sopenharmony_ci 0x29, 0x03, # ...Usage Maximum (3) 105 35962306a36Sopenharmony_ci 0x95, 0x03, # ...Report Count (3) 107 36062306a36Sopenharmony_ci 0x75, 0x01, # ...Report Size (1) 109 36162306a36Sopenharmony_ci 0x25, 0x01, # ...Logical Maximum (1) 111 36262306a36Sopenharmony_ci 0x81, 0x02, # ...Input (Data,Var,Abs) 113 36362306a36Sopenharmony_ci 0x95, 0x01, # ...Report Count (1) 115 36462306a36Sopenharmony_ci 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 117 36562306a36Sopenharmony_ci 0x09, 0x05, # ...Usage (Vendor Usage 0x05) 119 36662306a36Sopenharmony_ci 0x81, 0x02, # ...Input (Data,Var,Abs) 121 36762306a36Sopenharmony_ci 0x95, 0x03, # ...Report Count (3) 123 36862306a36Sopenharmony_ci 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 125 36962306a36Sopenharmony_ci 0x05, 0x01, # ...Usage Page (Generic Desktop) 127 37062306a36Sopenharmony_ci 0x09, 0x30, # ...Usage (X) 129 37162306a36Sopenharmony_ci 0x09, 0x31, # ...Usage (Y) 131 37262306a36Sopenharmony_ci 0x95, 0x02, # ...Report Count (2) 133 37362306a36Sopenharmony_ci 0x75, 0x08, # ...Report Size (8) 135 37462306a36Sopenharmony_ci 0x15, 0x81, # ...Logical Minimum (-127) 137 37562306a36Sopenharmony_ci 0x25, 0x7f, # ...Logical Maximum (127) 139 37662306a36Sopenharmony_ci 0x81, 0x06, # ...Input (Data,Var,Rel) 141 37762306a36Sopenharmony_ci 0xa1, 0x02, # ...Collection (Logical) 143 37862306a36Sopenharmony_ci 0x85, 0x12, # ....Report ID (18) 145 37962306a36Sopenharmony_ci 0x09, 0x48, # ....Usage (Resolution Multiplier) 147 38062306a36Sopenharmony_ci 0x95, 0x01, # ....Report Count (1) 149 38162306a36Sopenharmony_ci 0x75, 0x02, # ....Report Size (2) 151 38262306a36Sopenharmony_ci 0x15, 0x00, # ....Logical Minimum (0) 153 38362306a36Sopenharmony_ci 0x25, 0x01, # ....Logical Maximum (1) 155 38462306a36Sopenharmony_ci 0x35, 0x01, # ....Physical Minimum (1) 157 38562306a36Sopenharmony_ci 0x45, 0x04, # ....Physical Maximum (4) 159 38662306a36Sopenharmony_ci 0xb1, 0x02, # ....Feature (Data,Var,Abs) 161 38762306a36Sopenharmony_ci 0x35, 0x00, # ....Physical Minimum (0) 163 38862306a36Sopenharmony_ci 0x45, 0x00, # ....Physical Maximum (0) 165 38962306a36Sopenharmony_ci 0x75, 0x06, # ....Report Size (6) 167 39062306a36Sopenharmony_ci 0xb1, 0x01, # ....Feature (Cnst,Arr,Abs) 169 39162306a36Sopenharmony_ci 0x85, 0x11, # ....Report ID (17) 171 39262306a36Sopenharmony_ci 0x09, 0x38, # ....Usage (Wheel) 173 39362306a36Sopenharmony_ci 0x15, 0x81, # ....Logical Minimum (-127) 175 39462306a36Sopenharmony_ci 0x25, 0x7f, # ....Logical Maximum (127) 177 39562306a36Sopenharmony_ci 0x75, 0x08, # ....Report Size (8) 179 39662306a36Sopenharmony_ci 0x81, 0x06, # ....Input (Data,Var,Rel) 181 39762306a36Sopenharmony_ci 0xc0, # ...End Collection 183 39862306a36Sopenharmony_ci 0x05, 0x0c, # ...Usage Page (Consumer Devices) 184 39962306a36Sopenharmony_ci 0x75, 0x08, # ...Report Size (8) 186 40062306a36Sopenharmony_ci 0x0a, 0x38, 0x02, # ...Usage (AC Pan) 188 40162306a36Sopenharmony_ci 0x81, 0x06, # ...Input (Data,Var,Rel) 191 40262306a36Sopenharmony_ci 0xc0, # ..End Collection 193 40362306a36Sopenharmony_ci 0xc0, # .End Collection 194 40462306a36Sopenharmony_ci 0xc0, # End Collection 195 40562306a36Sopenharmony_ci ] 40662306a36Sopenharmony_ci # fmt: on 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 40962306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 41062306a36Sopenharmony_ci self.default_reportID = 0x11 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci # Feature Report 12, multiplier Feature value must be set to 0b01, 41362306a36Sopenharmony_ci # i.e. 1. We should extract that from the descriptor instead 41462306a36Sopenharmony_ci # of hardcoding it here, but meanwhile this will do. 41562306a36Sopenharmony_ci self.set_feature_report = [0x12, 0x1] 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci def set_report(self, req, rnum, rtype, data): 41862306a36Sopenharmony_ci if rtype != self.UHID_FEATURE_REPORT: 41962306a36Sopenharmony_ci raise InvalidHIDCommunication(f"Unexpected report type: {rtype}") 42062306a36Sopenharmony_ci if rnum != 0x12: 42162306a36Sopenharmony_ci raise InvalidHIDCommunication(f"Unexpected report number: {rnum}") 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci if data != self.set_feature_report: 42462306a36Sopenharmony_ci raise InvalidHIDCommunication( 42562306a36Sopenharmony_ci f"Unexpected data: {data}, expected {self.set_feature_report}" 42662306a36Sopenharmony_ci ) 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci self.wheel_multiplier = 4 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci return 0 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ciclass BadResolutionMultiplierMouse(ResolutionMultiplierMouse): 43462306a36Sopenharmony_ci def set_report(self, req, rnum, rtype, data): 43562306a36Sopenharmony_ci super().set_report(req, rnum, rtype, data) 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci self.wheel_multiplier = 1 43862306a36Sopenharmony_ci self.hwheel_multiplier = 1 43962306a36Sopenharmony_ci return 32 # EPIPE 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ciclass ResolutionMultiplierHWheelMouse(TwoWheelMouse): 44362306a36Sopenharmony_ci # fmt: off 44462306a36Sopenharmony_ci report_descriptor = [ 44562306a36Sopenharmony_ci 0x05, 0x01, # Usage Page (Generic Desktop) 0 44662306a36Sopenharmony_ci 0x09, 0x02, # Usage (Mouse) 2 44762306a36Sopenharmony_ci 0xa1, 0x01, # Collection (Application) 4 44862306a36Sopenharmony_ci 0x05, 0x01, # .Usage Page (Generic Desktop) 6 44962306a36Sopenharmony_ci 0x09, 0x02, # .Usage (Mouse) 8 45062306a36Sopenharmony_ci 0xa1, 0x02, # .Collection (Logical) 10 45162306a36Sopenharmony_ci 0x85, 0x1a, # ..Report ID (26) 12 45262306a36Sopenharmony_ci 0x09, 0x01, # ..Usage (Pointer) 14 45362306a36Sopenharmony_ci 0xa1, 0x00, # ..Collection (Physical) 16 45462306a36Sopenharmony_ci 0x05, 0x09, # ...Usage Page (Button) 18 45562306a36Sopenharmony_ci 0x19, 0x01, # ...Usage Minimum (1) 20 45662306a36Sopenharmony_ci 0x29, 0x05, # ...Usage Maximum (5) 22 45762306a36Sopenharmony_ci 0x95, 0x05, # ...Report Count (5) 24 45862306a36Sopenharmony_ci 0x75, 0x01, # ...Report Size (1) 26 45962306a36Sopenharmony_ci 0x15, 0x00, # ...Logical Minimum (0) 28 46062306a36Sopenharmony_ci 0x25, 0x01, # ...Logical Maximum (1) 30 46162306a36Sopenharmony_ci 0x81, 0x02, # ...Input (Data,Var,Abs) 32 46262306a36Sopenharmony_ci 0x75, 0x03, # ...Report Size (3) 34 46362306a36Sopenharmony_ci 0x95, 0x01, # ...Report Count (1) 36 46462306a36Sopenharmony_ci 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 38 46562306a36Sopenharmony_ci 0x05, 0x01, # ...Usage Page (Generic Desktop) 40 46662306a36Sopenharmony_ci 0x09, 0x30, # ...Usage (X) 42 46762306a36Sopenharmony_ci 0x09, 0x31, # ...Usage (Y) 44 46862306a36Sopenharmony_ci 0x95, 0x02, # ...Report Count (2) 46 46962306a36Sopenharmony_ci 0x75, 0x10, # ...Report Size (16) 48 47062306a36Sopenharmony_ci 0x16, 0x01, 0x80, # ...Logical Minimum (-32767) 50 47162306a36Sopenharmony_ci 0x26, 0xff, 0x7f, # ...Logical Maximum (32767) 53 47262306a36Sopenharmony_ci 0x81, 0x06, # ...Input (Data,Var,Rel) 56 47362306a36Sopenharmony_ci 0xa1, 0x02, # ...Collection (Logical) 58 47462306a36Sopenharmony_ci 0x85, 0x12, # ....Report ID (18) 60 47562306a36Sopenharmony_ci 0x09, 0x48, # ....Usage (Resolution Multiplier) 62 47662306a36Sopenharmony_ci 0x95, 0x01, # ....Report Count (1) 64 47762306a36Sopenharmony_ci 0x75, 0x02, # ....Report Size (2) 66 47862306a36Sopenharmony_ci 0x15, 0x00, # ....Logical Minimum (0) 68 47962306a36Sopenharmony_ci 0x25, 0x01, # ....Logical Maximum (1) 70 48062306a36Sopenharmony_ci 0x35, 0x01, # ....Physical Minimum (1) 72 48162306a36Sopenharmony_ci 0x45, 0x0c, # ....Physical Maximum (12) 74 48262306a36Sopenharmony_ci 0xb1, 0x02, # ....Feature (Data,Var,Abs) 76 48362306a36Sopenharmony_ci 0x85, 0x1a, # ....Report ID (26) 78 48462306a36Sopenharmony_ci 0x09, 0x38, # ....Usage (Wheel) 80 48562306a36Sopenharmony_ci 0x35, 0x00, # ....Physical Minimum (0) 82 48662306a36Sopenharmony_ci 0x45, 0x00, # ....Physical Maximum (0) 84 48762306a36Sopenharmony_ci 0x95, 0x01, # ....Report Count (1) 86 48862306a36Sopenharmony_ci 0x75, 0x10, # ....Report Size (16) 88 48962306a36Sopenharmony_ci 0x16, 0x01, 0x80, # ....Logical Minimum (-32767) 90 49062306a36Sopenharmony_ci 0x26, 0xff, 0x7f, # ....Logical Maximum (32767) 93 49162306a36Sopenharmony_ci 0x81, 0x06, # ....Input (Data,Var,Rel) 96 49262306a36Sopenharmony_ci 0xc0, # ...End Collection 98 49362306a36Sopenharmony_ci 0xa1, 0x02, # ...Collection (Logical) 99 49462306a36Sopenharmony_ci 0x85, 0x12, # ....Report ID (18) 101 49562306a36Sopenharmony_ci 0x09, 0x48, # ....Usage (Resolution Multiplier) 103 49662306a36Sopenharmony_ci 0x75, 0x02, # ....Report Size (2) 105 49762306a36Sopenharmony_ci 0x15, 0x00, # ....Logical Minimum (0) 107 49862306a36Sopenharmony_ci 0x25, 0x01, # ....Logical Maximum (1) 109 49962306a36Sopenharmony_ci 0x35, 0x01, # ....Physical Minimum (1) 111 50062306a36Sopenharmony_ci 0x45, 0x0c, # ....Physical Maximum (12) 113 50162306a36Sopenharmony_ci 0xb1, 0x02, # ....Feature (Data,Var,Abs) 115 50262306a36Sopenharmony_ci 0x35, 0x00, # ....Physical Minimum (0) 117 50362306a36Sopenharmony_ci 0x45, 0x00, # ....Physical Maximum (0) 119 50462306a36Sopenharmony_ci 0x75, 0x04, # ....Report Size (4) 121 50562306a36Sopenharmony_ci 0xb1, 0x01, # ....Feature (Cnst,Arr,Abs) 123 50662306a36Sopenharmony_ci 0x85, 0x1a, # ....Report ID (26) 125 50762306a36Sopenharmony_ci 0x05, 0x0c, # ....Usage Page (Consumer Devices) 127 50862306a36Sopenharmony_ci 0x95, 0x01, # ....Report Count (1) 129 50962306a36Sopenharmony_ci 0x75, 0x10, # ....Report Size (16) 131 51062306a36Sopenharmony_ci 0x16, 0x01, 0x80, # ....Logical Minimum (-32767) 133 51162306a36Sopenharmony_ci 0x26, 0xff, 0x7f, # ....Logical Maximum (32767) 136 51262306a36Sopenharmony_ci 0x0a, 0x38, 0x02, # ....Usage (AC Pan) 139 51362306a36Sopenharmony_ci 0x81, 0x06, # ....Input (Data,Var,Rel) 142 51462306a36Sopenharmony_ci 0xc0, # ...End Collection 144 51562306a36Sopenharmony_ci 0xc0, # ..End Collection 145 51662306a36Sopenharmony_ci 0xc0, # .End Collection 146 51762306a36Sopenharmony_ci 0xc0, # End Collection 147 51862306a36Sopenharmony_ci ] 51962306a36Sopenharmony_ci # fmt: on 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 52262306a36Sopenharmony_ci super().__init__(rdesc, name, input_info) 52362306a36Sopenharmony_ci self.default_reportID = 0x1A 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci # Feature Report 12, multiplier Feature value must be set to 0b0101, 52662306a36Sopenharmony_ci # i.e. 5. We should extract that from the descriptor instead 52762306a36Sopenharmony_ci # of hardcoding it here, but meanwhile this will do. 52862306a36Sopenharmony_ci self.set_feature_report = [0x12, 0x5] 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci def set_report(self, req, rnum, rtype, data): 53162306a36Sopenharmony_ci super().set_report(req, rnum, rtype, data) 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci self.wheel_multiplier = 12 53462306a36Sopenharmony_ci self.hwheel_multiplier = 12 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci return 0 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ciclass BaseTest: 54062306a36Sopenharmony_ci class TestMouse(base.BaseTestCase.TestUhid): 54162306a36Sopenharmony_ci def test_buttons(self): 54262306a36Sopenharmony_ci """check for button reliability.""" 54362306a36Sopenharmony_ci uhdev = self.uhdev 54462306a36Sopenharmony_ci evdev = uhdev.get_evdev() 54562306a36Sopenharmony_ci syn_event = self.syn_event 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci r = uhdev.event(0, 0, (None, True, None)) 54862306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1) 54962306a36Sopenharmony_ci events = uhdev.next_sync_events() 55062306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 55162306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 55262306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci r = uhdev.event(0, 0, (None, False, None)) 55562306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0) 55662306a36Sopenharmony_ci events = uhdev.next_sync_events() 55762306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 55862306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 55962306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci r = uhdev.event(0, 0, (None, None, True)) 56262306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 1) 56362306a36Sopenharmony_ci events = uhdev.next_sync_events() 56462306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 56562306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 56662306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 1 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci r = uhdev.event(0, 0, (None, None, False)) 56962306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 0) 57062306a36Sopenharmony_ci events = uhdev.next_sync_events() 57162306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 57262306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 57362306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 0 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci r = uhdev.event(0, 0, (True, None, None)) 57662306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) 57762306a36Sopenharmony_ci events = uhdev.next_sync_events() 57862306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 57962306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 58062306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci r = uhdev.event(0, 0, (False, None, None)) 58362306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) 58462306a36Sopenharmony_ci events = uhdev.next_sync_events() 58562306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 58662306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 58762306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci r = uhdev.event(0, 0, (True, True, None)) 59062306a36Sopenharmony_ci expected_event0 = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) 59162306a36Sopenharmony_ci expected_event1 = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1) 59262306a36Sopenharmony_ci events = uhdev.next_sync_events() 59362306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 59462306a36Sopenharmony_ci self.assertInputEventsIn( 59562306a36Sopenharmony_ci (syn_event, expected_event0, expected_event1), events 59662306a36Sopenharmony_ci ) 59762306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 59862306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci r = uhdev.event(0, 0, (False, None, None)) 60162306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) 60262306a36Sopenharmony_ci events = uhdev.next_sync_events() 60362306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 60462306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 60562306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 60662306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci r = uhdev.event(0, 0, (None, False, None)) 60962306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0) 61062306a36Sopenharmony_ci events = uhdev.next_sync_events() 61162306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 61262306a36Sopenharmony_ci self.assertInputEventsIn((syn_event, expected_event), events) 61362306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0 61462306a36Sopenharmony_ci assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci def test_relative(self): 61762306a36Sopenharmony_ci """Check for relative events.""" 61862306a36Sopenharmony_ci uhdev = self.uhdev 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci syn_event = self.syn_event 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci r = uhdev.event(0, -1) 62362306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_Y, -1) 62462306a36Sopenharmony_ci events = uhdev.next_sync_events() 62562306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 62662306a36Sopenharmony_ci self.assertInputEvents((syn_event, expected_event), events) 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci r = uhdev.event(1, 0) 62962306a36Sopenharmony_ci expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_X, 1) 63062306a36Sopenharmony_ci events = uhdev.next_sync_events() 63162306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 63262306a36Sopenharmony_ci self.assertInputEvents((syn_event, expected_event), events) 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci r = uhdev.event(-1, 2) 63562306a36Sopenharmony_ci expected_event0 = libevdev.InputEvent(libevdev.EV_REL.REL_X, -1) 63662306a36Sopenharmony_ci expected_event1 = libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2) 63762306a36Sopenharmony_ci events = uhdev.next_sync_events() 63862306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 63962306a36Sopenharmony_ci self.assertInputEvents( 64062306a36Sopenharmony_ci (syn_event, expected_event0, expected_event1), events 64162306a36Sopenharmony_ci ) 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ciclass TestSimpleMouse(BaseTest.TestMouse): 64562306a36Sopenharmony_ci def create_device(self): 64662306a36Sopenharmony_ci return ButtonMouse() 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci def test_rdesc(self): 64962306a36Sopenharmony_ci """Check that the testsuite actually manages to format the 65062306a36Sopenharmony_ci reports according to the report descriptors. 65162306a36Sopenharmony_ci No kernel device is used here""" 65262306a36Sopenharmony_ci uhdev = self.uhdev 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci event = (0, 0, (None, None, None)) 65562306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci event = (0, 0, (None, True, None)) 65862306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci event = (0, 0, (True, True, None)) 66162306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci event = (0, 0, (False, False, False)) 66462306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci event = (1, 0, (True, False, True)) 66762306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci event = (-1, 0, (True, False, True)) 67062306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci event = (-5, 5, (True, False, True)) 67362306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci event = (-127, 127, (True, False, True)) 67662306a36Sopenharmony_ci assert uhdev.fake_report(*event) == uhdev.create_report(*event) 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci event = (0, -128, (True, False, True)) 67962306a36Sopenharmony_ci with pytest.raises(hidtools.hid.RangeError): 68062306a36Sopenharmony_ci uhdev.create_report(*event) 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ciclass TestWheelMouse(BaseTest.TestMouse): 68462306a36Sopenharmony_ci def create_device(self): 68562306a36Sopenharmony_ci return WheelMouse() 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci def is_wheel_highres(self, uhdev): 68862306a36Sopenharmony_ci evdev = uhdev.get_evdev() 68962306a36Sopenharmony_ci assert evdev.has(libevdev.EV_REL.REL_WHEEL) 69062306a36Sopenharmony_ci return evdev.has(libevdev.EV_REL.REL_WHEEL_HI_RES) 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci def test_wheel(self): 69362306a36Sopenharmony_ci uhdev = self.uhdev 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci # check if the kernel is high res wheel compatible 69662306a36Sopenharmony_ci high_res_wheel = self.is_wheel_highres(uhdev) 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci syn_event = self.syn_event 69962306a36Sopenharmony_ci # The Resolution Multiplier is applied to the HID reports, so we 70062306a36Sopenharmony_ci # need to pre-multiply too. 70162306a36Sopenharmony_ci mult = uhdev.wheel_multiplier 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=1 * mult) 70462306a36Sopenharmony_ci expected = [syn_event] 70562306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1)) 70662306a36Sopenharmony_ci if high_res_wheel: 70762306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120)) 70862306a36Sopenharmony_ci events = uhdev.next_sync_events() 70962306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 71062306a36Sopenharmony_ci self.assertInputEvents(expected, events) 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=-1 * mult) 71362306a36Sopenharmony_ci expected = [syn_event] 71462306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -1)) 71562306a36Sopenharmony_ci if high_res_wheel: 71662306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120)) 71762306a36Sopenharmony_ci events = uhdev.next_sync_events() 71862306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 71962306a36Sopenharmony_ci self.assertInputEvents(expected, events) 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci r = uhdev.event(-1, 2, wheels=3 * mult) 72262306a36Sopenharmony_ci expected = [syn_event] 72362306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 72462306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 72562306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 3)) 72662306a36Sopenharmony_ci if high_res_wheel: 72762306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 360)) 72862306a36Sopenharmony_ci events = uhdev.next_sync_events() 72962306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 73062306a36Sopenharmony_ci self.assertInputEvents(expected, events) 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ciclass TestTwoWheelMouse(TestWheelMouse): 73462306a36Sopenharmony_ci def create_device(self): 73562306a36Sopenharmony_ci return TwoWheelMouse() 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci def is_hwheel_highres(self, uhdev): 73862306a36Sopenharmony_ci evdev = uhdev.get_evdev() 73962306a36Sopenharmony_ci assert evdev.has(libevdev.EV_REL.REL_HWHEEL) 74062306a36Sopenharmony_ci return evdev.has(libevdev.EV_REL.REL_HWHEEL_HI_RES) 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci def test_ac_pan(self): 74362306a36Sopenharmony_ci uhdev = self.uhdev 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci # check if the kernel is high res wheel compatible 74662306a36Sopenharmony_ci high_res_wheel = self.is_wheel_highres(uhdev) 74762306a36Sopenharmony_ci high_res_hwheel = self.is_hwheel_highres(uhdev) 74862306a36Sopenharmony_ci assert high_res_wheel == high_res_hwheel 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci syn_event = self.syn_event 75162306a36Sopenharmony_ci # The Resolution Multiplier is applied to the HID reports, so we 75262306a36Sopenharmony_ci # need to pre-multiply too. 75362306a36Sopenharmony_ci hmult = uhdev.hwheel_multiplier 75462306a36Sopenharmony_ci vmult = uhdev.wheel_multiplier 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=(0, 1 * hmult)) 75762306a36Sopenharmony_ci expected = [syn_event] 75862306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1)) 75962306a36Sopenharmony_ci if high_res_hwheel: 76062306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120)) 76162306a36Sopenharmony_ci events = uhdev.next_sync_events() 76262306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 76362306a36Sopenharmony_ci self.assertInputEvents(expected, events) 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=(0, -1 * hmult)) 76662306a36Sopenharmony_ci expected = [syn_event] 76762306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, -1)) 76862306a36Sopenharmony_ci if high_res_hwheel: 76962306a36Sopenharmony_ci expected.append( 77062306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120) 77162306a36Sopenharmony_ci ) 77262306a36Sopenharmony_ci events = uhdev.next_sync_events() 77362306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 77462306a36Sopenharmony_ci self.assertInputEvents(expected, events) 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci r = uhdev.event(-1, 2, wheels=(0, 3 * hmult)) 77762306a36Sopenharmony_ci expected = [syn_event] 77862306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 77962306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 78062306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 3)) 78162306a36Sopenharmony_ci if high_res_hwheel: 78262306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 360)) 78362306a36Sopenharmony_ci events = uhdev.next_sync_events() 78462306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 78562306a36Sopenharmony_ci self.assertInputEvents(expected, events) 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci r = uhdev.event(-1, 2, wheels=(-3 * vmult, 4 * hmult)) 78862306a36Sopenharmony_ci expected = [syn_event] 78962306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 79062306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 79162306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -3)) 79262306a36Sopenharmony_ci if high_res_wheel: 79362306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -360)) 79462306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 4)) 79562306a36Sopenharmony_ci if high_res_wheel: 79662306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 480)) 79762306a36Sopenharmony_ci events = uhdev.next_sync_events() 79862306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 79962306a36Sopenharmony_ci self.assertInputEvents(expected, events) 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ciclass TestResolutionMultiplierMouse(TestTwoWheelMouse): 80362306a36Sopenharmony_ci def create_device(self): 80462306a36Sopenharmony_ci return ResolutionMultiplierMouse() 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci def is_wheel_highres(self, uhdev): 80762306a36Sopenharmony_ci high_res = super().is_wheel_highres(uhdev) 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci if not high_res: 81062306a36Sopenharmony_ci # the kernel doesn't seem to support the high res wheel mice, 81162306a36Sopenharmony_ci # make sure we haven't triggered the feature 81262306a36Sopenharmony_ci assert uhdev.wheel_multiplier == 1 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci return high_res 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci def test_resolution_multiplier_wheel(self): 81762306a36Sopenharmony_ci uhdev = self.uhdev 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci if not self.is_wheel_highres(uhdev): 82062306a36Sopenharmony_ci pytest.skip("Kernel not compatible, we can not trigger the conditions") 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci assert uhdev.wheel_multiplier > 1 82362306a36Sopenharmony_ci assert 120 % uhdev.wheel_multiplier == 0 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci def test_wheel_with_multiplier(self): 82662306a36Sopenharmony_ci uhdev = self.uhdev 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci if not self.is_wheel_highres(uhdev): 82962306a36Sopenharmony_ci pytest.skip("Kernel not compatible, we can not trigger the conditions") 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci assert uhdev.wheel_multiplier > 1 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci syn_event = self.syn_event 83462306a36Sopenharmony_ci mult = uhdev.wheel_multiplier 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=1) 83762306a36Sopenharmony_ci expected = [syn_event] 83862306a36Sopenharmony_ci expected.append( 83962306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult) 84062306a36Sopenharmony_ci ) 84162306a36Sopenharmony_ci events = uhdev.next_sync_events() 84262306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 84362306a36Sopenharmony_ci self.assertInputEvents(expected, events) 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=-1) 84662306a36Sopenharmony_ci expected = [syn_event] 84762306a36Sopenharmony_ci expected.append( 84862306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120 / mult) 84962306a36Sopenharmony_ci ) 85062306a36Sopenharmony_ci events = uhdev.next_sync_events() 85162306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 85262306a36Sopenharmony_ci self.assertInputEvents(expected, events) 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci expected = [syn_event] 85562306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1)) 85662306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2)) 85762306a36Sopenharmony_ci expected.append( 85862306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult) 85962306a36Sopenharmony_ci ) 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci for _ in range(mult - 1): 86262306a36Sopenharmony_ci r = uhdev.event(1, -2, wheels=1) 86362306a36Sopenharmony_ci events = uhdev.next_sync_events() 86462306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 86562306a36Sopenharmony_ci self.assertInputEvents(expected, events) 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci r = uhdev.event(1, -2, wheels=1) 86862306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1)) 86962306a36Sopenharmony_ci events = uhdev.next_sync_events() 87062306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 87162306a36Sopenharmony_ci self.assertInputEvents(expected, events) 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ciclass TestBadResolutionMultiplierMouse(TestTwoWheelMouse): 87562306a36Sopenharmony_ci def create_device(self): 87662306a36Sopenharmony_ci return BadResolutionMultiplierMouse() 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci def is_wheel_highres(self, uhdev): 87962306a36Sopenharmony_ci high_res = super().is_wheel_highres(uhdev) 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci assert uhdev.wheel_multiplier == 1 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci return high_res 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci def test_resolution_multiplier_wheel(self): 88662306a36Sopenharmony_ci uhdev = self.uhdev 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci assert uhdev.wheel_multiplier == 1 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ciclass TestResolutionMultiplierHWheelMouse(TestResolutionMultiplierMouse): 89262306a36Sopenharmony_ci def create_device(self): 89362306a36Sopenharmony_ci return ResolutionMultiplierHWheelMouse() 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci def is_hwheel_highres(self, uhdev): 89662306a36Sopenharmony_ci high_res = super().is_hwheel_highres(uhdev) 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci if not high_res: 89962306a36Sopenharmony_ci # the kernel doesn't seem to support the high res wheel mice, 90062306a36Sopenharmony_ci # make sure we haven't triggered the feature 90162306a36Sopenharmony_ci assert uhdev.hwheel_multiplier == 1 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci return high_res 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci def test_resolution_multiplier_ac_pan(self): 90662306a36Sopenharmony_ci uhdev = self.uhdev 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci if not self.is_hwheel_highres(uhdev): 90962306a36Sopenharmony_ci pytest.skip("Kernel not compatible, we can not trigger the conditions") 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci assert uhdev.hwheel_multiplier > 1 91262306a36Sopenharmony_ci assert 120 % uhdev.hwheel_multiplier == 0 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci def test_ac_pan_with_multiplier(self): 91562306a36Sopenharmony_ci uhdev = self.uhdev 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci if not self.is_hwheel_highres(uhdev): 91862306a36Sopenharmony_ci pytest.skip("Kernel not compatible, we can not trigger the conditions") 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci assert uhdev.hwheel_multiplier > 1 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci syn_event = self.syn_event 92362306a36Sopenharmony_ci hmult = uhdev.hwheel_multiplier 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=(0, 1)) 92662306a36Sopenharmony_ci expected = [syn_event] 92762306a36Sopenharmony_ci expected.append( 92862306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult) 92962306a36Sopenharmony_ci ) 93062306a36Sopenharmony_ci events = uhdev.next_sync_events() 93162306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 93262306a36Sopenharmony_ci self.assertInputEvents(expected, events) 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci r = uhdev.event(0, 0, wheels=(0, -1)) 93562306a36Sopenharmony_ci expected = [syn_event] 93662306a36Sopenharmony_ci expected.append( 93762306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120 / hmult) 93862306a36Sopenharmony_ci ) 93962306a36Sopenharmony_ci events = uhdev.next_sync_events() 94062306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 94162306a36Sopenharmony_ci self.assertInputEvents(expected, events) 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci expected = [syn_event] 94462306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1)) 94562306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2)) 94662306a36Sopenharmony_ci expected.append( 94762306a36Sopenharmony_ci libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult) 94862306a36Sopenharmony_ci ) 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci for _ in range(hmult - 1): 95162306a36Sopenharmony_ci r = uhdev.event(1, -2, wheels=(0, 1)) 95262306a36Sopenharmony_ci events = uhdev.next_sync_events() 95362306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 95462306a36Sopenharmony_ci self.assertInputEvents(expected, events) 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci r = uhdev.event(1, -2, wheels=(0, 1)) 95762306a36Sopenharmony_ci expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1)) 95862306a36Sopenharmony_ci events = uhdev.next_sync_events() 95962306a36Sopenharmony_ci self.debug_reports(r, uhdev, events) 96062306a36Sopenharmony_ci self.assertInputEvents(expected, events) 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ciclass TestMiMouse(TestWheelMouse): 96462306a36Sopenharmony_ci def create_device(self): 96562306a36Sopenharmony_ci return MIDongleMIWirelessMouse() 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci def assertInputEvents(self, expected_events, effective_events): 96862306a36Sopenharmony_ci # Buttons and x/y are spread over two HID reports, so we can get two 96962306a36Sopenharmony_ci # event frames for this device. 97062306a36Sopenharmony_ci remaining = self.assertInputEventsIn(expected_events, effective_events) 97162306a36Sopenharmony_ci try: 97262306a36Sopenharmony_ci remaining.remove(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT, 0)) 97362306a36Sopenharmony_ci except ValueError: 97462306a36Sopenharmony_ci # If there's no SYN_REPORT in the list, continue and let the 97562306a36Sopenharmony_ci # assert below print out the real error 97662306a36Sopenharmony_ci pass 97762306a36Sopenharmony_ci assert remaining == [] 978