Skip to content

Commit f771656

Browse files
author
Jiri Kosina
committed
Merge branch 'for-5.17/magicmouse' into for-linus
- proper batter reporting for hid-magicmouse USB-connected devices (José Expósito)
2 parents 50ae0cf + 33812fc commit f771656

1 file changed

Lines changed: 89 additions & 6 deletions

File tree

drivers/hid/hid-magicmouse.c

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
5959
#define MOUSE_REPORT_ID 0x29
6060
#define MOUSE2_REPORT_ID 0x12
6161
#define DOUBLE_REPORT_ID 0xf7
62+
#define USB_BATTERY_TIMEOUT_MS 60000
63+
6264
/* These definitions are not precise, but they're close enough. (Bits
6365
* 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
6466
* to be some kind of bit mask -- 0x20 may be a near-field reading,
@@ -142,6 +144,7 @@ struct magicmouse_sc {
142144

143145
struct hid_device *hdev;
144146
struct delayed_work work;
147+
struct timer_list battery_timer;
145148
};
146149

147150
static int magicmouse_firm_touch(struct magicmouse_sc *msc)
@@ -752,18 +755,51 @@ static void magicmouse_enable_mt_work(struct work_struct *work)
752755
hid_err(msc->hdev, "unable to request touch data (%d)\n", ret);
753756
}
754757

758+
static int magicmouse_fetch_battery(struct hid_device *hdev)
759+
{
760+
#ifdef CONFIG_HID_BATTERY_STRENGTH
761+
struct hid_report_enum *report_enum;
762+
struct hid_report *report;
763+
764+
if (!hdev->battery || hdev->vendor != USB_VENDOR_ID_APPLE ||
765+
(hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
766+
hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2))
767+
return -1;
768+
769+
report_enum = &hdev->report_enum[hdev->battery_report_type];
770+
report = report_enum->report_id_hash[hdev->battery_report_id];
771+
772+
if (!report || report->maxfield < 1)
773+
return -1;
774+
775+
if (hdev->battery_capacity == hdev->battery_max)
776+
return -1;
777+
778+
hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
779+
return 0;
780+
#else
781+
return -1;
782+
#endif
783+
}
784+
785+
static void magicmouse_battery_timer_tick(struct timer_list *t)
786+
{
787+
struct magicmouse_sc *msc = from_timer(msc, t, battery_timer);
788+
struct hid_device *hdev = msc->hdev;
789+
790+
if (magicmouse_fetch_battery(hdev) == 0) {
791+
mod_timer(&msc->battery_timer,
792+
jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS));
793+
}
794+
}
795+
755796
static int magicmouse_probe(struct hid_device *hdev,
756797
const struct hid_device_id *id)
757798
{
758799
struct magicmouse_sc *msc;
759800
struct hid_report *report;
760801
int ret;
761802

762-
if (id->vendor == USB_VENDOR_ID_APPLE &&
763-
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
764-
hdev->type != HID_TYPE_USBMOUSE)
765-
return -ENODEV;
766-
767803
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
768804
if (msc == NULL) {
769805
hid_err(hdev, "can't alloc magicmouse descriptor\n");
@@ -789,6 +825,16 @@ static int magicmouse_probe(struct hid_device *hdev,
789825
return ret;
790826
}
791827

828+
timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0);
829+
mod_timer(&msc->battery_timer,
830+
jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS));
831+
magicmouse_fetch_battery(hdev);
832+
833+
if (id->vendor == USB_VENDOR_ID_APPLE &&
834+
(id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
835+
(id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && hdev->type != HID_TYPE_USBMOUSE)))
836+
return 0;
837+
792838
if (!msc->input) {
793839
hid_err(hdev, "magicmouse input not registered\n");
794840
ret = -ENOMEM;
@@ -841,6 +887,7 @@ static int magicmouse_probe(struct hid_device *hdev,
841887

842888
return 0;
843889
err_stop_hw:
890+
del_timer_sync(&msc->battery_timer);
844891
hid_hw_stop(hdev);
845892
return ret;
846893
}
@@ -849,17 +896,52 @@ static void magicmouse_remove(struct hid_device *hdev)
849896
{
850897
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
851898

852-
if (msc)
899+
if (msc) {
853900
cancel_delayed_work_sync(&msc->work);
901+
del_timer_sync(&msc->battery_timer);
902+
}
854903

855904
hid_hw_stop(hdev);
856905
}
857906

907+
static __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
908+
unsigned int *rsize)
909+
{
910+
/*
911+
* Change the usage from:
912+
* 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0
913+
* 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3
914+
* To:
915+
* 0x05, 0x01, // Usage Page (Generic Desktop) 0
916+
* 0x09, 0x02, // Usage (Mouse) 2
917+
*/
918+
if (hdev->vendor == USB_VENDOR_ID_APPLE &&
919+
(hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
920+
hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) &&
921+
*rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
922+
hid_info(hdev,
923+
"fixing up magicmouse battery report descriptor\n");
924+
*rsize = *rsize - 1;
925+
rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
926+
if (!rdesc)
927+
return NULL;
928+
929+
rdesc[0] = 0x05;
930+
rdesc[1] = 0x01;
931+
rdesc[2] = 0x09;
932+
rdesc[3] = 0x02;
933+
}
934+
935+
return rdesc;
936+
}
937+
858938
static const struct hid_device_id magic_mice[] = {
859939
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
860940
USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
861941
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
862942
USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
943+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
944+
USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
863945
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
864946
USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 },
865947
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
@@ -875,6 +957,7 @@ static struct hid_driver magicmouse_driver = {
875957
.id_table = magic_mice,
876958
.probe = magicmouse_probe,
877959
.remove = magicmouse_remove,
960+
.report_fixup = magicmouse_report_fixup,
878961
.raw_event = magicmouse_raw_event,
879962
.event = magicmouse_event,
880963
.input_mapping = magicmouse_input_mapping,

0 commit comments

Comments
 (0)