brintos

brintos / linux-shallow public Read only

0
0
Text · 13.1 KiB · 7e52c28 Raw
343 lines · python
1#!/bin/env python32# SPDX-License-Identifier: GPL-2.03# -*- coding: utf-8 -*-4#5# Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com>6# Copyright (c) 2020 Red Hat, Inc.7#8 9from .base import application_matches10from .test_gamepad import BaseTest11from hidtools.device.sony_gamepad import (12    PS3Controller,13    PS4ControllerBluetooth,14    PS4ControllerUSB,15    PS5ControllerBluetooth,16    PS5ControllerUSB,17    PSTouchPoint,18)19from hidtools.util import BusType20 21import libevdev22import logging23import pytest24 25logger = logging.getLogger("hidtools.test.sony")26 27PS3_MODULE = ("sony", "hid_sony")28PS4_MODULE = ("playstation", "hid_playstation")29PS5_MODULE = ("playstation", "hid_playstation")30 31 32class SonyBaseTest:33    class SonyTest(BaseTest.TestGamepad):34        pass35 36    class SonyPS4ControllerTest(SonyTest):37        kernel_modules = [PS4_MODULE]38 39        def test_accelerometer(self):40            uhdev = self.uhdev41            evdev = uhdev.get_evdev("Accelerometer")42 43            for x in range(-32000, 32000, 4000):44                r = uhdev.event(accel=(x, None, None))45                events = uhdev.next_sync_events("Accelerometer")46                self.debug_reports(r, uhdev, events)47 48                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X) in events49                value = evdev.value[libevdev.EV_ABS.ABS_X]50                # Check against range due to small loss in precision due51                # to inverse calibration, followed by calibration by hid-sony.52                assert x - 1 <= value <= x + 153 54            for y in range(-32000, 32000, 4000):55                r = uhdev.event(accel=(None, y, None))56                events = uhdev.next_sync_events("Accelerometer")57                self.debug_reports(r, uhdev, events)58 59                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y) in events60                value = evdev.value[libevdev.EV_ABS.ABS_Y]61                assert y - 1 <= value <= y + 162 63            for z in range(-32000, 32000, 4000):64                r = uhdev.event(accel=(None, None, z))65                events = uhdev.next_sync_events("Accelerometer")66                self.debug_reports(r, uhdev, events)67 68                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Z) in events69                value = evdev.value[libevdev.EV_ABS.ABS_Z]70                assert z - 1 <= value <= z + 171 72        def test_gyroscope(self):73            uhdev = self.uhdev74            evdev = uhdev.get_evdev("Accelerometer")75 76            for rx in range(-2000000, 2000000, 200000):77                r = uhdev.event(gyro=(rx, None, None))78                events = uhdev.next_sync_events("Accelerometer")79                self.debug_reports(r, uhdev, events)80 81                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RX) in events82                value = evdev.value[libevdev.EV_ABS.ABS_RX]83                # Sensor internal value is 16-bit, but calibrated is 22-bit, so84                # 6-bit (64) difference, so allow a range of +/- 64.85                assert rx - 64 <= value <= rx + 6486 87            for ry in range(-2000000, 2000000, 200000):88                r = uhdev.event(gyro=(None, ry, None))89                events = uhdev.next_sync_events("Accelerometer")90                self.debug_reports(r, uhdev, events)91 92                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RY) in events93                value = evdev.value[libevdev.EV_ABS.ABS_RY]94                assert ry - 64 <= value <= ry + 6495 96            for rz in range(-2000000, 2000000, 200000):97                r = uhdev.event(gyro=(None, None, rz))98                events = uhdev.next_sync_events("Accelerometer")99                self.debug_reports(r, uhdev, events)100 101                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RZ) in events102                value = evdev.value[libevdev.EV_ABS.ABS_RZ]103                assert rz - 64 <= value <= rz + 64104 105        def test_battery(self):106            uhdev = self.uhdev107 108            assert uhdev.power_supply_class is not None109 110            # DS4 capacity levels are in increments of 10.111            # Battery is never below 5%.112            for i in range(5, 105, 10):113                uhdev.battery.capacity = i114                uhdev.event()115                assert uhdev.power_supply_class.capacity == i116 117            # Discharging tests only make sense for BlueTooth.118            if uhdev.bus == BusType.BLUETOOTH:119                uhdev.battery.cable_connected = False120                uhdev.battery.capacity = 45121                uhdev.event()122                assert uhdev.power_supply_class.status == "Discharging"123 124            uhdev.battery.cable_connected = True125            uhdev.battery.capacity = 5126            uhdev.event()127            assert uhdev.power_supply_class.status == "Charging"128 129            uhdev.battery.capacity = 100130            uhdev.event()131            assert uhdev.power_supply_class.status == "Charging"132 133            uhdev.battery.full = True134            uhdev.event()135            assert uhdev.power_supply_class.status == "Full"136 137        def test_mt_single_touch(self):138            """send a single touch in the first slot of the device,139            and release it."""140            uhdev = self.uhdev141            evdev = uhdev.get_evdev("Touch Pad")142 143            t0 = PSTouchPoint(1, 50, 100)144            r = uhdev.event(touch=[t0])145            events = uhdev.next_sync_events("Touch Pad")146            self.debug_reports(r, uhdev, events)147 148            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events149            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0150            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50151            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100152 153            t0.tipswitch = False154            r = uhdev.event(touch=[t0])155            events = uhdev.next_sync_events("Touch Pad")156            self.debug_reports(r, uhdev, events)157            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events158            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1159 160        def test_mt_dual_touch(self):161            """Send 2 touches in the first 2 slots.162            Make sure the kernel sees this as a dual touch.163            Release and check164 165            Note: PTP will send here BTN_DOUBLETAP emulation"""166            uhdev = self.uhdev167            evdev = uhdev.get_evdev("Touch Pad")168 169            t0 = PSTouchPoint(1, 50, 100)170            t1 = PSTouchPoint(2, 150, 200)171 172            r = uhdev.event(touch=[t0])173            events = uhdev.next_sync_events("Touch Pad")174            self.debug_reports(r, uhdev, events)175 176            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events177            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1178            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0179            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50180            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100181            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1182 183            r = uhdev.event(touch=[t0, t1])184            events = uhdev.next_sync_events("Touch Pad")185            self.debug_reports(r, uhdev, events)186            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH) not in events187            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1188            assert (189                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X, 5) not in events190            )191            assert (192                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y, 10) not in events193            )194            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0195            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50196            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100197            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1198            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150199            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200200 201            t0.tipswitch = False202            r = uhdev.event(touch=[t0, t1])203            events = uhdev.next_sync_events("Touch Pad")204            self.debug_reports(r, uhdev, events)205            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1206            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1207            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X) not in events208            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y) not in events209 210            t1.tipswitch = False211            r = uhdev.event(touch=[t1])212 213            events = uhdev.next_sync_events("Touch Pad")214            self.debug_reports(r, uhdev, events)215            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1216            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1217 218 219class TestPS3Controller(SonyBaseTest.SonyTest):220    kernel_modules = [PS3_MODULE]221 222    def create_device(self):223        controller = PS3Controller()224        controller.application_matches = application_matches225        return controller226 227    @pytest.fixture(autouse=True)228    def start_controller(self):229        # emulate a 'PS' button press to tell the kernel we are ready to accept events230        self.assert_button(17)231 232        # drain any remaining udev events233        while self.uhdev.dispatch(10):234            pass235 236        def test_led(self):237            for k, v in self.uhdev.led_classes.items():238                # the kernel might have set a LED for us239                logger.info(f"{k}: {v.brightness}")240 241                idx = int(k[-1]) - 1242                assert self.uhdev.hw_leds.get_led(idx)[0] == bool(v.brightness)243 244                v.brightness = 0245                self.uhdev.dispatch(10)246                assert self.uhdev.hw_leds.get_led(idx)[0] is False247 248                v.brightness = v.max_brightness249                self.uhdev.dispatch(10)250                assert self.uhdev.hw_leds.get_led(idx)[0]251 252 253class CalibratedPS4Controller(object):254    # DS4 reports uncalibrated sensor data. Calibration coefficients255    # can be retrieved using a feature report (0x2 USB / 0x5 BT).256    # The values below are the processed calibration values for the257    # DS4s matching the feature reports of PS4ControllerBluetooth/USB258    # as dumped from hid-sony 'ds4_get_calibration_data'.259    #260    # Note we duplicate those values here in case the kernel changes them261    # so we can have tests passing even if hid-tools doesn't have the262    # correct values.263    accelerometer_calibration_data = {264        "x": {"bias": -73, "numer": 16384, "denom": 16472},265        "y": {"bias": -352, "numer": 16384, "denom": 16344},266        "z": {"bias": 81, "numer": 16384, "denom": 16319},267    }268    gyroscope_calibration_data = {269        "x": {"bias": 0, "numer": 1105920, "denom": 17827},270        "y": {"bias": 0, "numer": 1105920, "denom": 17777},271        "z": {"bias": 0, "numer": 1105920, "denom": 17748},272    }273 274 275class CalibratedPS4ControllerBluetooth(CalibratedPS4Controller, PS4ControllerBluetooth):276    pass277 278 279class TestPS4ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):280    def create_device(self):281        controller = CalibratedPS4ControllerBluetooth()282        controller.application_matches = application_matches283        return controller284 285 286class CalibratedPS4ControllerUSB(CalibratedPS4Controller, PS4ControllerUSB):287    pass288 289 290class TestPS4ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):291    def create_device(self):292        controller = CalibratedPS4ControllerUSB()293        controller.application_matches = application_matches294        return controller295 296 297class CalibratedPS5Controller(object):298    # DualSense reports uncalibrated sensor data. Calibration coefficients299    # can be retrieved using feature report 0x09.300    # The values below are the processed calibration values for the301    # DualSene matching the feature reports of PS5ControllerBluetooth/USB302    # as dumped from hid-playstation 'dualsense_get_calibration_data'.303    #304    # Note we duplicate those values here in case the kernel changes them305    # so we can have tests passing even if hid-tools doesn't have the306    # correct values.307    accelerometer_calibration_data = {308        "x": {"bias": 0, "numer": 16384, "denom": 16374},309        "y": {"bias": -114, "numer": 16384, "denom": 16362},310        "z": {"bias": 2, "numer": 16384, "denom": 16395},311    }312    gyroscope_calibration_data = {313        "x": {"bias": 0, "numer": 1105920, "denom": 17727},314        "y": {"bias": 0, "numer": 1105920, "denom": 17728},315        "z": {"bias": 0, "numer": 1105920, "denom": 17769},316    }317 318 319class CalibratedPS5ControllerBluetooth(CalibratedPS5Controller, PS5ControllerBluetooth):320    pass321 322 323class TestPS5ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):324    kernel_modules = [PS5_MODULE]325 326    def create_device(self):327        controller = CalibratedPS5ControllerBluetooth()328        controller.application_matches = application_matches329        return controller330 331 332class CalibratedPS5ControllerUSB(CalibratedPS5Controller, PS5ControllerUSB):333    pass334 335 336class TestPS5ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):337    kernel_modules = [PS5_MODULE]338 339    def create_device(self):340        controller = CalibratedPS5ControllerUSB()341        controller.application_matches = application_matches342        return controller343