Add a UHID mouse whose input report 0x90 contains a status byte before the capacity field. Answer GET_REPORT with 90 04 5f and read the power supply capacity before sending any input report.
On an unpatched kernel, the capacity read returns the status byte (4) instead of the capacity value (95), so the test fails. Enable CONFIG_HID_BATTERY_STRENGTH in the HID selftest configuration. Assisted-by: Codex:GPT-5 Signed-off-by: Mason Camara <[email protected]> --- tools/testing/selftests/hid/config | 1 + .../testing/selftests/hid/tests/test_mouse.py | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/tools/testing/selftests/hid/config b/tools/testing/selftests/hid/config index 1758b055f295..da52335b865a 100644 --- a/tools/testing/selftests/hid/config +++ b/tools/testing/selftests/hid/config @@ -16,6 +16,7 @@ CONFIG_FTRACE_SYSCALLS=y CONFIG_FUNCTION_TRACER=y CONFIG_HIDRAW=y CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HID_BPF=y CONFIG_INPUT_EVDEV=y CONFIG_UHID=y diff --git a/tools/testing/selftests/hid/tests/test_mouse.py b/tools/testing/selftests/hid/tests/test_mouse.py index eb4e15a0e53b..141c1f06905b 100644 --- a/tools/testing/selftests/hid/tests/test_mouse.py +++ b/tools/testing/selftests/hid/tests/test_mouse.py @@ -11,6 +11,7 @@ import hidtools.hid from hidtools.util import BusType import libevdev import logging +import threading import pytest logger = logging.getLogger("hidtools.test.mouse") @@ -598,6 +599,35 @@ class ResolutionMultiplierHWheelMouse(TwoWheelMouse): return 0 +class BatteryOffsetMouse(BaseMouse): + report_descriptor = [ + # Mouse report + 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x85, 0x12, + 0x05, 0x09, 0x19, 0x01, 0x29, 0x02, 0x15, 0x00, + 0x25, 0x01, 0x95, 0x02, 0x75, 0x01, 0x81, 0x02, + 0x95, 0x01, 0x75, 0x06, 0x81, 0x01, 0x05, 0x01, + 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, + 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, + 0x81, 0x06, 0xc0, 0xc0, + # Battery report: one status byte followed by capacity + 0x06, 0x00, 0xff, 0x09, 0x14, 0xa1, 0x01, 0x85, + 0x90, 0x05, 0x84, 0x75, 0x01, 0x95, 0x03, 0x15, + 0x00, 0x25, 0x01, 0x09, 0x61, 0x05, 0x85, 0x09, + 0x44, 0x09, 0x46, 0x81, 0x02, 0x95, 0x05, 0x81, + 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00, 0x26, + 0xff, 0x00, 0x09, 0x65, 0x81, 0x02, 0xc0, + ] + + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): + super().__init__(rdesc, name, input_info) + + def get_report(self, req, rnum, rtype): + if rtype != self.UHID_INPUT_REPORT or rnum != 0x90: + return (1, []) + + return (0, [0x90, 0x04, 0x5F]) + + class BaseTest: class TestMouse(base.BaseTestCase.TestUhid): def test_buttons(self): @@ -1045,3 +1075,27 @@ class TestBadReportDescriptorMouse(base.BaseTestCase.TestUhid): def assertName(self, uhdev): pass + + +class TestBatteryOffsetMouse(base.BaseTestCase.TestUhid): + def create_device(self): + return BatteryOffsetMouse() + + def test_queried_battery_field_offset(self): + uhdev = self.uhdev + power_supply = uhdev.power_supply_class + assert power_supply is not None + + done = False + + def dispatch(): + while not done: + uhdev.dispatch(1) + + thread = threading.Thread(target=dispatch) + thread.start() + try: + assert power_supply.capacity == 95 + finally: + done = True + thread.join() -- 2.55.0

