1#!/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3# -*- coding: utf-8 -*- 4# 5# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6# Copyright (c) 2019 Red Hat, Inc. 7# 8 9from . import base 10import libevdev 11import pytest 12 13from .base_gamepad import BaseGamepad, JoystickGamepad, AxisMapping 14from hidtools.util import BusType 15from .base import HidBpf 16 17import logging 18 19logger = logging.getLogger("hidtools.test.gamepad") 20 21 22class BaseTest: 23 class TestGamepad(base.BaseTestCase.TestUhid): 24 @pytest.fixture(autouse=True) 25 def send_initial_state(self): 26 """send an empty report to initialize the axes""" 27 uhdev = self.uhdev 28 29 r = uhdev.event() 30 events = uhdev.next_sync_events() 31 self.debug_reports(r, uhdev, events) 32 33 def assert_button(self, button): 34 uhdev = self.uhdev 35 evdev = uhdev.get_evdev() 36 syn_event = self.syn_event 37 38 buttons = {} 39 key = libevdev.evbit(uhdev.buttons_map[button]) 40 41 buttons[button] = True 42 r = uhdev.event(buttons=buttons) 43 expected_event = libevdev.InputEvent(key, 1) 44 events = uhdev.next_sync_events() 45 self.debug_reports(r, uhdev, events) 46 self.assertInputEventsIn((syn_event, expected_event), events) 47 assert evdev.value[key] == 1 48 49 buttons[button] = False 50 r = uhdev.event(buttons=buttons) 51 expected_event = libevdev.InputEvent(key, 0) 52 events = uhdev.next_sync_events() 53 self.debug_reports(r, uhdev, events) 54 self.assertInputEventsIn((syn_event, expected_event), events) 55 assert evdev.value[key] == 0 56 57 def test_buttons(self): 58 """check for button reliability.""" 59 uhdev = self.uhdev 60 61 for b in uhdev.buttons: 62 self.assert_button(b) 63 64 def test_dual_buttons(self): 65 """check for button reliability when pressing 2 buttons""" 66 uhdev = self.uhdev 67 evdev = uhdev.get_evdev() 68 syn_event = self.syn_event 69 70 # can change intended b1 b2 values 71 b1 = uhdev.buttons[0] 72 key1 = libevdev.evbit(uhdev.buttons_map[b1]) 73 b2 = uhdev.buttons[1] 74 key2 = libevdev.evbit(uhdev.buttons_map[b2]) 75 76 buttons = {b1: True, b2: True} 77 r = uhdev.event(buttons=buttons) 78 expected_event0 = libevdev.InputEvent(key1, 1) 79 expected_event1 = libevdev.InputEvent(key2, 1) 80 events = uhdev.next_sync_events() 81 self.debug_reports(r, uhdev, events) 82 self.assertInputEventsIn( 83 (syn_event, expected_event0, expected_event1), events 84 ) 85 assert evdev.value[key1] == 1 86 assert evdev.value[key2] == 1 87 88 buttons = {b1: False, b2: None} 89 r = uhdev.event(buttons=buttons) 90 expected_event = libevdev.InputEvent(key1, 0) 91 events = uhdev.next_sync_events() 92 self.debug_reports(r, uhdev, events) 93 self.assertInputEventsIn((syn_event, expected_event), events) 94 assert evdev.value[key1] == 0 95 assert evdev.value[key2] == 1 96 97 buttons = {b1: None, b2: False} 98 r = uhdev.event(buttons=buttons) 99 expected_event = libevdev.InputEvent(key2, 0) 100 events = uhdev.next_sync_events() 101 self.debug_reports(r, uhdev, events) 102 self.assertInputEventsIn((syn_event, expected_event), events) 103 assert evdev.value[key1] == 0 104 assert evdev.value[key2] == 0 105 106 def _get_libevdev_abs_events(self, which): 107 """Returns which ABS_* evdev axes are expected for the given stick""" 108 abs_map = self.uhdev.axes_map[which] 109 110 x = abs_map["x"].evdev 111 y = abs_map["y"].evdev 112 113 assert x 114 assert y 115 116 return x, y 117 118 def _test_joystick_press(self, which, data): 119 uhdev = self.uhdev 120 121 libevdev_axes = self._get_libevdev_abs_events(which) 122 123 r = None 124 if which == "left_stick": 125 r = uhdev.event(left=data) 126 else: 127 r = uhdev.event(right=data) 128 events = uhdev.next_sync_events() 129 self.debug_reports(r, uhdev, events) 130 131 for i, d in enumerate(data): 132 if d is not None and d != 127: 133 assert libevdev.InputEvent(libevdev_axes[i], d) in events 134 else: 135 assert libevdev.InputEvent(libevdev_axes[i]) not in events 136 137 def test_left_joystick_press_left(self): 138 """check for the left joystick reliability""" 139 self._test_joystick_press("left_stick", (63, None)) 140 self._test_joystick_press("left_stick", (0, 127)) 141 142 def test_left_joystick_press_right(self): 143 """check for the left joystick reliability""" 144 self._test_joystick_press("left_stick", (191, 127)) 145 self._test_joystick_press("left_stick", (255, None)) 146 147 def test_left_joystick_press_up(self): 148 """check for the left joystick reliability""" 149 self._test_joystick_press("left_stick", (None, 63)) 150 self._test_joystick_press("left_stick", (127, 0)) 151 152 def test_left_joystick_press_down(self): 153 """check for the left joystick reliability""" 154 self._test_joystick_press("left_stick", (127, 191)) 155 self._test_joystick_press("left_stick", (None, 255)) 156 157 def test_right_joystick_press_left(self): 158 """check for the right joystick reliability""" 159 self._test_joystick_press("right_stick", (63, None)) 160 self._test_joystick_press("right_stick", (0, 127)) 161 162 def test_right_joystick_press_right(self): 163 """check for the right joystick reliability""" 164 self._test_joystick_press("right_stick", (191, 127)) 165 self._test_joystick_press("right_stick", (255, None)) 166 167 def test_right_joystick_press_up(self): 168 """check for the right joystick reliability""" 169 self._test_joystick_press("right_stick", (None, 63)) 170 self._test_joystick_press("right_stick", (127, 0)) 171 172 def test_right_joystick_press_down(self): 173 """check for the right joystick reliability""" 174 self._test_joystick_press("right_stick", (127, 191)) 175 self._test_joystick_press("right_stick", (None, 255)) 176 177 @pytest.mark.skip_if_uhdev( 178 lambda uhdev: "Hat switch" not in uhdev.fields, 179 "Device not compatible, missing Hat switch usage", 180 ) 181 @pytest.mark.parametrize( 182 "hat_value,expected_evdev,evdev_value", 183 [ 184 (0, "ABS_HAT0Y", -1), 185 (2, "ABS_HAT0X", 1), 186 (4, "ABS_HAT0Y", 1), 187 (6, "ABS_HAT0X", -1), 188 ], 189 ) 190 def test_hat_switch(self, hat_value, expected_evdev, evdev_value): 191 uhdev = self.uhdev 192 193 r = uhdev.event(hat_switch=hat_value) 194 events = uhdev.next_sync_events() 195 self.debug_reports(r, uhdev, events) 196 assert ( 197 libevdev.InputEvent( 198 libevdev.evbit("EV_ABS", expected_evdev), evdev_value 199 ) 200 in events 201 ) 202 203 204class SaitekGamepad(JoystickGamepad): 205 # fmt: off 206 report_descriptor = [ 207 0x05, 0x01, # Usage Page (Generic Desktop) 0 208 0x09, 0x04, # Usage (Joystick) 2 209 0xa1, 0x01, # Collection (Application) 4 210 0x09, 0x01, # .Usage (Pointer) 6 211 0xa1, 0x00, # .Collection (Physical) 8 212 0x85, 0x01, # ..Report ID (1) 10 213 0x09, 0x30, # ..Usage (X) 12 214 0x15, 0x00, # ..Logical Minimum (0) 14 215 0x26, 0xff, 0x00, # ..Logical Maximum (255) 16 216 0x35, 0x00, # ..Physical Minimum (0) 19 217 0x46, 0xff, 0x00, # ..Physical Maximum (255) 21 218 0x75, 0x08, # ..Report Size (8) 24 219 0x95, 0x01, # ..Report Count (1) 26 220 0x81, 0x02, # ..Input (Data,Var,Abs) 28 221 0x09, 0x31, # ..Usage (Y) 30 222 0x81, 0x02, # ..Input (Data,Var,Abs) 32 223 0x05, 0x02, # ..Usage Page (Simulation Controls) 34 224 0x09, 0xba, # ..Usage (Rudder) 36 225 0x81, 0x02, # ..Input (Data,Var,Abs) 38 226 0x09, 0xbb, # ..Usage (Throttle) 40 227 0x81, 0x02, # ..Input (Data,Var,Abs) 42 228 0x05, 0x09, # ..Usage Page (Button) 44 229 0x19, 0x01, # ..Usage Minimum (1) 46 230 0x29, 0x0c, # ..Usage Maximum (12) 48 231 0x25, 0x01, # ..Logical Maximum (1) 50 232 0x45, 0x01, # ..Physical Maximum (1) 52 233 0x75, 0x01, # ..Report Size (1) 54 234 0x95, 0x0c, # ..Report Count (12) 56 235 0x81, 0x02, # ..Input (Data,Var,Abs) 58 236 0x95, 0x01, # ..Report Count (1) 60 237 0x75, 0x00, # ..Report Size (0) 62 238 0x81, 0x03, # ..Input (Cnst,Var,Abs) 64 239 0x05, 0x01, # ..Usage Page (Generic Desktop) 66 240 0x09, 0x39, # ..Usage (Hat switch) 68 241 0x25, 0x07, # ..Logical Maximum (7) 70 242 0x46, 0x3b, 0x01, # ..Physical Maximum (315) 72 243 0x55, 0x00, # ..Unit Exponent (0) 75 244 0x65, 0x44, # ..Unit (Degrees^4,EngRotation) 77 245 0x75, 0x04, # ..Report Size (4) 79 246 0x81, 0x42, # ..Input (Data,Var,Abs,Null) 81 247 0x65, 0x00, # ..Unit (None) 83 248 0xc0, # .End Collection 85 249 0x05, 0x0f, # .Usage Page (Vendor Usage Page 0x0f) 86 250 0x09, 0x92, # .Usage (Vendor Usage 0x92) 88 251 0xa1, 0x02, # .Collection (Logical) 90 252 0x85, 0x02, # ..Report ID (2) 92 253 0x09, 0xa0, # ..Usage (Vendor Usage 0xa0) 94 254 0x09, 0x9f, # ..Usage (Vendor Usage 0x9f) 96 255 0x25, 0x01, # ..Logical Maximum (1) 98 256 0x45, 0x00, # ..Physical Maximum (0) 100 257 0x75, 0x01, # ..Report Size (1) 102 258 0x95, 0x02, # ..Report Count (2) 104 259 0x81, 0x02, # ..Input (Data,Var,Abs) 106 260 0x75, 0x06, # ..Report Size (6) 108 261 0x95, 0x01, # ..Report Count (1) 110 262 0x81, 0x03, # ..Input (Cnst,Var,Abs) 112 263 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 114 264 0x75, 0x07, # ..Report Size (7) 116 265 0x25, 0x7f, # ..Logical Maximum (127) 118 266 0x81, 0x02, # ..Input (Data,Var,Abs) 120 267 0x09, 0x94, # ..Usage (Vendor Usage 0x94) 122 268 0x75, 0x01, # ..Report Size (1) 124 269 0x25, 0x01, # ..Logical Maximum (1) 126 270 0x81, 0x02, # ..Input (Data,Var,Abs) 128 271 0xc0, # .End Collection 130 272 0x09, 0x21, # .Usage (Vendor Usage 0x21) 131 273 0xa1, 0x02, # .Collection (Logical) 133 274 0x85, 0x0b, # ..Report ID (11) 135 275 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 137 276 0x26, 0xff, 0x00, # ..Logical Maximum (255) 139 277 0x75, 0x08, # ..Report Size (8) 142 278 0x91, 0x02, # ..Output (Data,Var,Abs) 144 279 0x09, 0x53, # ..Usage (Vendor Usage 0x53) 146 280 0x25, 0x0a, # ..Logical Maximum (10) 148 281 0x91, 0x02, # ..Output (Data,Var,Abs) 150 282 0x09, 0x50, # ..Usage (Vendor Usage 0x50) 152 283 0x27, 0xfe, 0xff, 0x00, 0x00, # ..Logical Maximum (65534) 154 284 0x47, 0xfe, 0xff, 0x00, 0x00, # ..Physical Maximum (65534) 159 285 0x75, 0x10, # ..Report Size (16) 164 286 0x55, 0xfd, # ..Unit Exponent (237) 166 287 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 168 288 0x91, 0x02, # ..Output (Data,Var,Abs) 171 289 0x55, 0x00, # ..Unit Exponent (0) 173 290 0x65, 0x00, # ..Unit (None) 175 291 0x09, 0x54, # ..Usage (Vendor Usage 0x54) 177 292 0x55, 0xfd, # ..Unit Exponent (237) 179 293 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 181 294 0x91, 0x02, # ..Output (Data,Var,Abs) 184 295 0x55, 0x00, # ..Unit Exponent (0) 186 296 0x65, 0x00, # ..Unit (None) 188 297 0x09, 0xa7, # ..Usage (Vendor Usage 0xa7) 190 298 0x55, 0xfd, # ..Unit Exponent (237) 192 299 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 194 300 0x91, 0x02, # ..Output (Data,Var,Abs) 197 301 0x55, 0x00, # ..Unit Exponent (0) 199 302 0x65, 0x00, # ..Unit (None) 201 303 0xc0, # .End Collection 203 304 0x09, 0x5a, # .Usage (Vendor Usage 0x5a) 204 305 0xa1, 0x02, # .Collection (Logical) 206 306 0x85, 0x0c, # ..Report ID (12) 208 307 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 210 308 0x26, 0xff, 0x00, # ..Logical Maximum (255) 212 309 0x45, 0x00, # ..Physical Maximum (0) 215 310 0x75, 0x08, # ..Report Size (8) 217 311 0x91, 0x02, # ..Output (Data,Var,Abs) 219 312 0x09, 0x5c, # ..Usage (Vendor Usage 0x5c) 221 313 0x26, 0x10, 0x27, # ..Logical Maximum (10000) 223 314 0x46, 0x10, 0x27, # ..Physical Maximum (10000) 226 315 0x75, 0x10, # ..Report Size (16) 229 316 0x55, 0xfd, # ..Unit Exponent (237) 231 317 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 233 318 0x91, 0x02, # ..Output (Data,Var,Abs) 236 319 0x55, 0x00, # ..Unit Exponent (0) 238 320 0x65, 0x00, # ..Unit (None) 240 321 0x09, 0x5b, # ..Usage (Vendor Usage 0x5b) 242 322 0x25, 0x7f, # ..Logical Maximum (127) 244 323 0x75, 0x08, # ..Report Size (8) 246 324 0x91, 0x02, # ..Output (Data,Var,Abs) 248 325 0x09, 0x5e, # ..Usage (Vendor Usage 0x5e) 250 326 0x26, 0x10, 0x27, # ..Logical Maximum (10000) 252 327 0x75, 0x10, # ..Report Size (16) 255 328 0x55, 0xfd, # ..Unit Exponent (237) 257 329 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 259 330 0x91, 0x02, # ..Output (Data,Var,Abs) 262 331 0x55, 0x00, # ..Unit Exponent (0) 264 332 0x65, 0x00, # ..Unit (None) 266 333 0x09, 0x5d, # ..Usage (Vendor Usage 0x5d) 268 334 0x25, 0x7f, # ..Logical Maximum (127) 270 335 0x75, 0x08, # ..Report Size (8) 272 336 0x91, 0x02, # ..Output (Data,Var,Abs) 274 337 0xc0, # .End Collection 276 338 0x09, 0x73, # .Usage (Vendor Usage 0x73) 277 339 0xa1, 0x02, # .Collection (Logical) 279 340 0x85, 0x0d, # ..Report ID (13) 281 341 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 283 342 0x26, 0xff, 0x00, # ..Logical Maximum (255) 285 343 0x45, 0x00, # ..Physical Maximum (0) 288 344 0x91, 0x02, # ..Output (Data,Var,Abs) 290 345 0x09, 0x70, # ..Usage (Vendor Usage 0x70) 292 346 0x15, 0x81, # ..Logical Minimum (-127) 294 347 0x25, 0x7f, # ..Logical Maximum (127) 296 348 0x36, 0xf0, 0xd8, # ..Physical Minimum (-10000) 298 349 0x46, 0x10, 0x27, # ..Physical Maximum (10000) 301 350 0x91, 0x02, # ..Output (Data,Var,Abs) 304 351 0xc0, # .End Collection 306 352 0x09, 0x6e, # .Usage (Vendor Usage 0x6e) 307 353 0xa1, 0x02, # .Collection (Logical) 309 354 0x85, 0x0e, # ..Report ID (14) 311 355 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 313 356 0x15, 0x00, # ..Logical Minimum (0) 315 357 0x26, 0xff, 0x00, # ..Logical Maximum (255) 317 358 0x35, 0x00, # ..Physical Minimum (0) 320 359 0x45, 0x00, # ..Physical Maximum (0) 322 360 0x91, 0x02, # ..Output (Data,Var,Abs) 324 361 0x09, 0x70, # ..Usage (Vendor Usage 0x70) 326 362 0x25, 0x7f, # ..Logical Maximum (127) 328 363 0x46, 0x10, 0x27, # ..Physical Maximum (10000) 330 364 0x91, 0x02, # ..Output (Data,Var,Abs) 333 365 0x09, 0x6f, # ..Usage (Vendor Usage 0x6f) 335 366 0x15, 0x81, # ..Logical Minimum (-127) 337 367 0x36, 0xf0, 0xd8, # ..Physical Minimum (-10000) 339 368 0x91, 0x02, # ..Output (Data,Var,Abs) 342 369 0x09, 0x71, # ..Usage (Vendor Usage 0x71) 344 370 0x15, 0x00, # ..Logical Minimum (0) 346 371 0x26, 0xff, 0x00, # ..Logical Maximum (255) 348 372 0x35, 0x00, # ..Physical Minimum (0) 351 373 0x46, 0x68, 0x01, # ..Physical Maximum (360) 353 374 0x91, 0x02, # ..Output (Data,Var,Abs) 356 375 0x09, 0x72, # ..Usage (Vendor Usage 0x72) 358 376 0x75, 0x10, # ..Report Size (16) 360 377 0x26, 0x10, 0x27, # ..Logical Maximum (10000) 362 378 0x46, 0x10, 0x27, # ..Physical Maximum (10000) 365 379 0x55, 0xfd, # ..Unit Exponent (237) 368 380 0x66, 0x01, 0x10, # ..Unit (Seconds,SILinear) 370 381 0x91, 0x02, # ..Output (Data,Var,Abs) 373 382 0x55, 0x00, # ..Unit Exponent (0) 375 383 0x65, 0x00, # ..Unit (None) 377 384 0xc0, # .End Collection 379 385 0x09, 0x77, # .Usage (Vendor Usage 0x77) 380 386 0xa1, 0x02, # .Collection (Logical) 382 387 0x85, 0x51, # ..Report ID (81) 384 388 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 386 389 0x25, 0x7f, # ..Logical Maximum (127) 388 390 0x45, 0x00, # ..Physical Maximum (0) 390 391 0x75, 0x08, # ..Report Size (8) 392 392 0x91, 0x02, # ..Output (Data,Var,Abs) 394 393 0x09, 0x78, # ..Usage (Vendor Usage 0x78) 396 394 0xa1, 0x02, # ..Collection (Logical) 398 395 0x09, 0x7b, # ...Usage (Vendor Usage 0x7b) 400 396 0x09, 0x79, # ...Usage (Vendor Usage 0x79) 402 397 0x09, 0x7a, # ...Usage (Vendor Usage 0x7a) 404 398 0x15, 0x01, # ...Logical Minimum (1) 406 399 0x25, 0x03, # ...Logical Maximum (3) 408 400 0x91, 0x00, # ...Output (Data,Arr,Abs) 410 401 0xc0, # ..End Collection 412 402 0x09, 0x7c, # ..Usage (Vendor Usage 0x7c) 413 403 0x15, 0x00, # ..Logical Minimum (0) 415 404 0x26, 0xfe, 0x00, # ..Logical Maximum (254) 417 405 0x91, 0x02, # ..Output (Data,Var,Abs) 420 406 0xc0, # .End Collection 422 407 0x09, 0x92, # .Usage (Vendor Usage 0x92) 423 408 0xa1, 0x02, # .Collection (Logical) 425 409 0x85, 0x52, # ..Report ID (82) 427 410 0x09, 0x96, # ..Usage (Vendor Usage 0x96) 429 411 0xa1, 0x02, # ..Collection (Logical) 431 412 0x09, 0x9a, # ...Usage (Vendor Usage 0x9a) 433 413 0x09, 0x99, # ...Usage (Vendor Usage 0x99) 435 414 0x09, 0x97, # ...Usage (Vendor Usage 0x97) 437 415 0x09, 0x98, # ...Usage (Vendor Usage 0x98) 439 416 0x09, 0x9b, # ...Usage (Vendor Usage 0x9b) 441 417 0x09, 0x9c, # ...Usage (Vendor Usage 0x9c) 443 418 0x15, 0x01, # ...Logical Minimum (1) 445 419 0x25, 0x06, # ...Logical Maximum (6) 447 420 0x91, 0x00, # ...Output (Data,Arr,Abs) 449 421 0xc0, # ..End Collection 451 422 0xc0, # .End Collection 452 423 0x05, 0xff, # .Usage Page (Vendor Usage Page 0xff) 453 424 0x0a, 0x01, 0x03, # .Usage (Vendor Usage 0x301) 455 425 0xa1, 0x02, # .Collection (Logical) 458 426 0x85, 0x40, # ..Report ID (64) 460 427 0x0a, 0x02, 0x03, # ..Usage (Vendor Usage 0x302) 462 428 0xa1, 0x02, # ..Collection (Logical) 465 429 0x1a, 0x11, 0x03, # ...Usage Minimum (785) 467 430 0x2a, 0x20, 0x03, # ...Usage Maximum (800) 470 431 0x25, 0x10, # ...Logical Maximum (16) 473 432 0x91, 0x00, # ...Output (Data,Arr,Abs) 475 433 0xc0, # ..End Collection 477 434 0x0a, 0x03, 0x03, # ..Usage (Vendor Usage 0x303) 478 435 0x15, 0x00, # ..Logical Minimum (0) 481 436 0x27, 0xff, 0xff, 0x00, 0x00, # ..Logical Maximum (65535) 483 437 0x75, 0x10, # ..Report Size (16) 488 438 0x91, 0x02, # ..Output (Data,Var,Abs) 490 439 0xc0, # .End Collection 492 440 0x05, 0x0f, # .Usage Page (Vendor Usage Page 0x0f) 493 441 0x09, 0x7d, # .Usage (Vendor Usage 0x7d) 495 442 0xa1, 0x02, # .Collection (Logical) 497 443 0x85, 0x43, # ..Report ID (67) 499 444 0x09, 0x7e, # ..Usage (Vendor Usage 0x7e) 501 445 0x26, 0x80, 0x00, # ..Logical Maximum (128) 503 446 0x46, 0x10, 0x27, # ..Physical Maximum (10000) 506 447 0x75, 0x08, # ..Report Size (8) 509 448 0x91, 0x02, # ..Output (Data,Var,Abs) 511 449 0xc0, # .End Collection 513 450 0x09, 0x7f, # .Usage (Vendor Usage 0x7f) 514 451 0xa1, 0x02, # .Collection (Logical) 516 452 0x85, 0x0b, # ..Report ID (11) 518 453 0x09, 0x80, # ..Usage (Vendor Usage 0x80) 520 454 0x26, 0xff, 0x7f, # ..Logical Maximum (32767) 522 455 0x45, 0x00, # ..Physical Maximum (0) 525 456 0x75, 0x0f, # ..Report Size (15) 527 457 0xb1, 0x03, # ..Feature (Cnst,Var,Abs) 529 458 0x09, 0xa9, # ..Usage (Vendor Usage 0xa9) 531 459 0x25, 0x01, # ..Logical Maximum (1) 533 460 0x75, 0x01, # ..Report Size (1) 535 461 0xb1, 0x03, # ..Feature (Cnst,Var,Abs) 537 462 0x09, 0x83, # ..Usage (Vendor Usage 0x83) 539 463 0x26, 0xff, 0x00, # ..Logical Maximum (255) 541 464 0x75, 0x08, # ..Report Size (8) 544 465 0xb1, 0x03, # ..Feature (Cnst,Var,Abs) 546 466 0xc0, # .End Collection 548 467 0x09, 0xab, # .Usage (Vendor Usage 0xab) 549 468 0xa1, 0x03, # .Collection (Report) 551 469 0x85, 0x15, # ..Report ID (21) 553 470 0x09, 0x25, # ..Usage (Vendor Usage 0x25) 555 471 0xa1, 0x02, # ..Collection (Logical) 557 472 0x09, 0x26, # ...Usage (Vendor Usage 0x26) 559 473 0x09, 0x30, # ...Usage (Vendor Usage 0x30) 561 474 0x09, 0x32, # ...Usage (Vendor Usage 0x32) 563 475 0x09, 0x31, # ...Usage (Vendor Usage 0x31) 565 476 0x09, 0x33, # ...Usage (Vendor Usage 0x33) 567 477 0x09, 0x34, # ...Usage (Vendor Usage 0x34) 569 478 0x15, 0x01, # ...Logical Minimum (1) 571 479 0x25, 0x06, # ...Logical Maximum (6) 573 480 0xb1, 0x00, # ...Feature (Data,Arr,Abs) 575 481 0xc0, # ..End Collection 577 482 0xc0, # .End Collection 578 483 0x09, 0x89, # .Usage (Vendor Usage 0x89) 579 484 0xa1, 0x03, # .Collection (Report) 581 485 0x85, 0x16, # ..Report ID (22) 583 486 0x09, 0x8b, # ..Usage (Vendor Usage 0x8b) 585 487 0xa1, 0x02, # ..Collection (Logical) 587 488 0x09, 0x8c, # ...Usage (Vendor Usage 0x8c) 589 489 0x09, 0x8d, # ...Usage (Vendor Usage 0x8d) 591 490 0x09, 0x8e, # ...Usage (Vendor Usage 0x8e) 593 491 0x25, 0x03, # ...Logical Maximum (3) 595 492 0xb1, 0x00, # ...Feature (Data,Arr,Abs) 597 493 0xc0, # ..End Collection 599 494 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 600 495 0x15, 0x00, # ..Logical Minimum (0) 602 496 0x26, 0xfe, 0x00, # ..Logical Maximum (254) 604 497 0xb1, 0x02, # ..Feature (Data,Var,Abs) 607 498 0xc0, # .End Collection 609 499 0x09, 0x90, # .Usage (Vendor Usage 0x90) 610 500 0xa1, 0x03, # .Collection (Report) 612 501 0x85, 0x50, # ..Report ID (80) 614 502 0x09, 0x22, # ..Usage (Vendor Usage 0x22) 616 503 0x26, 0xff, 0x00, # ..Logical Maximum (255) 618 504 0x91, 0x02, # ..Output (Data,Var,Abs) 621 505 0xc0, # .End Collection 623 506 0xc0, # End Collection 624 507 ] 508 # fmt: on 509 510 def __init__(self, rdesc=report_descriptor, name=None): 511 super().__init__(rdesc, name=name, input_info=(BusType.USB, 0x06A3, 0xFF0D)) 512 self.buttons = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) 513 514 515class AsusGamepad(BaseGamepad): 516 # fmt: off 517 report_descriptor = [ 518 0x05, 0x01, # Usage Page (Generic Desktop) 0 519 0x09, 0x05, # Usage (Game Pad) 2 520 0xa1, 0x01, # Collection (Application) 4 521 0x85, 0x01, # .Report ID (1) 6 522 0x05, 0x09, # .Usage Page (Button) 8 523 0x0a, 0x01, 0x00, # .Usage (Vendor Usage 0x01) 10 524 0x0a, 0x02, 0x00, # .Usage (Vendor Usage 0x02) 13 525 0x0a, 0x04, 0x00, # .Usage (Vendor Usage 0x04) 16 526 0x0a, 0x05, 0x00, # .Usage (Vendor Usage 0x05) 19 527 0x0a, 0x07, 0x00, # .Usage (Vendor Usage 0x07) 22 528 0x0a, 0x08, 0x00, # .Usage (Vendor Usage 0x08) 25 529 0x0a, 0x0e, 0x00, # .Usage (Vendor Usage 0x0e) 28 530 0x0a, 0x0f, 0x00, # .Usage (Vendor Usage 0x0f) 31 531 0x0a, 0x0d, 0x00, # .Usage (Vendor Usage 0x0d) 34 532 0x05, 0x0c, # .Usage Page (Consumer Devices) 37 533 0x0a, 0x24, 0x02, # .Usage (AC Back) 39 534 0x0a, 0x23, 0x02, # .Usage (AC Home) 42 535 0x15, 0x00, # .Logical Minimum (0) 45 536 0x25, 0x01, # .Logical Maximum (1) 47 537 0x75, 0x01, # .Report Size (1) 49 538 0x95, 0x0b, # .Report Count (11) 51 539 0x81, 0x02, # .Input (Data,Var,Abs) 53 540 0x75, 0x01, # .Report Size (1) 55 541 0x95, 0x01, # .Report Count (1) 57 542 0x81, 0x03, # .Input (Cnst,Var,Abs) 59 543 0x05, 0x01, # .Usage Page (Generic Desktop) 61 544 0x75, 0x04, # .Report Size (4) 63 545 0x95, 0x01, # .Report Count (1) 65 546 0x25, 0x07, # .Logical Maximum (7) 67 547 0x46, 0x3b, 0x01, # .Physical Maximum (315) 69 548 0x66, 0x14, 0x00, # .Unit (Degrees,EngRotation) 72 549 0x09, 0x39, # .Usage (Hat switch) 75 550 0x81, 0x42, # .Input (Data,Var,Abs,Null) 77 551 0x66, 0x00, 0x00, # .Unit (None) 79 552 0x09, 0x01, # .Usage (Pointer) 82 553 0xa1, 0x00, # .Collection (Physical) 84 554 0x09, 0x30, # ..Usage (X) 86 555 0x09, 0x31, # ..Usage (Y) 88 556 0x09, 0x32, # ..Usage (Z) 90 557 0x09, 0x35, # ..Usage (Rz) 92 558 0x05, 0x02, # ..Usage Page (Simulation Controls) 94 559 0x09, 0xc5, # ..Usage (Brake) 96 560 0x09, 0xc4, # ..Usage (Accelerator) 98 561 0x15, 0x00, # ..Logical Minimum (0) 100 562 0x26, 0xff, 0x00, # ..Logical Maximum (255) 102 563 0x35, 0x00, # ..Physical Minimum (0) 105 564 0x46, 0xff, 0x00, # ..Physical Maximum (255) 107 565 0x75, 0x08, # ..Report Size (8) 110 566 0x95, 0x06, # ..Report Count (6) 112 567 0x81, 0x02, # ..Input (Data,Var,Abs) 114 568 0xc0, # .End Collection 116 569 0x85, 0x02, # .Report ID (2) 117 570 0x05, 0x08, # .Usage Page (LEDs) 119 571 0x0a, 0x01, 0x00, # .Usage (Num Lock) 121 572 0x0a, 0x02, 0x00, # .Usage (Caps Lock) 124 573 0x0a, 0x03, 0x00, # .Usage (Scroll Lock) 127 574 0x0a, 0x04, 0x00, # .Usage (Compose) 130 575 0x15, 0x00, # .Logical Minimum (0) 133 576 0x25, 0x01, # .Logical Maximum (1) 135 577 0x75, 0x01, # .Report Size (1) 137 578 0x95, 0x04, # .Report Count (4) 139 579 0x91, 0x02, # .Output (Data,Var,Abs) 141 580 0x75, 0x04, # .Report Size (4) 143 581 0x95, 0x01, # .Report Count (1) 145 582 0x91, 0x03, # .Output (Cnst,Var,Abs) 147 583 0xc0, # End Collection 149 584 0x05, 0x0c, # Usage Page (Consumer Devices) 150 585 0x09, 0x01, # Usage (Consumer Control) 152 586 0xa1, 0x01, # Collection (Application) 154 587 0x85, 0x03, # .Report ID (3) 156 588 0x05, 0x01, # .Usage Page (Generic Desktop) 158 589 0x09, 0x06, # .Usage (Keyboard) 160 590 0xa1, 0x02, # .Collection (Logical) 162 591 0x05, 0x06, # ..Usage Page (Generic Device Controls) 164 592 0x09, 0x20, # ..Usage (Battery Strength) 166 593 0x15, 0x00, # ..Logical Minimum (0) 168 594 0x26, 0xff, 0x00, # ..Logical Maximum (255) 170 595 0x75, 0x08, # ..Report Size (8) 173 596 0x95, 0x01, # ..Report Count (1) 175 597 0x81, 0x02, # ..Input (Data,Var,Abs) 177 598 0x06, 0xbc, 0xff, # ..Usage Page (Vendor Usage Page 0xffbc) 179 599 0x0a, 0xad, 0xbd, # ..Usage (Vendor Usage 0xbdad) 182 600 0x75, 0x08, # ..Report Size (8) 185 601 0x95, 0x06, # ..Report Count (6) 187 602 0x81, 0x02, # ..Input (Data,Var,Abs) 189 603 0xc0, # .End Collection 191 604 0xc0, # End Collection 192 605 ] 606 # fmt: on 607 608 def __init__(self, rdesc=report_descriptor, name=None): 609 super().__init__(rdesc, name=name, input_info=(BusType.USB, 0x18D1, 0x2C40)) 610 self.buttons = (1, 2, 4, 5, 7, 8, 14, 15, 13) 611 612 613class RaptorMach2Joystick(JoystickGamepad): 614 axes_map = { 615 "left_stick": { 616 "x": AxisMapping("x"), 617 "y": AxisMapping("y"), 618 }, 619 "right_stick": { 620 "x": AxisMapping("z"), 621 "y": AxisMapping("Rz"), 622 }, 623 } 624 625 def __init__( 626 self, 627 name, 628 rdesc=None, 629 application="Joystick", 630 input_info=(BusType.USB, 0x11C0, 0x5606), 631 ): 632 super().__init__(rdesc, application, name, input_info) 633 self.buttons = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) 634 self.hat_switch = 240 # null value is 240 as max is 239 635 636 def event( 637 self, *, left=(None, None), right=(None, None), hat_switch=None, buttons=None 638 ): 639 if hat_switch is not None: 640 hat_switch *= 30 641 642 return super().event( 643 left=left, right=right, hat_switch=hat_switch, buttons=buttons 644 ) 645 646 647class TestSaitekGamepad(BaseTest.TestGamepad): 648 def create_device(self): 649 return SaitekGamepad() 650 651 652class TestAsusGamepad(BaseTest.TestGamepad): 653 def create_device(self): 654 return AsusGamepad() 655 656 657class TestRaptorMach2Joystick(BaseTest.TestGamepad): 658 hid_bpfs = [HidBpf("FR-TEC__Raptor-Mach-2.bpf.o", True)] 659 660 def create_device(self): 661 return RaptorMach2Joystick( 662 "uhid test Sanmos Group FR-TEC Raptor MACH 2", 663 rdesc="05 01 09 04 a1 01 05 01 85 01 05 01 09 30 75 10 95 01 15 00 26 ff 07 46 ff 07 81 02 05 01 09 31 75 10 95 01 15 00 26 ff 07 46 ff 07 81 02 05 01 09 33 75 10 95 01 15 00 26 ff 03 46 ff 03 81 02 05 00 09 00 75 10 95 01 15 00 26 ff 03 46 ff 03 81 02 05 01 09 32 75 10 95 01 15 00 26 ff 03 46 ff 03 81 02 05 01 09 35 75 10 95 01 15 00 26 ff 03 46 ff 03 81 02 05 01 09 34 75 10 95 01 15 00 26 ff 07 46 ff 07 81 02 05 01 09 36 75 10 95 01 15 00 26 ff 03 46 ff 03 81 02 05 09 19 01 2a 1d 00 15 00 25 01 75 01 96 80 00 81 02 05 01 09 39 26 ef 00 46 68 01 65 14 75 10 95 01 81 42 05 01 09 00 75 08 95 1d 81 01 15 00 26 ef 00 85 58 26 ff 00 46 ff 00 75 08 95 3f 09 00 91 02 85 59 75 08 95 80 09 00 b1 02 c0", 664 input_info=(BusType.USB, 0x11C0, 0x5606), 665 ) 666