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