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 == []
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.