From: Mason Camara <ping@masoncamara.com>
To: jikos@kernel.org, bentiss@kernel.org, shuah@kernel.org
Cc: linux-input@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org, wh6cyy@gmail.com,
Mason Camara <ping@masoncamara.com>
Subject: [PATCH v2] selftests/hid: test battery queries with nonzero field offsets
Date: Sun, 30 Aug 2026 12:31:09 -0600 [thread overview]
Message-ID: <20260830183109.9441-1-ping@masoncamara.com> (raw)
Commit d07644524b65 ("HID: input: read battery capacity from its actual
report offset") fixed synchronous battery queries for reports that place
the capacity byte after status fields.
Add a UHID mouse with the Magic Mouse 2 report layout and answer GET_REPORT
with 90 04 5f. Read capacity before sending an input report so the test
exercises the synchronous query path. Without the fix, it reads the status
byte as 4%; with the fix, it reads capacity as 95%.
Enable CONFIG_HID_BATTERY_STRENGTH in the HID selftest configuration.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221263
Assisted-by: LLM
Signed-off-by: Mason Camara <ping@masoncamara.com>
---
Changes in v2:
- Drop driver fix, superseded by d07644524b65.
- Rebase the regression test onto the current HID for-next branch.
- Amend commit message and tool-assistance trailer.
v1: https://lore.kernel.org/linux-input/20260712044702.893825-1-ping@masoncamara.com/
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 1758b055f..da52335b8 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 eb4e15a0e..141c1f069 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()
base-commit: 931aaa59d1826f43b0bb3f07e21233f6faf4540a
--
2.39.5 (Apple Git-154)
reply other threads:[~2026-08-30 18:31 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260830183109.9441-1-ping@masoncamara.com \
--to=ping@masoncamara.com \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=shuah@kernel.org \
--cc=wh6cyy@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox