From nobody Sat Jul 25 23:03:58 2026 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C0E222E3E9 for ; Sun, 12 Jul 2026 04:47:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783831657; cv=none; b=AEhy77hsdLJd3YlKpshAey54NNiil42P+HEcs+5CEahNFisPIKHmy1UlYMlNev1h+Q66tXEy5KhmWbK40cakeVW8qVam3FnHFCgumwDqaY+LAgA7eFgryUSNQ4fEhRP3Xa2ua7ORNkqQEaRHHvxl9Cqe066VF4jJZHV2+4IH3lU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783831657; c=relaxed/simple; bh=zFIrTtOqjdO3+IkDV652CpGMyKnVbAlNiv0Ym4owJaI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IusetnYJu2UcjgEPfwLZ3bcD+zjRRlDA/3syxBA/4R1zPNvtw3Q9cnhgKmbjoHAqmlwL2lYQR9USyekbV3FELx+AC4DF0Zmotz8n7a0unuuGkBTAguxyqn31XRWQNnNBqE4uUKNbhTTUI9GAl23GQPivIwynmUEtiwVyATxPU9o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=masoncamara.com; spf=pass smtp.mailfrom=masoncamara.com; dkim=pass (2048-bit key) header.d=masoncamara-com.20251104.gappssmtp.com header.i=@masoncamara-com.20251104.gappssmtp.com header.b=vWkP3IfZ; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=masoncamara.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=masoncamara.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=masoncamara-com.20251104.gappssmtp.com header.i=@masoncamara-com.20251104.gappssmtp.com header.b="vWkP3IfZ" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-8485b358552so2297036b3a.2 for ; Sat, 11 Jul 2026 21:47:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=masoncamara-com.20251104.gappssmtp.com; s=20251104; t=1783831655; x=1784436455; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lNkBXOfLF0O7asfBZN+v8AnyzGHcufqmHpC8s/f24kg=; b=vWkP3IfZCTvELT1NYtdL1ONnoOQzdQ2TZDXWjK7WH+Q+cvrJAWKiKLws/5mtRKIOSy FCSniVjI0UH0xIliugNSRtOhUHDXrvf8jbAFKZqIP7SIZIQmXOBEqvuDxcZbYFJ06c7F vcGMQcV8zIOsU+aYXaA3JTdarqR82o7+tyijOpW0//5AtKwKecE+Qv558ARSbQhI+/0I EL+FNCv5jutLnLiGuTcdqHIviY6VTe//Sb9OLNC8K0gsnHNWWeV1h8DGb4Vy+apmiTif LfM8dkXk0cQ/7hgjAUtzEzHVfWRKnCpWA2voCXFny6ONziuMX5lZxqvOK5v9owR58G7L p/Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783831655; x=1784436455; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=lNkBXOfLF0O7asfBZN+v8AnyzGHcufqmHpC8s/f24kg=; b=QEFxhrmvbhIbDQc8F7CmRC2oJd5t0zMkO7pKSRTVUDBgz4aANtDKaPtyYRQ6M20zNW FU9Hvqv2lMuZskeF6XaHh+JgkuzFhG0Q/6Mq2SPJUJ5Lwc5a6kofr3whVm7nhfri5F2O 64hn22T+y5peVf2+cuqF4r1W9c3FIWHOP5wq0g0YCEf7XoG/dDdL4q4K3GvF2i7e2Ddg d5ovsECLV9fK/80pQE53/kSDDpQtCZCnx7gsbjFH5TQQ1L/qx2WolApyvPlU8eN0DKfZ 5NCdQJcKKyjMt01N4H3rEGrsiJFCebd0rhZ+4MpgqhX5tDrpyd+Or5JjYdmzSc4GZExH bYLw== X-Forwarded-Encrypted: i=1; AHgh+RqLOYKaCW0oO2sbAGs/hGWNEeQoCN3G3Q9YTLY34I77MEgm5WQWaxbTTmn3sbMuPPRJQ6CRefhk/oimvP8=@vger.kernel.org X-Gm-Message-State: AOJu0YytlzEUo7TbctP9JMBSKGwcG30qQ1lGSrHXntOFW8OVGUjrPMbn wv8jvKRKQGlxIiIm+QxQaIqPiIEj7p+1h12dVTp0Jt4I4bRI3yBIkv3GJ6zWWiePHE3k X-Gm-Gg: AfdE7clqg+6FMNuR9Yho7YSZxnrNqPpoCwYk1ETI2RHDRxHz92/MsaZmU1Cun9Kn2yd y3nFC9B7hr17wXXsq1Fh4GHBWD5K2pDDwXWoxuJQ0HNNR10PuY8ZRL5jgQxT6GZSeY0aGJ7dcuC RnWrjzpdu3QBV9UtXQtUQMqEzcRbxHRCI9BuBn1cuOMnpa2DzFZua+TbSfL+ck4qCvg005cfbIx BCfmRIXrXDI7jAYUPJY1RajQmqC21rRPqR+whh7/4YzhnhTx/nAXwswTHQq+osFT7TMWAGaL/2a qfyeahqsB3OJM1PAhSg3He8SxjCKErDax1Hk24EHe6wVRYGpd400pakuZhHouL8Bmf2S5f3lX5F wJdVHVhMEyy2q7DX3AXkrAydyxqlXd8vKthMwcyMDNUlcz75CQoFBicX0X/kNWi3U3dDSLCJX3u 7A3ENK0G/fozmxqVkYjiuVX1ZZVoXrTIejkNcfvA== X-Received: by 2002:a05:6a20:9185:b0:3b4:b2d7:c146 with SMTP id adf61e73a8af0-3c1108b5a56mr5015548637.21.1783831655501; Sat, 11 Jul 2026 21:47:35 -0700 (PDT) Received: from nobara ([69.26.129.115]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3118ee6091dsm59384338eec.14.2026.07.11.21.47.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 21:47:35 -0700 (PDT) From: Mason Camara To: Jiri Kosina , Benjamin Tissoires Cc: Shuah Khan , John Chen , linux-input@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] HID: input: honor report field offsets in battery queries Date: Sat, 11 Jul 2026 22:47:01 -0600 Message-ID: <20260712044702.893825-2-ping@masoncamara.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712044702.893825-1-ping@masoncamara.com> References: <20260712044702.893825-1-ping@masoncamara.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" hidinput_query_battery_capacity() always reads buf[1] from a GET_REPORT reply. This assumes capacity usage starts at bit 0 of the report payload and that capacity occupies the first byte. The Magic Mouse 2 puts a status byte before AbsoluteStateOfCharge in input report 0x90. Its GET_REPORT response is: 90 04 5f Here 0x04 is the status byte and 0x5f is the capacity. Reading buf[1] reports 4% in sysfs. This query runs when userspace reads capacity before an input report updates the battery cache. The event path already extracts the usage from the descriptor, so moving the mouse before the sysfs read can hide the bug. Record the report containing the capacity field, bit offset, and size when setting up the battery. Allocate a buffer large enough for the complete report, skip the report ID byte, and extract the value at the recorded bit offset. Reject replies that do not contain the complete field. Fixes: 9de07a4e8d4c ("HID: input: map battery capacity (00850065)") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=3D221263 Assisted-by: Codex:GPT-5 Signed-off-by: Mason Camara --- drivers/hid/hid-input.c | 39 +++++++++++++++++++++++++++++---------- include/linux/hid.h | 6 ++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 3487600cadb4..01ce9e176299 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -431,18 +431,28 @@ static int hidinput_scale_battery_capacity(struct hid= _battery *bat, =20 static int hidinput_query_battery_capacity(struct hid_battery *bat) { + u8 *buf __free(kfree) =3D NULL; + unsigned int field_end; + unsigned int report_len; + u32 value; int ret; =20 - u8 *buf __free(kfree) =3D kmalloc(4, GFP_KERNEL); + report_len =3D hid_report_len(bat->report) + !bat->report->id; + buf =3D hid_alloc_report_buf(bat->report, GFP_KERNEL); if (!buf) return -ENOMEM; =20 - ret =3D hid_hw_raw_request(bat->dev, bat->report_id, buf, 4, + ret =3D hid_hw_raw_request(bat->dev, bat->report_id, buf, report_len, bat->report_type, HID_REQ_GET_REPORT); - if (ret < 2) + field_end =3D DIV_ROUND_UP(bat->report_offset + bat->report_size, 8) + + 1; + if (ret < 0 || (unsigned int)ret < field_end) return -ENODATA; =20 - return hidinput_scale_battery_capacity(bat, buf[1]); + value =3D hid_field_extract(bat->dev, buf + 1, bat->report_offset, + bat->report_size); + + return hidinput_scale_battery_capacity(bat, value); } =20 static int hidinput_get_battery_property(struct power_supply *psy, @@ -529,7 +539,8 @@ static void hidinput_cleanup_battery(void *res) } =20 static int hidinput_setup_battery(struct hid_device *dev, unsigned report_= type, - struct hid_field *field, bool is_percentage) + struct hid_field *field, unsigned int usage_index, + bool is_percentage) { struct hid_battery *bat; struct power_supply_desc *psy_desc; @@ -593,6 +604,10 @@ static int hidinput_setup_battery(struct hid_device *d= ev, unsigned report_type, bat->max =3D max; bat->report_type =3D report_type; bat->report_id =3D field->report->id; + bat->report =3D field->report; + bat->report_offset =3D field->report_offset + + usage_index * field->report_size; + bat->report_size =3D field->report_size; bat->charge_status =3D POWER_SUPPLY_STATUS_DISCHARGING; bat->status =3D HID_BATTERY_UNKNOWN; =20 @@ -687,7 +702,8 @@ static void hidinput_update_battery(struct hid_device *= dev, int report_id, } #else /* !CONFIG_HID_BATTERY_STRENGTH */ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_= type, - struct hid_field *field, bool is_percentage) + struct hid_field *field, unsigned int usage_index, + bool is_percentage) { return 0; } @@ -1035,7 +1051,8 @@ static void hidinput_configure_usage(struct hid_input= *hidinput, struct hid_fiel break; =20 case 0x3b: /* Battery Strength */ - hidinput_setup_battery(device, HID_INPUT_REPORT, field, false); + hidinput_setup_battery(device, HID_INPUT_REPORT, field, + usage_index, false); usage->type =3D EV_PWR; return; =20 @@ -1313,7 +1330,8 @@ static void hidinput_configure_usage(struct hid_input= *hidinput, struct hid_fiel case HID_UP_GENDEVCTRLS: switch (usage->hid) { case HID_DC_BATTERYSTRENGTH: - hidinput_setup_battery(device, HID_INPUT_REPORT, field, false); + hidinput_setup_battery(device, HID_INPUT_REPORT, field, + usage_index, false); usage->type =3D EV_PWR; return; } @@ -1322,7 +1340,8 @@ static void hidinput_configure_usage(struct hid_input= *hidinput, struct hid_fiel case HID_UP_BATTERY: switch (usage->hid) { case HID_BAT_ABSOLUTESTATEOFCHARGE: - hidinput_setup_battery(device, HID_INPUT_REPORT, field, true); + hidinput_setup_battery(device, HID_INPUT_REPORT, field, + usage_index, true); usage->type =3D EV_PWR; return; case HID_BAT_CHARGING: @@ -2040,7 +2059,7 @@ static void report_features(struct hid_device *hid) /* Verify if Battery Strength feature is available */ if (usage->hid =3D=3D HID_DC_BATTERYSTRENGTH) hidinput_setup_battery(hid, HID_FEATURE_REPORT, - rep->field[i], false); + rep->field[i], j, false); =20 if (drv->feature_mapping) drv->feature_mapping(hid, rep->field[i], usage); diff --git a/include/linux/hid.h b/include/linux/hid.h index b240baa95ab5..396de1080fdc 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -642,6 +642,9 @@ enum hid_battery_status { * @max: maximum battery value from HID descriptor * @report_type: HID report type (input/feature) * @report_id: HID report ID for this battery + * @report: HID report containing the capacity field + * @report_offset: bit offset of the capacity field in the report + * @report_size: size of the capacity field in bits * @charge_status: current charging status * @status: battery reporting status * @capacity: current battery capacity (0-100) @@ -657,6 +660,9 @@ struct hid_battery { __s32 max; __s32 report_type; __s32 report_id; + struct hid_report *report; + __u32 report_offset; + __u32 report_size; __s32 charge_status; enum hid_battery_status status; __s32 capacity; --=20 2.55.0 From nobody Sat Jul 25 23:03:58 2026 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85EB5322A for ; Sun, 12 Jul 2026 04:47:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783831659; cv=none; b=aTrhTFSv5UsEMOXJ+R9TGc6xXic7ny5JGw6cXHHbsNGE/Y9s3nJ0Ivf+6NGxdepdjIG6yCqaxmFz0C69aHAGjed6p8EBwaPtSJso8AFz9IU3nrLQ9vf5IWt1NSUBCLGCJTLueuL6vPZzT54tf9eSkYry5WqcsFTh2qdt7IBt7c0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783831659; c=relaxed/simple; bh=gVoVhvIy7NIUB1l7ESMbLeoAjSFDx4L17+1xD7r2jjQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eXUW0xYxluBWUrIqJN7LjoEKeuNjFGfcAmKZqInI8ntBpDE1l0thbl6YDtBSMR53EoOEW95giMrSwU0v5s9ZYcUDcmvMMP6s4VywLlGB9HSC9wxvCKrC6w0mFcQ5Lf8fn4b5d9CezTI5d0gmFyLmjYTkFik62DldSRB5bVwCQ9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=masoncamara.com; spf=pass smtp.mailfrom=masoncamara.com; dkim=pass (2048-bit key) header.d=masoncamara-com.20251104.gappssmtp.com header.i=@masoncamara-com.20251104.gappssmtp.com header.b=LLIBYAYf; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=masoncamara.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=masoncamara.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=masoncamara-com.20251104.gappssmtp.com header.i=@masoncamara-com.20251104.gappssmtp.com header.b="LLIBYAYf" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-2cc7e86e7aeso19448025ad.2 for ; Sat, 11 Jul 2026 21:47:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=masoncamara-com.20251104.gappssmtp.com; s=20251104; t=1783831658; x=1784436458; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9oLcv0qVSMsTkgn/ZfSsFOjEguUBCGI4Az7FCb7eMIk=; b=LLIBYAYfk78rs3UXIhrb5OrBnFn25HUkslivUHRccIrf7WckE6ge1IMM6tJ4tqtz6F KVLj53b/Aw3BGiYVYprW2x3UV1/uAqp60Ox2+rdsvB/pNpsRYHb5hv7h2xw7f3X9t5QB 2d9luZy9S51vR5Sh1q86KKqehT55/9vh2XypTj5XMUZI/ffmVm9dHiCVkEAUtvVCivAe RoTLILT0ET4dydBsOabvoCVr3iMqywVGwCnDq2pQLTpb9IapOgXupA8ssBVUihcQEGdC xX+z4dBLHCbSv6/UTkhn1+VRqCNKUWKf5JBmlLUoxKRkV8V5NfrQp51CF9SaQDyLwz+x iFmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783831658; x=1784436458; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=9oLcv0qVSMsTkgn/ZfSsFOjEguUBCGI4Az7FCb7eMIk=; b=f6EPTJ/Xml0U5mOCir0ipGdKy8ZpoteWyOtn3Pu5Sr9saq5iYwsDKrigptATQwgZl9 m5HXSWxbzD6fxZ9n5nVec4QXrJHcDBlSv2I+akq2uWsJRnlqa0r8AwaYd46IgJr+gb3I WQ5hM2Ol/rfULO0dTbRoQslkPrp7Co4yxqQn3Ac3MitqYa+vWwKFbw8CVG31Kw1i8aB8 7oLiBVRQIrbl0XPw7jIc3UAr6nN+VxP97ozpEOdCpcb68z5xm7lg4wzH7lg093s3J4Kk VgR7oGSDGyclt1ONrTdQ42VQvSE7WYYYviSYFCUh7IhDfKVqXUfkBzcRynU775PUlqvI 92tA== X-Forwarded-Encrypted: i=1; AHgh+RpihWe2L0amBR0TrE/NJiUhGH23AYH5TfHf5U+K6I7UO7uHJYoxWb/Rzbli62Bp9GDruh+N/esj9qcuxtY=@vger.kernel.org X-Gm-Message-State: AOJu0YwMU61prDpShNNFkrAjtKrZCLIGwNt6kxNSfByMBHXmVq8nGYfy sp6iU1RdfVXyUiO2r70GfXPEOCFSpq1CqBurX6gBzwYY+Mv8R8f95bEeTMN/8wTxFVki X-Gm-Gg: AfdE7cnX5OTF1qoKOqynnbdo5ToRW/AFxGHPrGi9gGSCgO0JkUO/Vxw/XJWqzYpCk1x hgv/GVENhQMBl+C5L16aNfbBmiokA/Qh0JLawP3TQECLq/ZtHr1HLHJa1+tQ7fTosowASGtSDJc Hdky/qTP/jnss7+iq//K43aSsdFmmeXngclMrKyE66yFuvWsTVs8w6V/uzk7yjZY2G06igdB3f/ Hh6sxQPX3F/GYhkGaZr9b2kO+1I7kxOv6W2cBMRiBUbj2hzMlRGnR4zvRqo81abxZa8Xv51V+H7 qxWOTSjb7Wb7TW+dcgGgd4JkiavIevnHKErbBgCcb12DYlFhwc+wb8/wUuqrGMnDafJYrnhjy0i 1N0C6P0dMSLEdD86YRBNOnFyFqCSFjtz802Pgn1UUOdKjw5BqC3nod8FCXCzZ/R8h+Iz951GB+X RfUxlqheHGWp3JE2EfdHP2cXX/8kE2Uhv+R+AsRg== X-Received: by 2002:a05:6a21:6e91:b0:39f:2dd0:65d5 with SMTP id adf61e73a8af0-3c110b263e8mr4830981637.39.1783831657914; Sat, 11 Jul 2026 21:47:37 -0700 (PDT) Received: from nobara ([69.26.129.115]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3118ee6091dsm59384338eec.14.2026.07.11.21.47.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 21:47:37 -0700 (PDT) From: Mason Camara To: Jiri Kosina , Benjamin Tissoires Cc: Shuah Khan , John Chen , linux-input@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] selftests/hid: test battery queries with nonzero field offsets Date: Sat, 11 Jul 2026 22:47:02 -0600 Message-ID: <20260712044702.893825-3-ping@masoncamara.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712044702.893825-1-ping@masoncamara.com> References: <20260712044702.893825-1-ping@masoncamara.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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/h= id/config index 1758b055f295..da52335b865a 100644 --- a/tools/testing/selftests/hid/config +++ b/tools/testing/selftests/hid/config @@ -16,6 +16,7 @@ CONFIG_FTRACE_SYSCALLS=3Dy CONFIG_FUNCTION_TRACER=3Dy CONFIG_HIDRAW=3Dy CONFIG_HID=3Dy +CONFIG_HID_BATTERY_STRENGTH=3Dy CONFIG_HID_BPF=3Dy CONFIG_INPUT_EVDEV=3Dy CONFIG_UHID=3Dy diff --git a/tools/testing/selftests/hid/tests/test_mouse.py b/tools/testin= g/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 =20 logger =3D logging.getLogger("hidtools.test.mouse") @@ -598,6 +599,35 @@ class ResolutionMultiplierHWheelMouse(TwoWheelMouse): return 0 =20 =20 +class BatteryOffsetMouse(BaseMouse): + report_descriptor =3D [ + # 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=3Dreport_descriptor, name=3DNone, input_info= =3DNone): + super().__init__(rdesc, name, input_info) + + def get_report(self, req, rnum, rtype): + if rtype !=3D self.UHID_INPUT_REPORT or rnum !=3D 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): =20 def assertName(self, uhdev): pass + + +class TestBatteryOffsetMouse(base.BaseTestCase.TestUhid): + def create_device(self): + return BatteryOffsetMouse() + + def test_queried_battery_field_offset(self): + uhdev =3D self.uhdev + power_supply =3D uhdev.power_supply_class + assert power_supply is not None + + done =3D False + + def dispatch(): + while not done: + uhdev.dispatch(1) + + thread =3D threading.Thread(target=3Ddispatch) + thread.start() + try: + assert power_supply.capacity =3D=3D 95 + finally: + done =3D True + thread.join() --=20 2.55.0