Skip to content

Commit 4675a12

Browse files
and-fedgregkh
authored andcommitted
HID: magicmouse: fix battery reporting for Bluetooth Magic Trackpad USB-C
[ Upstream commit a1556b4 ] The Apple Magic Trackpad 2 (USB-C) reports a wildly wrong battery capacity over Bluetooth, for example a constant 4% for a pack that is actually at 74%. The device's battery input report (0x90) is laid out as [report-id][status][charge]. hid-input's synchronous capacity query, hidinput_query_battery_capacity(), assumes the common [report-id][capacity] layout and returns buf[1], which for this device is the status byte rather than the charge (buf[2]). magicmouse_fetch_battery(), which requests the battery report through hid_hw_request() so the reply is decoded via the report descriptor at the correct field offset, is gated to the USB models and never runs over Bluetooth. The device does not push battery reports on its own either, except a single one at connect time, which is delivered while probe holds driver_input_lock and is silently dropped. All userspace reads therefore go through the misparsing query, and the device is stuck reporting its status byte as the capacity. Enabling the fetch for Bluetooth is not sufficient on its own: user space reacts to the power_supply registration immediately, so a query is typically already in flight when the fetch reply is parsed. hidinput_get_battery_property() stores the query result and marks the battery as queried without rechecking whether a report arrived while it was waiting, clobbering the just-reported correct value with the misparsed one. Fix this by adding HID_BATTERY_QUIRK_AVOID_QUERY for the Bluetooth Magic Trackpad USB-C so the misparsing query path is never used, and by fetching the battery at the end of probe for this device. hidp has no asynchronous request() callback, so the fetch is serviced synchronously via __hid_request() while probe still holds driver_input_lock; call hid_device_io_start() first so the reply is processed instead of being discarded. Tested with a Magic Trackpad USB-C (004c:0324) over Bluetooth on 6.18.37: the reported capacity now matches the device (verified against a raw GET_REPORT of report 0x90) and updates on reconnect. Fixes: 87a2f10 ("HID: magicmouse: Apple Magic Trackpad 2 USB-C driver support") Cc: stable@vger.kernel.org Signed-off-by: Andrei Fed <andfed.net@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com> [ Kept only the new quirk entry from the conflicting hunk, dropping the adjacent Magic Trackpad 1 entry absent from this tree. ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 04e5135 commit 4675a12

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

drivers/hid/hid-input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
358358
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
359359
USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
360360
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
361+
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
362+
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC),
363+
HID_BATTERY_QUIRK_AVOID_QUERY },
361364
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
362365
USB_DEVICE_ID_ELECOM_BM084),
363366
HID_BATTERY_QUIRK_IGNORE },

drivers/hid/hid-magicmouse.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,12 @@ static bool is_usb_magictrackpad2(__u32 vendor, __u32 product)
808808
product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC;
809809
}
810810

811+
static bool is_bt_magictrackpad2(__u32 vendor, __u32 product)
812+
{
813+
return vendor == BT_VENDOR_ID_APPLE &&
814+
product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC;
815+
}
816+
811817
static int magicmouse_fetch_battery(struct hid_device *hdev)
812818
{
813819
#ifdef CONFIG_HID_BATTERY_STRENGTH
@@ -816,7 +822,8 @@ static int magicmouse_fetch_battery(struct hid_device *hdev)
816822

817823
if (!hdev->battery ||
818824
(!is_usb_magicmouse2(hdev->vendor, hdev->product) &&
819-
!is_usb_magictrackpad2(hdev->vendor, hdev->product)))
825+
!is_usb_magictrackpad2(hdev->vendor, hdev->product) &&
826+
!is_bt_magictrackpad2(hdev->vendor, hdev->product)))
820827
return -1;
821828

822829
report_enum = &hdev->report_enum[hdev->battery_report_type];
@@ -952,6 +959,16 @@ static int magicmouse_probe(struct hid_device *hdev,
952959
schedule_delayed_work(&msc->work, msecs_to_jiffies(500));
953960
}
954961

962+
/*
963+
* Query the Bluetooth Magic Trackpad USB-C battery as done for USB.
964+
* Start io first: probe holds driver_input_lock and the synchronous
965+
* GET_REPORT reply would otherwise be dropped.
966+
*/
967+
if (is_bt_magictrackpad2(id->vendor, id->product)) {
968+
hid_device_io_start(hdev);
969+
magicmouse_fetch_battery(hdev);
970+
}
971+
955972
return 0;
956973
err_stop_hw:
957974
if (is_usb_magicmouse2(id->vendor, id->product) ||

0 commit comments

Comments
 (0)