~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/hid/tests/test_mouse.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/testing/selftests/hid/tests/test_mouse.py (Architecture i386) and /tools/testing/selftests/hid/tests/test_mouse.py (Architecture ppc)


  1 #!/bin/env python3                                  1 #!/bin/env python3
  2 # SPDX-License-Identifier: GPL-2.0                  2 # SPDX-License-Identifier: GPL-2.0
  3 # -*- coding: utf-8 -*-                             3 # -*- coding: utf-8 -*-
  4 #                                                   4 #
  5 # Copyright (c) 2017 Benjamin Tissoires <benjam      5 # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
  6 # Copyright (c) 2017 Red Hat, Inc.                  6 # Copyright (c) 2017 Red Hat, Inc.
  7 #                                                   7 #
  8                                                     8 
  9 from . import base                                  9 from . import base
 10 import hidtools.hid                                10 import hidtools.hid
 11 from hidtools.util import BusType                  11 from hidtools.util import BusType
 12 import libevdev                                    12 import libevdev
 13 import logging                                     13 import logging
 14 import pytest                                      14 import pytest
 15                                                    15 
 16 logger = logging.getLogger("hidtools.test.mous     16 logger = logging.getLogger("hidtools.test.mouse")
 17                                                    17 
 18 # workaround https://gitlab.freedesktop.org/li     18 # workaround https://gitlab.freedesktop.org/libevdev/python-libevdev/issues/6
 19 try:                                               19 try:
 20     libevdev.EV_REL.REL_WHEEL_HI_RES               20     libevdev.EV_REL.REL_WHEEL_HI_RES
 21 except AttributeError:                             21 except AttributeError:
 22     libevdev.EV_REL.REL_WHEEL_HI_RES = libevde     22     libevdev.EV_REL.REL_WHEEL_HI_RES = libevdev.EV_REL.REL_0B
 23     libevdev.EV_REL.REL_HWHEEL_HI_RES = libevd     23     libevdev.EV_REL.REL_HWHEEL_HI_RES = libevdev.EV_REL.REL_0C
 24                                                    24 
 25                                                    25 
 26 class InvalidHIDCommunication(Exception):          26 class InvalidHIDCommunication(Exception):
 27     pass                                           27     pass
 28                                                    28 
 29                                                    29 
 30 class MouseData(object):                           30 class MouseData(object):
 31     pass                                           31     pass
 32                                                    32 
 33                                                    33 
 34 class BaseMouse(base.UHIDTestDevice):              34 class BaseMouse(base.UHIDTestDevice):
 35     def __init__(self, rdesc, name=None, input     35     def __init__(self, rdesc, name=None, input_info=None):
 36         assert rdesc is not None                   36         assert rdesc is not None
 37         super().__init__(name, "Mouse", input_     37         super().__init__(name, "Mouse", input_info=input_info, rdesc=rdesc)
 38         self.left = False                          38         self.left = False
 39         self.right = False                         39         self.right = False
 40         self.middle = False                        40         self.middle = False
 41                                                    41 
 42     def create_report(self, x, y, buttons=None     42     def create_report(self, x, y, buttons=None, wheels=None, reportID=None):
 43         """                                        43         """
 44         Return an input report for this device     44         Return an input report for this device.
 45                                                    45 
 46         :param x: relative x                       46         :param x: relative x
 47         :param y: relative y                       47         :param y: relative y
 48         :param buttons: a (l, r, m) tuple of b     48         :param buttons: a (l, r, m) tuple of bools for the button states,
 49             where ``None`` is "leave unchanged     49             where ``None`` is "leave unchanged"
 50         :param wheels: a single value for the      50         :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for
 51             the two wheels                         51             the two wheels
 52         :param reportID: the numeric report ID     52         :param reportID: the numeric report ID for this report, if needed
 53         """                                        53         """
 54         if buttons is not None:                    54         if buttons is not None:
 55             left, right, middle = buttons          55             left, right, middle = buttons
 56             if left is not None:                   56             if left is not None:
 57                 self.left = left                   57                 self.left = left
 58             if right is not None:                  58             if right is not None:
 59                 self.right = right                 59                 self.right = right
 60             if middle is not None:                 60             if middle is not None:
 61                 self.middle = middle               61                 self.middle = middle
 62         left = self.left                           62         left = self.left
 63         right = self.right                         63         right = self.right
 64         middle = self.middle                       64         middle = self.middle
 65         # Note: the BaseMouse doesn't actually     65         # Note: the BaseMouse doesn't actually have a wheel but the
 66         # create_report magic only fills in th     66         # create_report magic only fills in those fields exist, so let's
 67         # make this generic here.                  67         # make this generic here.
 68         wheel, acpan = 0, 0                        68         wheel, acpan = 0, 0
 69         if wheels is not None:                     69         if wheels is not None:
 70             if isinstance(wheels, tuple):          70             if isinstance(wheels, tuple):
 71                 wheel = wheels[0]                  71                 wheel = wheels[0]
 72                 acpan = wheels[1]                  72                 acpan = wheels[1]
 73             else:                                  73             else:
 74                 wheel = wheels                     74                 wheel = wheels
 75                                                    75 
 76         reportID = reportID or self.default_re     76         reportID = reportID or self.default_reportID
 77                                                    77 
 78         mouse = MouseData()                        78         mouse = MouseData()
 79         mouse.b1 = int(left)                       79         mouse.b1 = int(left)
 80         mouse.b2 = int(right)                      80         mouse.b2 = int(right)
 81         mouse.b3 = int(middle)                     81         mouse.b3 = int(middle)
 82         mouse.x = x                                82         mouse.x = x
 83         mouse.y = y                                83         mouse.y = y
 84         mouse.wheel = wheel                        84         mouse.wheel = wheel
 85         mouse.acpan = acpan                        85         mouse.acpan = acpan
 86         return super().create_report(mouse, re     86         return super().create_report(mouse, reportID=reportID)
 87                                                    87 
 88     def event(self, x, y, buttons=None, wheels     88     def event(self, x, y, buttons=None, wheels=None):
 89         """                                        89         """
 90         Send an input event on the default rep     90         Send an input event on the default report ID.
 91                                                    91 
 92         :param x: relative x                       92         :param x: relative x
 93         :param y: relative y                       93         :param y: relative y
 94         :param buttons: a (l, r, m) tuple of b     94         :param buttons: a (l, r, m) tuple of bools for the button states,
 95             where ``None`` is "leave unchanged     95             where ``None`` is "leave unchanged"
 96         :param wheels: a single value for the      96         :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for
 97             the two wheels                         97             the two wheels
 98         """                                        98         """
 99         r = self.create_report(x, y, buttons,      99         r = self.create_report(x, y, buttons, wheels)
100         self.call_input_event(r)                  100         self.call_input_event(r)
101         return [r]                                101         return [r]
102                                                   102 
103                                                   103 
104 class ButtonMouse(BaseMouse):                     104 class ButtonMouse(BaseMouse):
105     # fmt: off                                    105     # fmt: off
106     report_descriptor = [                         106     report_descriptor = [
107         0x05, 0x01,  # .Usage Page (Generic De    107         0x05, 0x01,  # .Usage Page (Generic Desktop)        0
108         0x09, 0x02,  # .Usage (Mouse)             108         0x09, 0x02,  # .Usage (Mouse)                       2
109         0xa1, 0x01,  # .Collection (Applicatio    109         0xa1, 0x01,  # .Collection (Application)            4
110         0x09, 0x02,  # ..Usage (Mouse)            110         0x09, 0x02,  # ..Usage (Mouse)                      6
111         0xa1, 0x02,  # ..Collection (Logical)     111         0xa1, 0x02,  # ..Collection (Logical)               8
112         0x09, 0x01,  # ...Usage (Pointer)         112         0x09, 0x01,  # ...Usage (Pointer)                   10
113         0xa1, 0x00,  # ...Collection (Physical    113         0xa1, 0x00,  # ...Collection (Physical)             12
114         0x05, 0x09,  # ....Usage Page (Button)    114         0x05, 0x09,  # ....Usage Page (Button)              14
115         0x19, 0x01,  # ....Usage Minimum (1)      115         0x19, 0x01,  # ....Usage Minimum (1)                16
116         0x29, 0x03,  # ....Usage Maximum (3)      116         0x29, 0x03,  # ....Usage Maximum (3)                18
117         0x15, 0x00,  # ....Logical Minimum (0)    117         0x15, 0x00,  # ....Logical Minimum (0)              20
118         0x25, 0x01,  # ....Logical Maximum (1)    118         0x25, 0x01,  # ....Logical Maximum (1)              22
119         0x75, 0x01,  # ....Report Size (1)        119         0x75, 0x01,  # ....Report Size (1)                  24
120         0x95, 0x03,  # ....Report Count (3)       120         0x95, 0x03,  # ....Report Count (3)                 26
121         0x81, 0x02,  # ....Input (Data,Var,Abs    121         0x81, 0x02,  # ....Input (Data,Var,Abs)             28
122         0x75, 0x05,  # ....Report Size (5)        122         0x75, 0x05,  # ....Report Size (5)                  30
123         0x95, 0x01,  # ....Report Count (1)       123         0x95, 0x01,  # ....Report Count (1)                 32
124         0x81, 0x03,  # ....Input (Cnst,Var,Abs    124         0x81, 0x03,  # ....Input (Cnst,Var,Abs)             34
125         0x05, 0x01,  # ....Usage Page (Generic    125         0x05, 0x01,  # ....Usage Page (Generic Desktop)     36
126         0x09, 0x30,  # ....Usage (X)              126         0x09, 0x30,  # ....Usage (X)                        38
127         0x09, 0x31,  # ....Usage (Y)              127         0x09, 0x31,  # ....Usage (Y)                        40
128         0x15, 0x81,  # ....Logical Minimum (-1    128         0x15, 0x81,  # ....Logical Minimum (-127)           42
129         0x25, 0x7f,  # ....Logical Maximum (12    129         0x25, 0x7f,  # ....Logical Maximum (127)            44
130         0x75, 0x08,  # ....Report Size (8)        130         0x75, 0x08,  # ....Report Size (8)                  46
131         0x95, 0x02,  # ....Report Count (2)       131         0x95, 0x02,  # ....Report Count (2)                 48
132         0x81, 0x06,  # ....Input (Data,Var,Rel    132         0x81, 0x06,  # ....Input (Data,Var,Rel)             50
133         0xc0,        # ...End Collection          133         0xc0,        # ...End Collection                    52
134         0xc0,        # ..End Collection           134         0xc0,        # ..End Collection                     53
135         0xc0,        # .End Collection            135         0xc0,        # .End Collection                      54
136     ]                                             136     ]
137     # fmt: on                                     137     # fmt: on
138                                                   138 
139     def __init__(self, rdesc=report_descriptor    139     def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
140         super().__init__(rdesc, name, input_in    140         super().__init__(rdesc, name, input_info)
141                                                   141 
142     def fake_report(self, x, y, buttons):         142     def fake_report(self, x, y, buttons):
143         if buttons is not None:                   143         if buttons is not None:
144             left, right, middle = buttons         144             left, right, middle = buttons
145             if left is None:                      145             if left is None:
146                 left = self.left                  146                 left = self.left
147             if right is None:                     147             if right is None:
148                 right = self.right                148                 right = self.right
149             if middle is None:                    149             if middle is None:
150                 middle = self.middle              150                 middle = self.middle
151         else:                                     151         else:
152             left = self.left                      152             left = self.left
153             right = self.right                    153             right = self.right
154             middle = self.middle                  154             middle = self.middle
155                                                   155 
156         button_mask = sum(1 << i for i, b in e    156         button_mask = sum(1 << i for i, b in enumerate([left, right, middle]) if b)
157         x = max(-127, min(127, x))                157         x = max(-127, min(127, x))
158         y = max(-127, min(127, y))                158         y = max(-127, min(127, y))
159         x = hidtools.util.to_twos_comp(x, 8)      159         x = hidtools.util.to_twos_comp(x, 8)
160         y = hidtools.util.to_twos_comp(y, 8)      160         y = hidtools.util.to_twos_comp(y, 8)
161         return [button_mask, x, y]                161         return [button_mask, x, y]
162                                                   162 
163                                                   163 
164 class WheelMouse(ButtonMouse):                    164 class WheelMouse(ButtonMouse):
165     # fmt: off                                    165     # fmt: off
166     report_descriptor = [                         166     report_descriptor = [
167         0x05, 0x01,  # Usage Page (Generic Des    167         0x05, 0x01,  # Usage Page (Generic Desktop)        0
168         0x09, 0x02,  # Usage (Mouse)              168         0x09, 0x02,  # Usage (Mouse)                       2
169         0xa1, 0x01,  # Collection (Application    169         0xa1, 0x01,  # Collection (Application)            4
170         0x05, 0x09,  # .Usage Page (Button)       170         0x05, 0x09,  # .Usage Page (Button)                6
171         0x19, 0x01,  # .Usage Minimum (1)         171         0x19, 0x01,  # .Usage Minimum (1)                  8
172         0x29, 0x03,  # .Usage Maximum (3)         172         0x29, 0x03,  # .Usage Maximum (3)                  10
173         0x15, 0x00,  # .Logical Minimum (0)       173         0x15, 0x00,  # .Logical Minimum (0)                12
174         0x25, 0x01,  # .Logical Maximum (1)       174         0x25, 0x01,  # .Logical Maximum (1)                14
175         0x95, 0x03,  # .Report Count (3)          175         0x95, 0x03,  # .Report Count (3)                   16
176         0x75, 0x01,  # .Report Size (1)           176         0x75, 0x01,  # .Report Size (1)                    18
177         0x81, 0x02,  # .Input (Data,Var,Abs)      177         0x81, 0x02,  # .Input (Data,Var,Abs)               20
178         0x95, 0x01,  # .Report Count (1)          178         0x95, 0x01,  # .Report Count (1)                   22
179         0x75, 0x05,  # .Report Size (5)           179         0x75, 0x05,  # .Report Size (5)                    24
180         0x81, 0x03,  # .Input (Cnst,Var,Abs)      180         0x81, 0x03,  # .Input (Cnst,Var,Abs)               26
181         0x05, 0x01,  # .Usage Page (Generic De    181         0x05, 0x01,  # .Usage Page (Generic Desktop)       28
182         0x09, 0x01,  # .Usage (Pointer)           182         0x09, 0x01,  # .Usage (Pointer)                    30
183         0xa1, 0x00,  # .Collection (Physical)     183         0xa1, 0x00,  # .Collection (Physical)              32
184         0x09, 0x30,  # ..Usage (X)                184         0x09, 0x30,  # ..Usage (X)                         34
185         0x09, 0x31,  # ..Usage (Y)                185         0x09, 0x31,  # ..Usage (Y)                         36
186         0x15, 0x81,  # ..Logical Minimum (-127    186         0x15, 0x81,  # ..Logical Minimum (-127)            38
187         0x25, 0x7f,  # ..Logical Maximum (127)    187         0x25, 0x7f,  # ..Logical Maximum (127)             40
188         0x75, 0x08,  # ..Report Size (8)          188         0x75, 0x08,  # ..Report Size (8)                   42
189         0x95, 0x02,  # ..Report Count (2)         189         0x95, 0x02,  # ..Report Count (2)                  44
190         0x81, 0x06,  # ..Input (Data,Var,Rel)     190         0x81, 0x06,  # ..Input (Data,Var,Rel)              46
191         0xc0,        # .End Collection            191         0xc0,        # .End Collection                     48
192         0x09, 0x38,  # .Usage (Wheel)             192         0x09, 0x38,  # .Usage (Wheel)                      49
193         0x15, 0x81,  # .Logical Minimum (-127)    193         0x15, 0x81,  # .Logical Minimum (-127)             51
194         0x25, 0x7f,  # .Logical Maximum (127)     194         0x25, 0x7f,  # .Logical Maximum (127)              53
195         0x75, 0x08,  # .Report Size (8)           195         0x75, 0x08,  # .Report Size (8)                    55
196         0x95, 0x01,  # .Report Count (1)          196         0x95, 0x01,  # .Report Count (1)                   57
197         0x81, 0x06,  # .Input (Data,Var,Rel)      197         0x81, 0x06,  # .Input (Data,Var,Rel)               59
198         0xc0,        # End Collection             198         0xc0,        # End Collection                      61
199     ]                                             199     ]
200     # fmt: on                                     200     # fmt: on
201                                                   201 
202     def __init__(self, rdesc=report_descriptor    202     def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
203         super().__init__(rdesc, name, input_in    203         super().__init__(rdesc, name, input_info)
204         self.wheel_multiplier = 1                 204         self.wheel_multiplier = 1
205                                                   205 
206                                                   206 
207 class TwoWheelMouse(WheelMouse):                  207 class TwoWheelMouse(WheelMouse):
208     # fmt: off                                    208     # fmt: off
209     report_descriptor = [                         209     report_descriptor = [
210         0x05, 0x01,        # Usage Page (Gener    210         0x05, 0x01,        # Usage Page (Generic Desktop)        0
211         0x09, 0x02,        # Usage (Mouse)        211         0x09, 0x02,        # Usage (Mouse)                       2
212         0xa1, 0x01,        # Collection (Appli    212         0xa1, 0x01,        # Collection (Application)            4
213         0x09, 0x01,        # .Usage (Pointer)     213         0x09, 0x01,        # .Usage (Pointer)                    6
214         0xa1, 0x00,        # .Collection (Phys    214         0xa1, 0x00,        # .Collection (Physical)              8
215         0x05, 0x09,        # ..Usage Page (But    215         0x05, 0x09,        # ..Usage Page (Button)               10
216         0x19, 0x01,        # ..Usage Minimum (    216         0x19, 0x01,        # ..Usage Minimum (1)                 12
217         0x29, 0x10,        # ..Usage Maximum (    217         0x29, 0x10,        # ..Usage Maximum (16)                14
218         0x15, 0x00,        # ..Logical Minimum    218         0x15, 0x00,        # ..Logical Minimum (0)               16
219         0x25, 0x01,        # ..Logical Maximum    219         0x25, 0x01,        # ..Logical Maximum (1)               18
220         0x95, 0x10,        # ..Report Count (1    220         0x95, 0x10,        # ..Report Count (16)                 20
221         0x75, 0x01,        # ..Report Size (1)    221         0x75, 0x01,        # ..Report Size (1)                   22
222         0x81, 0x02,        # ..Input (Data,Var    222         0x81, 0x02,        # ..Input (Data,Var,Abs)              24
223         0x05, 0x01,        # ..Usage Page (Gen    223         0x05, 0x01,        # ..Usage Page (Generic Desktop)      26
224         0x16, 0x01, 0x80,  # ..Logical Minimum    224         0x16, 0x01, 0x80,  # ..Logical Minimum (-32767)          28
225         0x26, 0xff, 0x7f,  # ..Logical Maximum    225         0x26, 0xff, 0x7f,  # ..Logical Maximum (32767)           31
226         0x75, 0x10,        # ..Report Size (16    226         0x75, 0x10,        # ..Report Size (16)                  34
227         0x95, 0x02,        # ..Report Count (2    227         0x95, 0x02,        # ..Report Count (2)                  36
228         0x09, 0x30,        # ..Usage (X)          228         0x09, 0x30,        # ..Usage (X)                         38
229         0x09, 0x31,        # ..Usage (Y)          229         0x09, 0x31,        # ..Usage (Y)                         40
230         0x81, 0x06,        # ..Input (Data,Var    230         0x81, 0x06,        # ..Input (Data,Var,Rel)              42
231         0x15, 0x81,        # ..Logical Minimum    231         0x15, 0x81,        # ..Logical Minimum (-127)            44
232         0x25, 0x7f,        # ..Logical Maximum    232         0x25, 0x7f,        # ..Logical Maximum (127)             46
233         0x75, 0x08,        # ..Report Size (8)    233         0x75, 0x08,        # ..Report Size (8)                   48
234         0x95, 0x01,        # ..Report Count (1    234         0x95, 0x01,        # ..Report Count (1)                  50
235         0x09, 0x38,        # ..Usage (Wheel)      235         0x09, 0x38,        # ..Usage (Wheel)                     52
236         0x81, 0x06,        # ..Input (Data,Var    236         0x81, 0x06,        # ..Input (Data,Var,Rel)              54
237         0x05, 0x0c,        # ..Usage Page (Con    237         0x05, 0x0c,        # ..Usage Page (Consumer Devices)     56
238         0x0a, 0x38, 0x02,  # ..Usage (AC Pan)     238         0x0a, 0x38, 0x02,  # ..Usage (AC Pan)                    58
239         0x95, 0x01,        # ..Report Count (1    239         0x95, 0x01,        # ..Report Count (1)                  61
240         0x81, 0x06,        # ..Input (Data,Var    240         0x81, 0x06,        # ..Input (Data,Var,Rel)              63
241         0xc0,              # .End Collection      241         0xc0,              # .End Collection                     65
242         0xc0,              # End Collection       242         0xc0,              # End Collection                      66
243     ]                                             243     ]
244     # fmt: on                                     244     # fmt: on
245                                                   245 
246     def __init__(self, rdesc=report_descriptor    246     def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
247         super().__init__(rdesc, name, input_in    247         super().__init__(rdesc, name, input_info)
248         self.hwheel_multiplier = 1                248         self.hwheel_multiplier = 1
249                                                   249 
250                                                   250 
251 class MIDongleMIWirelessMouse(TwoWheelMouse):     251 class MIDongleMIWirelessMouse(TwoWheelMouse):
252     # fmt: off                                    252     # fmt: off
253     report_descriptor = [                         253     report_descriptor = [
254         0x05, 0x01,         # Usage Page (Gene    254         0x05, 0x01,         # Usage Page (Generic Desktop)
255         0x09, 0x02,         # Usage (Mouse)       255         0x09, 0x02,         # Usage (Mouse)
256         0xa1, 0x01,         # Collection (Appl    256         0xa1, 0x01,         # Collection (Application)
257         0x85, 0x01,         # .Report ID (1)      257         0x85, 0x01,         # .Report ID (1)
258         0x09, 0x01,         # .Usage (Pointer)    258         0x09, 0x01,         # .Usage (Pointer)
259         0xa1, 0x00,         # .Collection (Phy    259         0xa1, 0x00,         # .Collection (Physical)
260         0x95, 0x05,         # ..Report Count (    260         0x95, 0x05,         # ..Report Count (5)
261         0x75, 0x01,         # ..Report Size (1    261         0x75, 0x01,         # ..Report Size (1)
262         0x05, 0x09,         # ..Usage Page (Bu    262         0x05, 0x09,         # ..Usage Page (Button)
263         0x19, 0x01,         # ..Usage Minimum     263         0x19, 0x01,         # ..Usage Minimum (1)
264         0x29, 0x05,         # ..Usage Maximum     264         0x29, 0x05,         # ..Usage Maximum (5)
265         0x15, 0x00,         # ..Logical Minimu    265         0x15, 0x00,         # ..Logical Minimum (0)
266         0x25, 0x01,         # ..Logical Maximu    266         0x25, 0x01,         # ..Logical Maximum (1)
267         0x81, 0x02,         # ..Input (Data,Va    267         0x81, 0x02,         # ..Input (Data,Var,Abs)
268         0x95, 0x01,         # ..Report Count (    268         0x95, 0x01,         # ..Report Count (1)
269         0x75, 0x03,         # ..Report Size (3    269         0x75, 0x03,         # ..Report Size (3)
270         0x81, 0x01,         # ..Input (Cnst,Ar    270         0x81, 0x01,         # ..Input (Cnst,Arr,Abs)
271         0x75, 0x08,         # ..Report Size (8    271         0x75, 0x08,         # ..Report Size (8)
272         0x95, 0x01,         # ..Report Count (    272         0x95, 0x01,         # ..Report Count (1)
273         0x05, 0x01,         # ..Usage Page (Ge    273         0x05, 0x01,         # ..Usage Page (Generic Desktop)
274         0x09, 0x38,         # ..Usage (Wheel)     274         0x09, 0x38,         # ..Usage (Wheel)
275         0x15, 0x81,         # ..Logical Minimu    275         0x15, 0x81,         # ..Logical Minimum (-127)
276         0x25, 0x7f,         # ..Logical Maximu    276         0x25, 0x7f,         # ..Logical Maximum (127)
277         0x81, 0x06,         # ..Input (Data,Va    277         0x81, 0x06,         # ..Input (Data,Var,Rel)
278         0x05, 0x0c,         # ..Usage Page (Co    278         0x05, 0x0c,         # ..Usage Page (Consumer Devices)
279         0x0a, 0x38, 0x02,   # ..Usage (AC Pan)    279         0x0a, 0x38, 0x02,   # ..Usage (AC Pan)
280         0x95, 0x01,         # ..Report Count (    280         0x95, 0x01,         # ..Report Count (1)
281         0x81, 0x06,         # ..Input (Data,Va    281         0x81, 0x06,         # ..Input (Data,Var,Rel)
282         0xc0,               # .End Collection     282         0xc0,               # .End Collection
283         0x85, 0x02,         # .Report ID (2)      283         0x85, 0x02,         # .Report ID (2)
284         0x09, 0x01,         # .Usage (Consumer    284         0x09, 0x01,         # .Usage (Consumer Control)
285         0xa1, 0x00,         # .Collection (Phy    285         0xa1, 0x00,         # .Collection (Physical)
286         0x75, 0x0c,         # ..Report Size (1    286         0x75, 0x0c,         # ..Report Size (12)
287         0x95, 0x02,         # ..Report Count (    287         0x95, 0x02,         # ..Report Count (2)
288         0x05, 0x01,         # ..Usage Page (Ge    288         0x05, 0x01,         # ..Usage Page (Generic Desktop)
289         0x09, 0x30,         # ..Usage (X)         289         0x09, 0x30,         # ..Usage (X)
290         0x09, 0x31,         # ..Usage (Y)         290         0x09, 0x31,         # ..Usage (Y)
291         0x16, 0x01, 0xf8,   # ..Logical Minimu    291         0x16, 0x01, 0xf8,   # ..Logical Minimum (-2047)
292         0x26, 0xff, 0x07,   # ..Logical Maximu    292         0x26, 0xff, 0x07,   # ..Logical Maximum (2047)
293         0x81, 0x06,         # ..Input (Data,Va    293         0x81, 0x06,         # ..Input (Data,Var,Rel)
294         0xc0,               # .End Collection     294         0xc0,               # .End Collection
295         0xc0,               # End Collection      295         0xc0,               # End Collection
296         0x05, 0x0c,         # Usage Page (Cons    296         0x05, 0x0c,         # Usage Page (Consumer Devices)
297         0x09, 0x01,         # Usage (Consumer     297         0x09, 0x01,         # Usage (Consumer Control)
298         0xa1, 0x01,         # Collection (Appl    298         0xa1, 0x01,         # Collection (Application)
299         0x85, 0x03,         # .Report ID (3)      299         0x85, 0x03,         # .Report ID (3)
300         0x15, 0x00,         # .Logical Minimum    300         0x15, 0x00,         # .Logical Minimum (0)
301         0x25, 0x01,         # .Logical Maximum    301         0x25, 0x01,         # .Logical Maximum (1)
302         0x75, 0x01,         # .Report Size (1)    302         0x75, 0x01,         # .Report Size (1)
303         0x95, 0x01,         # .Report Count (1    303         0x95, 0x01,         # .Report Count (1)
304         0x09, 0xcd,         # .Usage (Play/Pau    304         0x09, 0xcd,         # .Usage (Play/Pause)
305         0x81, 0x06,         # .Input (Data,Var    305         0x81, 0x06,         # .Input (Data,Var,Rel)
306         0x0a, 0x83, 0x01,   # .Usage (AL Consu    306         0x0a, 0x83, 0x01,   # .Usage (AL Consumer Control Config)
307         0x81, 0x06,         # .Input (Data,Var    307         0x81, 0x06,         # .Input (Data,Var,Rel)
308         0x09, 0xb5,         # .Usage (Scan Nex    308         0x09, 0xb5,         # .Usage (Scan Next Track)
309         0x81, 0x06,         # .Input (Data,Var    309         0x81, 0x06,         # .Input (Data,Var,Rel)
310         0x09, 0xb6,         # .Usage (Scan Pre    310         0x09, 0xb6,         # .Usage (Scan Previous Track)
311         0x81, 0x06,         # .Input (Data,Var    311         0x81, 0x06,         # .Input (Data,Var,Rel)
312         0x09, 0xea,         # .Usage (Volume D    312         0x09, 0xea,         # .Usage (Volume Down)
313         0x81, 0x06,         # .Input (Data,Var    313         0x81, 0x06,         # .Input (Data,Var,Rel)
314         0x09, 0xe9,         # .Usage (Volume U    314         0x09, 0xe9,         # .Usage (Volume Up)
315         0x81, 0x06,         # .Input (Data,Var    315         0x81, 0x06,         # .Input (Data,Var,Rel)
316         0x0a, 0x25, 0x02,   # .Usage (AC Forwa    316         0x0a, 0x25, 0x02,   # .Usage (AC Forward)
317         0x81, 0x06,         # .Input (Data,Var    317         0x81, 0x06,         # .Input (Data,Var,Rel)
318         0x0a, 0x24, 0x02,   # .Usage (AC Back)    318         0x0a, 0x24, 0x02,   # .Usage (AC Back)
319         0x81, 0x06,         # .Input (Data,Var    319         0x81, 0x06,         # .Input (Data,Var,Rel)
320         0xc0,               # End Collection      320         0xc0,               # End Collection
321     ]                                             321     ]
322     # fmt: on                                     322     # fmt: on
323     device_input_info = (BusType.USB, 0x2717,     323     device_input_info = (BusType.USB, 0x2717, 0x003B)
324     device_name = "uhid test MI Dongle MI Wire    324     device_name = "uhid test MI Dongle MI Wireless Mouse"
325                                                   325 
326     def __init__(                                 326     def __init__(
327         self, rdesc=report_descriptor, name=de    327         self, rdesc=report_descriptor, name=device_name, input_info=device_input_info
328     ):                                            328     ):
329         super().__init__(rdesc, name, input_in    329         super().__init__(rdesc, name, input_info)
330                                                   330 
331     def event(self, x, y, buttons=None, wheels    331     def event(self, x, y, buttons=None, wheels=None):
332         # this mouse spreads the relative poin    332         # this mouse spreads the relative pointer and the mouse buttons
333         # onto 2 distinct reports                 333         # onto 2 distinct reports
334         rs = []                                   334         rs = []
335         r = self.create_report(x, y, buttons,     335         r = self.create_report(x, y, buttons, wheels, reportID=1)
336         self.call_input_event(r)                  336         self.call_input_event(r)
337         rs.append(r)                              337         rs.append(r)
338         r = self.create_report(x, y, buttons,     338         r = self.create_report(x, y, buttons, reportID=2)
339         self.call_input_event(r)                  339         self.call_input_event(r)
340         rs.append(r)                              340         rs.append(r)
341         return rs                                 341         return rs
342                                                   342 
343                                                   343 
344 class ResolutionMultiplierMouse(TwoWheelMouse)    344 class ResolutionMultiplierMouse(TwoWheelMouse):
345     # fmt: off                                    345     # fmt: off
346     report_descriptor = [                         346     report_descriptor = [
347         0x05, 0x01,        # Usage Page (Gener    347         0x05, 0x01,        # Usage Page (Generic Desktop)        83
348         0x09, 0x02,        # Usage (Mouse)        348         0x09, 0x02,        # Usage (Mouse)                       85
349         0xa1, 0x01,        # Collection (Appli    349         0xa1, 0x01,        # Collection (Application)            87
350         0x05, 0x01,        # .Usage Page (Gene    350         0x05, 0x01,        # .Usage Page (Generic Desktop)       89
351         0x09, 0x02,        # .Usage (Mouse)       351         0x09, 0x02,        # .Usage (Mouse)                      91
352         0xa1, 0x02,        # .Collection (Logi    352         0xa1, 0x02,        # .Collection (Logical)               93
353         0x85, 0x11,        # ..Report ID (17)     353         0x85, 0x11,        # ..Report ID (17)                    95
354         0x09, 0x01,        # ..Usage (Pointer)    354         0x09, 0x01,        # ..Usage (Pointer)                   97
355         0xa1, 0x00,        # ..Collection (Phy    355         0xa1, 0x00,        # ..Collection (Physical)             99
356         0x05, 0x09,        # ...Usage Page (Bu    356         0x05, 0x09,        # ...Usage Page (Button)              101
357         0x19, 0x01,        # ...Usage Minimum     357         0x19, 0x01,        # ...Usage Minimum (1)                103
358         0x29, 0x03,        # ...Usage Maximum     358         0x29, 0x03,        # ...Usage Maximum (3)                105
359         0x95, 0x03,        # ...Report Count (    359         0x95, 0x03,        # ...Report Count (3)                 107
360         0x75, 0x01,        # ...Report Size (1    360         0x75, 0x01,        # ...Report Size (1)                  109
361         0x25, 0x01,        # ...Logical Maximu    361         0x25, 0x01,        # ...Logical Maximum (1)              111
362         0x81, 0x02,        # ...Input (Data,Va    362         0x81, 0x02,        # ...Input (Data,Var,Abs)             113
363         0x95, 0x01,        # ...Report Count (    363         0x95, 0x01,        # ...Report Count (1)                 115
364         0x81, 0x01,        # ...Input (Cnst,Ar    364         0x81, 0x01,        # ...Input (Cnst,Arr,Abs)             117
365         0x09, 0x05,        # ...Usage (Vendor     365         0x09, 0x05,        # ...Usage (Vendor Usage 0x05)        119
366         0x81, 0x02,        # ...Input (Data,Va    366         0x81, 0x02,        # ...Input (Data,Var,Abs)             121
367         0x95, 0x03,        # ...Report Count (    367         0x95, 0x03,        # ...Report Count (3)                 123
368         0x81, 0x01,        # ...Input (Cnst,Ar    368         0x81, 0x01,        # ...Input (Cnst,Arr,Abs)             125
369         0x05, 0x01,        # ...Usage Page (Ge    369         0x05, 0x01,        # ...Usage Page (Generic Desktop)     127
370         0x09, 0x30,        # ...Usage (X)         370         0x09, 0x30,        # ...Usage (X)                        129
371         0x09, 0x31,        # ...Usage (Y)         371         0x09, 0x31,        # ...Usage (Y)                        131
372         0x95, 0x02,        # ...Report Count (    372         0x95, 0x02,        # ...Report Count (2)                 133
373         0x75, 0x08,        # ...Report Size (8    373         0x75, 0x08,        # ...Report Size (8)                  135
374         0x15, 0x81,        # ...Logical Minimu    374         0x15, 0x81,        # ...Logical Minimum (-127)           137
375         0x25, 0x7f,        # ...Logical Maximu    375         0x25, 0x7f,        # ...Logical Maximum (127)            139
376         0x81, 0x06,        # ...Input (Data,Va    376         0x81, 0x06,        # ...Input (Data,Var,Rel)             141
377         0xa1, 0x02,        # ...Collection (Lo    377         0xa1, 0x02,        # ...Collection (Logical)             143
378         0x85, 0x12,        # ....Report ID (18    378         0x85, 0x12,        # ....Report ID (18)                  145
379         0x09, 0x48,        # ....Usage (Resolu    379         0x09, 0x48,        # ....Usage (Resolution Multiplier)   147
380         0x95, 0x01,        # ....Report Count     380         0x95, 0x01,        # ....Report Count (1)                149
381         0x75, 0x02,        # ....Report Size (    381         0x75, 0x02,        # ....Report Size (2)                 151
382         0x15, 0x00,        # ....Logical Minim    382         0x15, 0x00,        # ....Logical Minimum (0)             153
383         0x25, 0x01,        # ....Logical Maxim    383         0x25, 0x01,        # ....Logical Maximum (1)             155
384         0x35, 0x01,        # ....Physical Mini    384         0x35, 0x01,        # ....Physical Minimum (1)            157
385         0x45, 0x04,        # ....Physical Maxi    385         0x45, 0x04,        # ....Physical Maximum (4)            159
386         0xb1, 0x02,        # ....Feature (Data    386         0xb1, 0x02,        # ....Feature (Data,Var,Abs)          161
387         0x35, 0x00,        # ....Physical Mini    387         0x35, 0x00,        # ....Physical Minimum (0)            163
388         0x45, 0x00,        # ....Physical Maxi    388         0x45, 0x00,        # ....Physical Maximum (0)            165
389         0x75, 0x06,        # ....Report Size (    389         0x75, 0x06,        # ....Report Size (6)                 167
390         0xb1, 0x01,        # ....Feature (Cnst    390         0xb1, 0x01,        # ....Feature (Cnst,Arr,Abs)          169
391         0x85, 0x11,        # ....Report ID (17    391         0x85, 0x11,        # ....Report ID (17)                  171
392         0x09, 0x38,        # ....Usage (Wheel)    392         0x09, 0x38,        # ....Usage (Wheel)                   173
393         0x15, 0x81,        # ....Logical Minim    393         0x15, 0x81,        # ....Logical Minimum (-127)          175
394         0x25, 0x7f,        # ....Logical Maxim    394         0x25, 0x7f,        # ....Logical Maximum (127)           177
395         0x75, 0x08,        # ....Report Size (    395         0x75, 0x08,        # ....Report Size (8)                 179
396         0x81, 0x06,        # ....Input (Data,V    396         0x81, 0x06,        # ....Input (Data,Var,Rel)            181
397         0xc0,              # ...End Collection    397         0xc0,              # ...End Collection                   183
398         0x05, 0x0c,        # ...Usage Page (Co    398         0x05, 0x0c,        # ...Usage Page (Consumer Devices)    184
399         0x75, 0x08,        # ...Report Size (8    399         0x75, 0x08,        # ...Report Size (8)                  186
400         0x0a, 0x38, 0x02,  # ...Usage (AC Pan)    400         0x0a, 0x38, 0x02,  # ...Usage (AC Pan)                   188
401         0x81, 0x06,        # ...Input (Data,Va    401         0x81, 0x06,        # ...Input (Data,Var,Rel)             191
402         0xc0,              # ..End Collection     402         0xc0,              # ..End Collection                    193
403         0xc0,              # .End Collection      403         0xc0,              # .End Collection                     194
404         0xc0,              # End Collection       404         0xc0,              # End Collection                      195
405     ]                                             405     ]
406     # fmt: on                                     406     # fmt: on
407                                                   407 
408     def __init__(self, rdesc=report_descriptor    408     def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
409         super().__init__(rdesc, name, input_in    409         super().__init__(rdesc, name, input_info)
410         self.default_reportID = 0x11              410         self.default_reportID = 0x11
411                                                   411 
412         # Feature Report 12, multiplier Featur    412         # Feature Report 12, multiplier Feature value must be set to 0b01,
413         # i.e. 1. We should extract that from     413         # i.e. 1. We should extract that from the descriptor instead
414         # of hardcoding it here, but meanwhile    414         # of hardcoding it here, but meanwhile this will do.
415         self.set_feature_report = [0x12, 0x1]     415         self.set_feature_report = [0x12, 0x1]
416                                                   416 
417     def set_report(self, req, rnum, rtype, dat    417     def set_report(self, req, rnum, rtype, data):
418         if rtype != self.UHID_FEATURE_REPORT:     418         if rtype != self.UHID_FEATURE_REPORT:
419             raise InvalidHIDCommunication(f"Un    419             raise InvalidHIDCommunication(f"Unexpected report type: {rtype}")
420         if rnum != 0x12:                          420         if rnum != 0x12:
421             raise InvalidHIDCommunication(f"Un    421             raise InvalidHIDCommunication(f"Unexpected report number: {rnum}")
422                                                   422 
423         if data != self.set_feature_report:       423         if data != self.set_feature_report:
424             raise InvalidHIDCommunication(        424             raise InvalidHIDCommunication(
425                 f"Unexpected data: {data}, exp    425                 f"Unexpected data: {data}, expected {self.set_feature_report}"
426             )                                     426             )
427                                                   427 
428         self.wheel_multiplier = 4                 428         self.wheel_multiplier = 4
429                                                   429 
430         return 0                                  430         return 0
431                                                   431 
432                                                   432 
433 class BadResolutionMultiplierMouse(ResolutionM    433 class BadResolutionMultiplierMouse(ResolutionMultiplierMouse):
434     def set_report(self, req, rnum, rtype, dat    434     def set_report(self, req, rnum, rtype, data):
435         super().set_report(req, rnum, rtype, d    435         super().set_report(req, rnum, rtype, data)
436                                                   436 
437         self.wheel_multiplier = 1                 437         self.wheel_multiplier = 1
438         self.hwheel_multiplier = 1                438         self.hwheel_multiplier = 1
439         return 32  # EPIPE                        439         return 32  # EPIPE
440                                                   440 
441                                                   441 
442 class ResolutionMultiplierHWheelMouse(TwoWheel    442 class ResolutionMultiplierHWheelMouse(TwoWheelMouse):
443     # fmt: off                                    443     # fmt: off
444     report_descriptor = [                         444     report_descriptor = [
445         0x05, 0x01,         # Usage Page (Gene    445         0x05, 0x01,         # Usage Page (Generic Desktop)        0
446         0x09, 0x02,         # Usage (Mouse)       446         0x09, 0x02,         # Usage (Mouse)                       2
447         0xa1, 0x01,         # Collection (Appl    447         0xa1, 0x01,         # Collection (Application)            4
448         0x05, 0x01,         # .Usage Page (Gen    448         0x05, 0x01,         # .Usage Page (Generic Desktop)       6
449         0x09, 0x02,         # .Usage (Mouse)      449         0x09, 0x02,         # .Usage (Mouse)                      8
450         0xa1, 0x02,         # .Collection (Log    450         0xa1, 0x02,         # .Collection (Logical)               10
451         0x85, 0x1a,         # ..Report ID (26)    451         0x85, 0x1a,         # ..Report ID (26)                    12
452         0x09, 0x01,         # ..Usage (Pointer    452         0x09, 0x01,         # ..Usage (Pointer)                   14
453         0xa1, 0x00,         # ..Collection (Ph    453         0xa1, 0x00,         # ..Collection (Physical)             16
454         0x05, 0x09,         # ...Usage Page (B    454         0x05, 0x09,         # ...Usage Page (Button)              18
455         0x19, 0x01,         # ...Usage Minimum    455         0x19, 0x01,         # ...Usage Minimum (1)                20
456         0x29, 0x05,         # ...Usage Maximum    456         0x29, 0x05,         # ...Usage Maximum (5)                22
457         0x95, 0x05,         # ...Report Count     457         0x95, 0x05,         # ...Report Count (5)                 24
458         0x75, 0x01,         # ...Report Size (    458         0x75, 0x01,         # ...Report Size (1)                  26
459         0x15, 0x00,         # ...Logical Minim    459         0x15, 0x00,         # ...Logical Minimum (0)              28
460         0x25, 0x01,         # ...Logical Maxim    460         0x25, 0x01,         # ...Logical Maximum (1)              30
461         0x81, 0x02,         # ...Input (Data,V    461         0x81, 0x02,         # ...Input (Data,Var,Abs)             32
462         0x75, 0x03,         # ...Report Size (    462         0x75, 0x03,         # ...Report Size (3)                  34
463         0x95, 0x01,         # ...Report Count     463         0x95, 0x01,         # ...Report Count (1)                 36
464         0x81, 0x01,         # ...Input (Cnst,A    464         0x81, 0x01,         # ...Input (Cnst,Arr,Abs)             38
465         0x05, 0x01,         # ...Usage Page (G    465         0x05, 0x01,         # ...Usage Page (Generic Desktop)     40
466         0x09, 0x30,         # ...Usage (X)        466         0x09, 0x30,         # ...Usage (X)                        42
467         0x09, 0x31,         # ...Usage (Y)        467         0x09, 0x31,         # ...Usage (Y)                        44
468         0x95, 0x02,         # ...Report Count     468         0x95, 0x02,         # ...Report Count (2)                 46
469         0x75, 0x10,         # ...Report Size (    469         0x75, 0x10,         # ...Report Size (16)                 48
470         0x16, 0x01, 0x80,   # ...Logical Minim    470         0x16, 0x01, 0x80,   # ...Logical Minimum (-32767)         50
471         0x26, 0xff, 0x7f,   # ...Logical Maxim    471         0x26, 0xff, 0x7f,   # ...Logical Maximum (32767)          53
472         0x81, 0x06,         # ...Input (Data,V    472         0x81, 0x06,         # ...Input (Data,Var,Rel)             56
473         0xa1, 0x02,         # ...Collection (L    473         0xa1, 0x02,         # ...Collection (Logical)             58
474         0x85, 0x12,         # ....Report ID (1    474         0x85, 0x12,         # ....Report ID (18)                  60
475         0x09, 0x48,         # ....Usage (Resol    475         0x09, 0x48,         # ....Usage (Resolution Multiplier)   62
476         0x95, 0x01,         # ....Report Count    476         0x95, 0x01,         # ....Report Count (1)                64
477         0x75, 0x02,         # ....Report Size     477         0x75, 0x02,         # ....Report Size (2)                 66
478         0x15, 0x00,         # ....Logical Mini    478         0x15, 0x00,         # ....Logical Minimum (0)             68
479         0x25, 0x01,         # ....Logical Maxi    479         0x25, 0x01,         # ....Logical Maximum (1)             70
480         0x35, 0x01,         # ....Physical Min    480         0x35, 0x01,         # ....Physical Minimum (1)            72
481         0x45, 0x0c,         # ....Physical Max    481         0x45, 0x0c,         # ....Physical Maximum (12)           74
482         0xb1, 0x02,         # ....Feature (Dat    482         0xb1, 0x02,         # ....Feature (Data,Var,Abs)          76
483         0x85, 0x1a,         # ....Report ID (2    483         0x85, 0x1a,         # ....Report ID (26)                  78
484         0x09, 0x38,         # ....Usage (Wheel    484         0x09, 0x38,         # ....Usage (Wheel)                   80
485         0x35, 0x00,         # ....Physical Min    485         0x35, 0x00,         # ....Physical Minimum (0)            82
486         0x45, 0x00,         # ....Physical Max    486         0x45, 0x00,         # ....Physical Maximum (0)            84
487         0x95, 0x01,         # ....Report Count    487         0x95, 0x01,         # ....Report Count (1)                86
488         0x75, 0x10,         # ....Report Size     488         0x75, 0x10,         # ....Report Size (16)                88
489         0x16, 0x01, 0x80,   # ....Logical Mini    489         0x16, 0x01, 0x80,   # ....Logical Minimum (-32767)        90
490         0x26, 0xff, 0x7f,   # ....Logical Maxi    490         0x26, 0xff, 0x7f,   # ....Logical Maximum (32767)         93
491         0x81, 0x06,         # ....Input (Data,    491         0x81, 0x06,         # ....Input (Data,Var,Rel)            96
492         0xc0,               # ...End Collectio    492         0xc0,               # ...End Collection                   98
493         0xa1, 0x02,         # ...Collection (L    493         0xa1, 0x02,         # ...Collection (Logical)             99
494         0x85, 0x12,         # ....Report ID (1    494         0x85, 0x12,         # ....Report ID (18)                  101
495         0x09, 0x48,         # ....Usage (Resol    495         0x09, 0x48,         # ....Usage (Resolution Multiplier)   103
496         0x75, 0x02,         # ....Report Size     496         0x75, 0x02,         # ....Report Size (2)                 105
497         0x15, 0x00,         # ....Logical Mini    497         0x15, 0x00,         # ....Logical Minimum (0)             107
498         0x25, 0x01,         # ....Logical Maxi    498         0x25, 0x01,         # ....Logical Maximum (1)             109
499         0x35, 0x01,         # ....Physical Min    499         0x35, 0x01,         # ....Physical Minimum (1)            111
500         0x45, 0x0c,         # ....Physical Max    500         0x45, 0x0c,         # ....Physical Maximum (12)           113
501         0xb1, 0x02,         # ....Feature (Dat    501         0xb1, 0x02,         # ....Feature (Data,Var,Abs)          115
502         0x35, 0x00,         # ....Physical Min    502         0x35, 0x00,         # ....Physical Minimum (0)            117
503         0x45, 0x00,         # ....Physical Max    503         0x45, 0x00,         # ....Physical Maximum (0)            119
504         0x75, 0x04,         # ....Report Size     504         0x75, 0x04,         # ....Report Size (4)                 121
505         0xb1, 0x01,         # ....Feature (Cns    505         0xb1, 0x01,         # ....Feature (Cnst,Arr,Abs)          123
506         0x85, 0x1a,         # ....Report ID (2    506         0x85, 0x1a,         # ....Report ID (26)                  125
507         0x05, 0x0c,         # ....Usage Page (    507         0x05, 0x0c,         # ....Usage Page (Consumer Devices)   127
508         0x95, 0x01,         # ....Report Count    508         0x95, 0x01,         # ....Report Count (1)                129
509         0x75, 0x10,         # ....Report Size     509         0x75, 0x10,         # ....Report Size (16)                131
510         0x16, 0x01, 0x80,   # ....Logical Mini    510         0x16, 0x01, 0x80,   # ....Logical Minimum (-32767)        133
511         0x26, 0xff, 0x7f,   # ....Logical Maxi    511         0x26, 0xff, 0x7f,   # ....Logical Maximum (32767)         136
512         0x0a, 0x38, 0x02,   # ....Usage (AC Pa    512         0x0a, 0x38, 0x02,   # ....Usage (AC Pan)                  139
513         0x81, 0x06,         # ....Input (Data,    513         0x81, 0x06,         # ....Input (Data,Var,Rel)            142
514         0xc0,               # ...End Collectio    514         0xc0,               # ...End Collection                   144
515         0xc0,               # ..End Collection    515         0xc0,               # ..End Collection                    145
516         0xc0,               # .End Collection     516         0xc0,               # .End Collection                     146
517         0xc0,               # End Collection      517         0xc0,               # End Collection                      147
518     ]                                             518     ]
519     # fmt: on                                     519     # fmt: on
520                                                   520 
521     def __init__(self, rdesc=report_descriptor    521     def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
522         super().__init__(rdesc, name, input_in    522         super().__init__(rdesc, name, input_info)
523         self.default_reportID = 0x1A              523         self.default_reportID = 0x1A
524                                                   524 
525         # Feature Report 12, multiplier Featur    525         # Feature Report 12, multiplier Feature value must be set to 0b0101,
526         # i.e. 5. We should extract that from     526         # i.e. 5. We should extract that from the descriptor instead
527         # of hardcoding it here, but meanwhile    527         # of hardcoding it here, but meanwhile this will do.
528         self.set_feature_report = [0x12, 0x5]     528         self.set_feature_report = [0x12, 0x5]
529                                                   529 
530     def set_report(self, req, rnum, rtype, dat    530     def set_report(self, req, rnum, rtype, data):
531         super().set_report(req, rnum, rtype, d    531         super().set_report(req, rnum, rtype, data)
532                                                   532 
533         self.wheel_multiplier = 12                533         self.wheel_multiplier = 12
534         self.hwheel_multiplier = 12               534         self.hwheel_multiplier = 12
535                                                   535 
536         return 0                                  536         return 0
537                                                   537 
538                                                   538 
539 class BaseTest:                                   539 class BaseTest:
540     class TestMouse(base.BaseTestCase.TestUhid    540     class TestMouse(base.BaseTestCase.TestUhid):
541         def test_buttons(self):                   541         def test_buttons(self):
542             """check for button reliability.""    542             """check for button reliability."""
543             uhdev = self.uhdev                    543             uhdev = self.uhdev
544             evdev = uhdev.get_evdev()             544             evdev = uhdev.get_evdev()
545             syn_event = self.syn_event            545             syn_event = self.syn_event
546                                                   546 
547             r = uhdev.event(0, 0, (None, True,    547             r = uhdev.event(0, 0, (None, True, None))
548             expected_event = libevdev.InputEve    548             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1)
549             events = uhdev.next_sync_events()     549             events = uhdev.next_sync_events()
550             self.debug_reports(r, uhdev, event    550             self.debug_reports(r, uhdev, events)
551             self.assertInputEventsIn((syn_even    551             self.assertInputEventsIn((syn_event, expected_event), events)
552             assert evdev.value[libevdev.EV_KEY    552             assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1
553                                                   553 
554             r = uhdev.event(0, 0, (None, False    554             r = uhdev.event(0, 0, (None, False, None))
555             expected_event = libevdev.InputEve    555             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0)
556             events = uhdev.next_sync_events()     556             events = uhdev.next_sync_events()
557             self.debug_reports(r, uhdev, event    557             self.debug_reports(r, uhdev, events)
558             self.assertInputEventsIn((syn_even    558             self.assertInputEventsIn((syn_event, expected_event), events)
559             assert evdev.value[libevdev.EV_KEY    559             assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0
560                                                   560 
561             r = uhdev.event(0, 0, (None, None,    561             r = uhdev.event(0, 0, (None, None, True))
562             expected_event = libevdev.InputEve    562             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 1)
563             events = uhdev.next_sync_events()     563             events = uhdev.next_sync_events()
564             self.debug_reports(r, uhdev, event    564             self.debug_reports(r, uhdev, events)
565             self.assertInputEventsIn((syn_even    565             self.assertInputEventsIn((syn_event, expected_event), events)
566             assert evdev.value[libevdev.EV_KEY    566             assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 1
567                                                   567 
568             r = uhdev.event(0, 0, (None, None,    568             r = uhdev.event(0, 0, (None, None, False))
569             expected_event = libevdev.InputEve    569             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 0)
570             events = uhdev.next_sync_events()     570             events = uhdev.next_sync_events()
571             self.debug_reports(r, uhdev, event    571             self.debug_reports(r, uhdev, events)
572             self.assertInputEventsIn((syn_even    572             self.assertInputEventsIn((syn_event, expected_event), events)
573             assert evdev.value[libevdev.EV_KEY    573             assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 0
574                                                   574 
575             r = uhdev.event(0, 0, (True, None,    575             r = uhdev.event(0, 0, (True, None, None))
576             expected_event = libevdev.InputEve    576             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1)
577             events = uhdev.next_sync_events()     577             events = uhdev.next_sync_events()
578             self.debug_reports(r, uhdev, event    578             self.debug_reports(r, uhdev, events)
579             self.assertInputEventsIn((syn_even    579             self.assertInputEventsIn((syn_event, expected_event), events)
580             assert evdev.value[libevdev.EV_KEY    580             assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1
581                                                   581 
582             r = uhdev.event(0, 0, (False, None    582             r = uhdev.event(0, 0, (False, None, None))
583             expected_event = libevdev.InputEve    583             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0)
584             events = uhdev.next_sync_events()     584             events = uhdev.next_sync_events()
585             self.debug_reports(r, uhdev, event    585             self.debug_reports(r, uhdev, events)
586             self.assertInputEventsIn((syn_even    586             self.assertInputEventsIn((syn_event, expected_event), events)
587             assert evdev.value[libevdev.EV_KEY    587             assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
588                                                   588 
589             r = uhdev.event(0, 0, (True, True,    589             r = uhdev.event(0, 0, (True, True, None))
590             expected_event0 = libevdev.InputEv    590             expected_event0 = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1)
591             expected_event1 = libevdev.InputEv    591             expected_event1 = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1)
592             events = uhdev.next_sync_events()     592             events = uhdev.next_sync_events()
593             self.debug_reports(r, uhdev, event    593             self.debug_reports(r, uhdev, events)
594             self.assertInputEventsIn(             594             self.assertInputEventsIn(
595                 (syn_event, expected_event0, e    595                 (syn_event, expected_event0, expected_event1), events
596             )                                     596             )
597             assert evdev.value[libevdev.EV_KEY    597             assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1
598             assert evdev.value[libevdev.EV_KEY    598             assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1
599                                                   599 
600             r = uhdev.event(0, 0, (False, None    600             r = uhdev.event(0, 0, (False, None, None))
601             expected_event = libevdev.InputEve    601             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0)
602             events = uhdev.next_sync_events()     602             events = uhdev.next_sync_events()
603             self.debug_reports(r, uhdev, event    603             self.debug_reports(r, uhdev, events)
604             self.assertInputEventsIn((syn_even    604             self.assertInputEventsIn((syn_event, expected_event), events)
605             assert evdev.value[libevdev.EV_KEY    605             assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1
606             assert evdev.value[libevdev.EV_KEY    606             assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
607                                                   607 
608             r = uhdev.event(0, 0, (None, False    608             r = uhdev.event(0, 0, (None, False, None))
609             expected_event = libevdev.InputEve    609             expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0)
610             events = uhdev.next_sync_events()     610             events = uhdev.next_sync_events()
611             self.debug_reports(r, uhdev, event    611             self.debug_reports(r, uhdev, events)
612             self.assertInputEventsIn((syn_even    612             self.assertInputEventsIn((syn_event, expected_event), events)
613             assert evdev.value[libevdev.EV_KEY    613             assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0
614             assert evdev.value[libevdev.EV_KEY    614             assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
615                                                   615 
616         def test_relative(self):                  616         def test_relative(self):
617             """Check for relative events."""      617             """Check for relative events."""
618             uhdev = self.uhdev                    618             uhdev = self.uhdev
619                                                   619 
620             syn_event = self.syn_event            620             syn_event = self.syn_event
621                                                   621 
622             r = uhdev.event(0, -1)                622             r = uhdev.event(0, -1)
623             expected_event = libevdev.InputEve    623             expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_Y, -1)
624             events = uhdev.next_sync_events()     624             events = uhdev.next_sync_events()
625             self.debug_reports(r, uhdev, event    625             self.debug_reports(r, uhdev, events)
626             self.assertInputEvents((syn_event,    626             self.assertInputEvents((syn_event, expected_event), events)
627                                                   627 
628             r = uhdev.event(1, 0)                 628             r = uhdev.event(1, 0)
629             expected_event = libevdev.InputEve    629             expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_X, 1)
630             events = uhdev.next_sync_events()     630             events = uhdev.next_sync_events()
631             self.debug_reports(r, uhdev, event    631             self.debug_reports(r, uhdev, events)
632             self.assertInputEvents((syn_event,    632             self.assertInputEvents((syn_event, expected_event), events)
633                                                   633 
634             r = uhdev.event(-1, 2)                634             r = uhdev.event(-1, 2)
635             expected_event0 = libevdev.InputEv    635             expected_event0 = libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)
636             expected_event1 = libevdev.InputEv    636             expected_event1 = libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)
637             events = uhdev.next_sync_events()     637             events = uhdev.next_sync_events()
638             self.debug_reports(r, uhdev, event    638             self.debug_reports(r, uhdev, events)
639             self.assertInputEvents(               639             self.assertInputEvents(
640                 (syn_event, expected_event0, e    640                 (syn_event, expected_event0, expected_event1), events
641             )                                     641             )
642                                                   642 
643                                                   643 
644 class TestSimpleMouse(BaseTest.TestMouse):        644 class TestSimpleMouse(BaseTest.TestMouse):
645     def create_device(self):                      645     def create_device(self):
646         return ButtonMouse()                      646         return ButtonMouse()
647                                                   647 
648     def test_rdesc(self):                         648     def test_rdesc(self):
649         """Check that the testsuite actually m    649         """Check that the testsuite actually manages to format the
650         reports according to the report descri    650         reports according to the report descriptors.
651         No kernel device is used here"""          651         No kernel device is used here"""
652         uhdev = self.uhdev                        652         uhdev = self.uhdev
653                                                   653 
654         event = (0, 0, (None, None, None))        654         event = (0, 0, (None, None, None))
655         assert uhdev.fake_report(*event) == uh    655         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
656                                                   656 
657         event = (0, 0, (None, True, None))        657         event = (0, 0, (None, True, None))
658         assert uhdev.fake_report(*event) == uh    658         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
659                                                   659 
660         event = (0, 0, (True, True, None))        660         event = (0, 0, (True, True, None))
661         assert uhdev.fake_report(*event) == uh    661         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
662                                                   662 
663         event = (0, 0, (False, False, False))     663         event = (0, 0, (False, False, False))
664         assert uhdev.fake_report(*event) == uh    664         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
665                                                   665 
666         event = (1, 0, (True, False, True))       666         event = (1, 0, (True, False, True))
667         assert uhdev.fake_report(*event) == uh    667         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
668                                                   668 
669         event = (-1, 0, (True, False, True))      669         event = (-1, 0, (True, False, True))
670         assert uhdev.fake_report(*event) == uh    670         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
671                                                   671 
672         event = (-5, 5, (True, False, True))      672         event = (-5, 5, (True, False, True))
673         assert uhdev.fake_report(*event) == uh    673         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
674                                                   674 
675         event = (-127, 127, (True, False, True    675         event = (-127, 127, (True, False, True))
676         assert uhdev.fake_report(*event) == uh    676         assert uhdev.fake_report(*event) == uhdev.create_report(*event)
677                                                   677 
678         event = (0, -128, (True, False, True))    678         event = (0, -128, (True, False, True))
679         with pytest.raises(hidtools.hid.RangeE    679         with pytest.raises(hidtools.hid.RangeError):
680             uhdev.create_report(*event)           680             uhdev.create_report(*event)
681                                                   681 
682                                                   682 
683 class TestWheelMouse(BaseTest.TestMouse):         683 class TestWheelMouse(BaseTest.TestMouse):
684     def create_device(self):                      684     def create_device(self):
685         return WheelMouse()                       685         return WheelMouse()
686                                                   686 
687     def is_wheel_highres(self, uhdev):            687     def is_wheel_highres(self, uhdev):
688         evdev = uhdev.get_evdev()                 688         evdev = uhdev.get_evdev()
689         assert evdev.has(libevdev.EV_REL.REL_W    689         assert evdev.has(libevdev.EV_REL.REL_WHEEL)
690         return evdev.has(libevdev.EV_REL.REL_W    690         return evdev.has(libevdev.EV_REL.REL_WHEEL_HI_RES)
691                                                   691 
692     def test_wheel(self):                         692     def test_wheel(self):
693         uhdev = self.uhdev                        693         uhdev = self.uhdev
694                                                   694 
695         # check if the kernel is high res whee    695         # check if the kernel is high res wheel compatible
696         high_res_wheel = self.is_wheel_highres    696         high_res_wheel = self.is_wheel_highres(uhdev)
697                                                   697 
698         syn_event = self.syn_event                698         syn_event = self.syn_event
699         # The Resolution Multiplier is applied    699         # The Resolution Multiplier is applied to the HID reports, so we
700         # need to pre-multiply too.               700         # need to pre-multiply too.
701         mult = uhdev.wheel_multiplier             701         mult = uhdev.wheel_multiplier
702                                                   702 
703         r = uhdev.event(0, 0, wheels=1 * mult)    703         r = uhdev.event(0, 0, wheels=1 * mult)
704         expected = [syn_event]                    704         expected = [syn_event]
705         expected.append(libevdev.InputEvent(li    705         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1))
706         if high_res_wheel:                        706         if high_res_wheel:
707             expected.append(libevdev.InputEven    707             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120))
708         events = uhdev.next_sync_events()         708         events = uhdev.next_sync_events()
709         self.debug_reports(r, uhdev, events)      709         self.debug_reports(r, uhdev, events)
710         self.assertInputEvents(expected, event    710         self.assertInputEvents(expected, events)
711                                                   711 
712         r = uhdev.event(0, 0, wheels=-1 * mult    712         r = uhdev.event(0, 0, wheels=-1 * mult)
713         expected = [syn_event]                    713         expected = [syn_event]
714         expected.append(libevdev.InputEvent(li    714         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -1))
715         if high_res_wheel:                        715         if high_res_wheel:
716             expected.append(libevdev.InputEven    716             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120))
717         events = uhdev.next_sync_events()         717         events = uhdev.next_sync_events()
718         self.debug_reports(r, uhdev, events)      718         self.debug_reports(r, uhdev, events)
719         self.assertInputEvents(expected, event    719         self.assertInputEvents(expected, events)
720                                                   720 
721         r = uhdev.event(-1, 2, wheels=3 * mult    721         r = uhdev.event(-1, 2, wheels=3 * mult)
722         expected = [syn_event]                    722         expected = [syn_event]
723         expected.append(libevdev.InputEvent(li    723         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1))
724         expected.append(libevdev.InputEvent(li    724         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2))
725         expected.append(libevdev.InputEvent(li    725         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 3))
726         if high_res_wheel:                        726         if high_res_wheel:
727             expected.append(libevdev.InputEven    727             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 360))
728         events = uhdev.next_sync_events()         728         events = uhdev.next_sync_events()
729         self.debug_reports(r, uhdev, events)      729         self.debug_reports(r, uhdev, events)
730         self.assertInputEvents(expected, event    730         self.assertInputEvents(expected, events)
731                                                   731 
732                                                   732 
733 class TestTwoWheelMouse(TestWheelMouse):          733 class TestTwoWheelMouse(TestWheelMouse):
734     def create_device(self):                      734     def create_device(self):
735         return TwoWheelMouse()                    735         return TwoWheelMouse()
736                                                   736 
737     def is_hwheel_highres(self, uhdev):           737     def is_hwheel_highres(self, uhdev):
738         evdev = uhdev.get_evdev()                 738         evdev = uhdev.get_evdev()
739         assert evdev.has(libevdev.EV_REL.REL_H    739         assert evdev.has(libevdev.EV_REL.REL_HWHEEL)
740         return evdev.has(libevdev.EV_REL.REL_H    740         return evdev.has(libevdev.EV_REL.REL_HWHEEL_HI_RES)
741                                                   741 
742     def test_ac_pan(self):                        742     def test_ac_pan(self):
743         uhdev = self.uhdev                        743         uhdev = self.uhdev
744                                                   744 
745         # check if the kernel is high res whee    745         # check if the kernel is high res wheel compatible
746         high_res_wheel = self.is_wheel_highres    746         high_res_wheel = self.is_wheel_highres(uhdev)
747         high_res_hwheel = self.is_hwheel_highr    747         high_res_hwheel = self.is_hwheel_highres(uhdev)
748         assert high_res_wheel == high_res_hwhe    748         assert high_res_wheel == high_res_hwheel
749                                                   749 
750         syn_event = self.syn_event                750         syn_event = self.syn_event
751         # The Resolution Multiplier is applied    751         # The Resolution Multiplier is applied to the HID reports, so we
752         # need to pre-multiply too.               752         # need to pre-multiply too.
753         hmult = uhdev.hwheel_multiplier           753         hmult = uhdev.hwheel_multiplier
754         vmult = uhdev.wheel_multiplier            754         vmult = uhdev.wheel_multiplier
755                                                   755 
756         r = uhdev.event(0, 0, wheels=(0, 1 * h    756         r = uhdev.event(0, 0, wheels=(0, 1 * hmult))
757         expected = [syn_event]                    757         expected = [syn_event]
758         expected.append(libevdev.InputEvent(li    758         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1))
759         if high_res_hwheel:                       759         if high_res_hwheel:
760             expected.append(libevdev.InputEven    760             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120))
761         events = uhdev.next_sync_events()         761         events = uhdev.next_sync_events()
762         self.debug_reports(r, uhdev, events)      762         self.debug_reports(r, uhdev, events)
763         self.assertInputEvents(expected, event    763         self.assertInputEvents(expected, events)
764                                                   764 
765         r = uhdev.event(0, 0, wheels=(0, -1 *     765         r = uhdev.event(0, 0, wheels=(0, -1 * hmult))
766         expected = [syn_event]                    766         expected = [syn_event]
767         expected.append(libevdev.InputEvent(li    767         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, -1))
768         if high_res_hwheel:                       768         if high_res_hwheel:
769             expected.append(                      769             expected.append(
770                 libevdev.InputEvent(libevdev.E    770                 libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120)
771             )                                     771             )
772         events = uhdev.next_sync_events()         772         events = uhdev.next_sync_events()
773         self.debug_reports(r, uhdev, events)      773         self.debug_reports(r, uhdev, events)
774         self.assertInputEvents(expected, event    774         self.assertInputEvents(expected, events)
775                                                   775 
776         r = uhdev.event(-1, 2, wheels=(0, 3 *     776         r = uhdev.event(-1, 2, wheels=(0, 3 * hmult))
777         expected = [syn_event]                    777         expected = [syn_event]
778         expected.append(libevdev.InputEvent(li    778         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1))
779         expected.append(libevdev.InputEvent(li    779         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2))
780         expected.append(libevdev.InputEvent(li    780         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 3))
781         if high_res_hwheel:                       781         if high_res_hwheel:
782             expected.append(libevdev.InputEven    782             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 360))
783         events = uhdev.next_sync_events()         783         events = uhdev.next_sync_events()
784         self.debug_reports(r, uhdev, events)      784         self.debug_reports(r, uhdev, events)
785         self.assertInputEvents(expected, event    785         self.assertInputEvents(expected, events)
786                                                   786 
787         r = uhdev.event(-1, 2, wheels=(-3 * vm    787         r = uhdev.event(-1, 2, wheels=(-3 * vmult, 4 * hmult))
788         expected = [syn_event]                    788         expected = [syn_event]
789         expected.append(libevdev.InputEvent(li    789         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1))
790         expected.append(libevdev.InputEvent(li    790         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2))
791         expected.append(libevdev.InputEvent(li    791         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -3))
792         if high_res_wheel:                        792         if high_res_wheel:
793             expected.append(libevdev.InputEven    793             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -360))
794         expected.append(libevdev.InputEvent(li    794         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 4))
795         if high_res_wheel:                        795         if high_res_wheel:
796             expected.append(libevdev.InputEven    796             expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 480))
797         events = uhdev.next_sync_events()         797         events = uhdev.next_sync_events()
798         self.debug_reports(r, uhdev, events)      798         self.debug_reports(r, uhdev, events)
799         self.assertInputEvents(expected, event    799         self.assertInputEvents(expected, events)
800                                                   800 
801                                                   801 
802 class TestResolutionMultiplierMouse(TestTwoWhe    802 class TestResolutionMultiplierMouse(TestTwoWheelMouse):
803     def create_device(self):                      803     def create_device(self):
804         return ResolutionMultiplierMouse()        804         return ResolutionMultiplierMouse()
805                                                   805 
806     def is_wheel_highres(self, uhdev):            806     def is_wheel_highres(self, uhdev):
807         high_res = super().is_wheel_highres(uh    807         high_res = super().is_wheel_highres(uhdev)
808                                                   808 
809         if not high_res:                          809         if not high_res:
810             # the kernel doesn't seem to suppo    810             # the kernel doesn't seem to support the high res wheel mice,
811             # make sure we haven't triggered t    811             # make sure we haven't triggered the feature
812             assert uhdev.wheel_multiplier == 1    812             assert uhdev.wheel_multiplier == 1
813                                                   813 
814         return high_res                           814         return high_res
815                                                   815 
816     def test_resolution_multiplier_wheel(self)    816     def test_resolution_multiplier_wheel(self):
817         uhdev = self.uhdev                        817         uhdev = self.uhdev
818                                                   818 
819         if not self.is_wheel_highres(uhdev):      819         if not self.is_wheel_highres(uhdev):
820             pytest.skip("Kernel not compatible    820             pytest.skip("Kernel not compatible, we can not trigger the conditions")
821                                                   821 
822         assert uhdev.wheel_multiplier > 1         822         assert uhdev.wheel_multiplier > 1
823         assert 120 % uhdev.wheel_multiplier ==    823         assert 120 % uhdev.wheel_multiplier == 0
824                                                   824 
825     def test_wheel_with_multiplier(self):         825     def test_wheel_with_multiplier(self):
826         uhdev = self.uhdev                        826         uhdev = self.uhdev
827                                                   827 
828         if not self.is_wheel_highres(uhdev):      828         if not self.is_wheel_highres(uhdev):
829             pytest.skip("Kernel not compatible    829             pytest.skip("Kernel not compatible, we can not trigger the conditions")
830                                                   830 
831         assert uhdev.wheel_multiplier > 1         831         assert uhdev.wheel_multiplier > 1
832                                                   832 
833         syn_event = self.syn_event                833         syn_event = self.syn_event
834         mult = uhdev.wheel_multiplier             834         mult = uhdev.wheel_multiplier
835                                                   835 
836         r = uhdev.event(0, 0, wheels=1)           836         r = uhdev.event(0, 0, wheels=1)
837         expected = [syn_event]                    837         expected = [syn_event]
838         expected.append(                          838         expected.append(
839             libevdev.InputEvent(libevdev.EV_RE    839             libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult)
840         )                                         840         )
841         events = uhdev.next_sync_events()         841         events = uhdev.next_sync_events()
842         self.debug_reports(r, uhdev, events)      842         self.debug_reports(r, uhdev, events)
843         self.assertInputEvents(expected, event    843         self.assertInputEvents(expected, events)
844                                                   844 
845         r = uhdev.event(0, 0, wheels=-1)          845         r = uhdev.event(0, 0, wheels=-1)
846         expected = [syn_event]                    846         expected = [syn_event]
847         expected.append(                          847         expected.append(
848             libevdev.InputEvent(libevdev.EV_RE    848             libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120 / mult)
849         )                                         849         )
850         events = uhdev.next_sync_events()         850         events = uhdev.next_sync_events()
851         self.debug_reports(r, uhdev, events)      851         self.debug_reports(r, uhdev, events)
852         self.assertInputEvents(expected, event    852         self.assertInputEvents(expected, events)
853                                                   853 
854         expected = [syn_event]                    854         expected = [syn_event]
855         expected.append(libevdev.InputEvent(li    855         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1))
856         expected.append(libevdev.InputEvent(li    856         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2))
857         expected.append(                          857         expected.append(
858             libevdev.InputEvent(libevdev.EV_RE    858             libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult)
859         )                                         859         )
860                                                   860 
861         for _ in range(mult - 1):                 861         for _ in range(mult - 1):
862             r = uhdev.event(1, -2, wheels=1)      862             r = uhdev.event(1, -2, wheels=1)
863             events = uhdev.next_sync_events()     863             events = uhdev.next_sync_events()
864             self.debug_reports(r, uhdev, event    864             self.debug_reports(r, uhdev, events)
865             self.assertInputEvents(expected, e    865             self.assertInputEvents(expected, events)
866                                                   866 
867         r = uhdev.event(1, -2, wheels=1)          867         r = uhdev.event(1, -2, wheels=1)
868         expected.append(libevdev.InputEvent(li    868         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1))
869         events = uhdev.next_sync_events()         869         events = uhdev.next_sync_events()
870         self.debug_reports(r, uhdev, events)      870         self.debug_reports(r, uhdev, events)
871         self.assertInputEvents(expected, event    871         self.assertInputEvents(expected, events)
872                                                   872 
873                                                   873 
874 class TestBadResolutionMultiplierMouse(TestTwo    874 class TestBadResolutionMultiplierMouse(TestTwoWheelMouse):
875     def create_device(self):                      875     def create_device(self):
876         return BadResolutionMultiplierMouse()     876         return BadResolutionMultiplierMouse()
877                                                   877 
878     def is_wheel_highres(self, uhdev):            878     def is_wheel_highres(self, uhdev):
879         high_res = super().is_wheel_highres(uh    879         high_res = super().is_wheel_highres(uhdev)
880                                                   880 
881         assert uhdev.wheel_multiplier == 1        881         assert uhdev.wheel_multiplier == 1
882                                                   882 
883         return high_res                           883         return high_res
884                                                   884 
885     def test_resolution_multiplier_wheel(self)    885     def test_resolution_multiplier_wheel(self):
886         uhdev = self.uhdev                        886         uhdev = self.uhdev
887                                                   887 
888         assert uhdev.wheel_multiplier == 1        888         assert uhdev.wheel_multiplier == 1
889                                                   889 
890                                                   890 
891 class TestResolutionMultiplierHWheelMouse(Test    891 class TestResolutionMultiplierHWheelMouse(TestResolutionMultiplierMouse):
892     def create_device(self):                      892     def create_device(self):
893         return ResolutionMultiplierHWheelMouse    893         return ResolutionMultiplierHWheelMouse()
894                                                   894 
895     def is_hwheel_highres(self, uhdev):           895     def is_hwheel_highres(self, uhdev):
896         high_res = super().is_hwheel_highres(u    896         high_res = super().is_hwheel_highres(uhdev)
897                                                   897 
898         if not high_res:                          898         if not high_res:
899             # the kernel doesn't seem to suppo    899             # the kernel doesn't seem to support the high res wheel mice,
900             # make sure we haven't triggered t    900             # make sure we haven't triggered the feature
901             assert uhdev.hwheel_multiplier ==     901             assert uhdev.hwheel_multiplier == 1
902                                                   902 
903         return high_res                           903         return high_res
904                                                   904 
905     def test_resolution_multiplier_ac_pan(self    905     def test_resolution_multiplier_ac_pan(self):
906         uhdev = self.uhdev                        906         uhdev = self.uhdev
907                                                   907 
908         if not self.is_hwheel_highres(uhdev):     908         if not self.is_hwheel_highres(uhdev):
909             pytest.skip("Kernel not compatible    909             pytest.skip("Kernel not compatible, we can not trigger the conditions")
910                                                   910 
911         assert uhdev.hwheel_multiplier > 1        911         assert uhdev.hwheel_multiplier > 1
912         assert 120 % uhdev.hwheel_multiplier =    912         assert 120 % uhdev.hwheel_multiplier == 0
913                                                   913 
914     def test_ac_pan_with_multiplier(self):        914     def test_ac_pan_with_multiplier(self):
915         uhdev = self.uhdev                        915         uhdev = self.uhdev
916                                                   916 
917         if not self.is_hwheel_highres(uhdev):     917         if not self.is_hwheel_highres(uhdev):
918             pytest.skip("Kernel not compatible    918             pytest.skip("Kernel not compatible, we can not trigger the conditions")
919                                                   919 
920         assert uhdev.hwheel_multiplier > 1        920         assert uhdev.hwheel_multiplier > 1
921                                                   921 
922         syn_event = self.syn_event                922         syn_event = self.syn_event
923         hmult = uhdev.hwheel_multiplier           923         hmult = uhdev.hwheel_multiplier
924                                                   924 
925         r = uhdev.event(0, 0, wheels=(0, 1))      925         r = uhdev.event(0, 0, wheels=(0, 1))
926         expected = [syn_event]                    926         expected = [syn_event]
927         expected.append(                          927         expected.append(
928             libevdev.InputEvent(libevdev.EV_RE    928             libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult)
929         )                                         929         )
930         events = uhdev.next_sync_events()         930         events = uhdev.next_sync_events()
931         self.debug_reports(r, uhdev, events)      931         self.debug_reports(r, uhdev, events)
932         self.assertInputEvents(expected, event    932         self.assertInputEvents(expected, events)
933                                                   933 
934         r = uhdev.event(0, 0, wheels=(0, -1))     934         r = uhdev.event(0, 0, wheels=(0, -1))
935         expected = [syn_event]                    935         expected = [syn_event]
936         expected.append(                          936         expected.append(
937             libevdev.InputEvent(libevdev.EV_RE    937             libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120 / hmult)
938         )                                         938         )
939         events = uhdev.next_sync_events()         939         events = uhdev.next_sync_events()
940         self.debug_reports(r, uhdev, events)      940         self.debug_reports(r, uhdev, events)
941         self.assertInputEvents(expected, event    941         self.assertInputEvents(expected, events)
942                                                   942 
943         expected = [syn_event]                    943         expected = [syn_event]
944         expected.append(libevdev.InputEvent(li    944         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1))
945         expected.append(libevdev.InputEvent(li    945         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2))
946         expected.append(                          946         expected.append(
947             libevdev.InputEvent(libevdev.EV_RE    947             libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult)
948         )                                         948         )
949                                                   949 
950         for _ in range(hmult - 1):                950         for _ in range(hmult - 1):
951             r = uhdev.event(1, -2, wheels=(0,     951             r = uhdev.event(1, -2, wheels=(0, 1))
952             events = uhdev.next_sync_events()     952             events = uhdev.next_sync_events()
953             self.debug_reports(r, uhdev, event    953             self.debug_reports(r, uhdev, events)
954             self.assertInputEvents(expected, e    954             self.assertInputEvents(expected, events)
955                                                   955 
956         r = uhdev.event(1, -2, wheels=(0, 1))     956         r = uhdev.event(1, -2, wheels=(0, 1))
957         expected.append(libevdev.InputEvent(li    957         expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1))
958         events = uhdev.next_sync_events()         958         events = uhdev.next_sync_events()
959         self.debug_reports(r, uhdev, events)      959         self.debug_reports(r, uhdev, events)
960         self.assertInputEvents(expected, event    960         self.assertInputEvents(expected, events)
961                                                   961 
962                                                   962 
963 class TestMiMouse(TestWheelMouse):                963 class TestMiMouse(TestWheelMouse):
964     def create_device(self):                      964     def create_device(self):
965         return MIDongleMIWirelessMouse()          965         return MIDongleMIWirelessMouse()
966                                                   966 
967     def assertInputEvents(self, expected_event    967     def assertInputEvents(self, expected_events, effective_events):
968         # Buttons and x/y are spread over two     968         # Buttons and x/y are spread over two HID reports, so we can get two
969         # event frames for this device.           969         # event frames for this device.
970         remaining = self.assertInputEventsIn(e    970         remaining = self.assertInputEventsIn(expected_events, effective_events)
971         try:                                      971         try:
972             remaining.remove(libevdev.InputEve    972             remaining.remove(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT, 0))
973         except ValueError:                        973         except ValueError:
974             # If there's no SYN_REPORT in the     974             # If there's no SYN_REPORT in the list, continue and let the
975             # assert below print out the real     975             # assert below print out the real error
976             pass                                  976             pass
977         assert remaining == []                    977         assert remaining == []
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php