@@ -57,6 +57,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
5757#define MOUSE_REPORT_ID 0x29
5858#define MOUSE2_REPORT_ID 0x12
5959#define DOUBLE_REPORT_ID 0xf7
60+ #define USB_BATTERY_TIMEOUT_MS 60000
61+
6062/* These definitions are not precise, but they're close enough. (Bits
6163 * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
6264 * to be some kind of bit mask -- 0x20 may be a near-field reading,
@@ -140,6 +142,7 @@ struct magicmouse_sc {
140142
141143 struct hid_device * hdev ;
142144 struct delayed_work work ;
145+ struct timer_list battery_timer ;
143146};
144147
145148static int magicmouse_firm_touch (struct magicmouse_sc * msc )
@@ -735,18 +738,51 @@ static void magicmouse_enable_mt_work(struct work_struct *work)
735738 hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
736739}
737740
741+ static int magicmouse_fetch_battery (struct hid_device * hdev )
742+ {
743+ #ifdef CONFIG_HID_BATTERY_STRENGTH
744+ struct hid_report_enum * report_enum ;
745+ struct hid_report * report ;
746+
747+ if (!hdev -> battery || hdev -> vendor != USB_VENDOR_ID_APPLE ||
748+ (hdev -> product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
749+ hdev -> product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ))
750+ return -1 ;
751+
752+ report_enum = & hdev -> report_enum [hdev -> battery_report_type ];
753+ report = report_enum -> report_id_hash [hdev -> battery_report_id ];
754+
755+ if (!report || report -> maxfield < 1 )
756+ return -1 ;
757+
758+ if (hdev -> battery_capacity == hdev -> battery_max )
759+ return -1 ;
760+
761+ hid_hw_request (hdev , report , HID_REQ_GET_REPORT );
762+ return 0 ;
763+ #else
764+ return -1 ;
765+ #endif
766+ }
767+
768+ static void magicmouse_battery_timer_tick (struct timer_list * t )
769+ {
770+ struct magicmouse_sc * msc = from_timer (msc , t , battery_timer );
771+ struct hid_device * hdev = msc -> hdev ;
772+
773+ if (magicmouse_fetch_battery (hdev ) == 0 ) {
774+ mod_timer (& msc -> battery_timer ,
775+ jiffies + msecs_to_jiffies (USB_BATTERY_TIMEOUT_MS ));
776+ }
777+ }
778+
738779static int magicmouse_probe (struct hid_device * hdev ,
739780 const struct hid_device_id * id )
740781{
741782 struct magicmouse_sc * msc ;
742783 struct hid_report * report ;
743784 int ret ;
744785
745- if (id -> vendor == USB_VENDOR_ID_APPLE &&
746- id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
747- hdev -> type != HID_TYPE_USBMOUSE )
748- return - ENODEV ;
749-
750786 msc = devm_kzalloc (& hdev -> dev , sizeof (* msc ), GFP_KERNEL );
751787 if (msc == NULL ) {
752788 hid_err (hdev , "can't alloc magicmouse descriptor\n" );
@@ -772,6 +808,16 @@ static int magicmouse_probe(struct hid_device *hdev,
772808 return ret ;
773809 }
774810
811+ timer_setup (& msc -> battery_timer , magicmouse_battery_timer_tick , 0 );
812+ mod_timer (& msc -> battery_timer ,
813+ jiffies + msecs_to_jiffies (USB_BATTERY_TIMEOUT_MS ));
814+ magicmouse_fetch_battery (hdev );
815+
816+ if (id -> vendor == USB_VENDOR_ID_APPLE &&
817+ (id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
818+ (id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && hdev -> type != HID_TYPE_USBMOUSE )))
819+ return 0 ;
820+
775821 if (!msc -> input ) {
776822 hid_err (hdev , "magicmouse input not registered\n" );
777823 ret = - ENOMEM ;
@@ -832,17 +878,52 @@ static void magicmouse_remove(struct hid_device *hdev)
832878{
833879 struct magicmouse_sc * msc = hid_get_drvdata (hdev );
834880
835- if (msc )
881+ if (msc ) {
836882 cancel_delayed_work_sync (& msc -> work );
883+ del_timer_sync (& msc -> battery_timer );
884+ }
837885
838886 hid_hw_stop (hdev );
839887}
840888
889+ static __u8 * magicmouse_report_fixup (struct hid_device * hdev , __u8 * rdesc ,
890+ unsigned int * rsize )
891+ {
892+ /*
893+ * Change the usage from:
894+ * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0
895+ * 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3
896+ * To:
897+ * 0x05, 0x01, // Usage Page (Generic Desktop) 0
898+ * 0x09, 0x02, // Usage (Mouse) 2
899+ */
900+ if (hdev -> vendor == USB_VENDOR_ID_APPLE &&
901+ (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
902+ hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) &&
903+ * rsize == 83 && rdesc [46 ] == 0x84 && rdesc [58 ] == 0x85 ) {
904+ hid_info (hdev ,
905+ "fixing up magicmouse battery report descriptor\n" );
906+ * rsize = * rsize - 1 ;
907+ rdesc = kmemdup (rdesc + 1 , * rsize , GFP_KERNEL );
908+ if (!rdesc )
909+ return NULL ;
910+
911+ rdesc [0 ] = 0x05 ;
912+ rdesc [1 ] = 0x01 ;
913+ rdesc [2 ] = 0x09 ;
914+ rdesc [3 ] = 0x02 ;
915+ }
916+
917+ return rdesc ;
918+ }
919+
841920static const struct hid_device_id magic_mice [] = {
842921 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
843922 USB_DEVICE_ID_APPLE_MAGICMOUSE ), .driver_data = 0 },
844923 { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE ,
845924 USB_DEVICE_ID_APPLE_MAGICMOUSE2 ), .driver_data = 0 },
925+ { HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,
926+ USB_DEVICE_ID_APPLE_MAGICMOUSE2 ), .driver_data = 0 },
846927 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
847928 USB_DEVICE_ID_APPLE_MAGICTRACKPAD ), .driver_data = 0 },
848929 { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE ,
@@ -858,6 +939,7 @@ static struct hid_driver magicmouse_driver = {
858939 .id_table = magic_mice ,
859940 .probe = magicmouse_probe ,
860941 .remove = magicmouse_remove ,
942+ .report_fixup = magicmouse_report_fixup ,
861943 .raw_event = magicmouse_raw_event ,
862944 .event = magicmouse_event ,
863945 .input_mapping = magicmouse_input_mapping ,
0 commit comments