1616#include <linux/input/mt.h>
1717#include <linux/module.h>
1818#include <linux/slab.h>
19+ #include <linux/workqueue.h>
1920
2021#include "hid-ids.h"
2122
@@ -128,6 +129,9 @@ struct magicmouse_sc {
128129 u8 size ;
129130 } touches [16 ];
130131 int tracking_ids [16 ];
132+
133+ struct hid_device * hdev ;
134+ struct delayed_work work ;
131135};
132136
133137static int magicmouse_firm_touch (struct magicmouse_sc * msc )
@@ -631,20 +635,60 @@ static int magicmouse_input_configured(struct hid_device *hdev,
631635 return 0 ;
632636}
633637
634-
635- static int magicmouse_probe (struct hid_device * hdev ,
636- const struct hid_device_id * id )
638+ static int magicmouse_enable_multitouch (struct hid_device * hdev )
637639{
638640 const u8 * feature ;
639641 const u8 feature_mt [] = { 0xD7 , 0x01 };
640642 const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
641643 const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
642644 const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
643645 u8 * buf ;
646+ int ret ;
647+ int feature_size ;
648+
649+ if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
650+ if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
651+ feature_size = sizeof (feature_mt_trackpad2_bt );
652+ feature = feature_mt_trackpad2_bt ;
653+ } else { /* USB_VENDOR_ID_APPLE */
654+ feature_size = sizeof (feature_mt_trackpad2_usb );
655+ feature = feature_mt_trackpad2_usb ;
656+ }
657+ } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
658+ feature_size = sizeof (feature_mt_mouse2 );
659+ feature = feature_mt_mouse2 ;
660+ } else {
661+ feature_size = sizeof (feature_mt );
662+ feature = feature_mt ;
663+ }
664+
665+ buf = kmemdup (feature , feature_size , GFP_KERNEL );
666+ if (!buf )
667+ return - ENOMEM ;
668+
669+ ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
670+ HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
671+ kfree (buf );
672+ return ret ;
673+ }
674+
675+ static void magicmouse_enable_mt_work (struct work_struct * work )
676+ {
677+ struct magicmouse_sc * msc =
678+ container_of (work , struct magicmouse_sc , work .work );
679+ int ret ;
680+
681+ ret = magicmouse_enable_multitouch (msc -> hdev );
682+ if (ret < 0 )
683+ hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
684+ }
685+
686+ static int magicmouse_probe (struct hid_device * hdev ,
687+ const struct hid_device_id * id )
688+ {
644689 struct magicmouse_sc * msc ;
645690 struct hid_report * report ;
646691 int ret ;
647- int feature_size ;
648692
649693 if (id -> vendor == USB_VENDOR_ID_APPLE &&
650694 id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
@@ -658,6 +702,8 @@ static int magicmouse_probe(struct hid_device *hdev,
658702 }
659703
660704 msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
705+ msc -> hdev = hdev ;
706+ INIT_DEFERRABLE_WORK (& msc -> work , magicmouse_enable_mt_work );
661707
662708 msc -> quirks = id -> driver_data ;
663709 hid_set_drvdata (hdev , msc );
@@ -707,28 +753,6 @@ static int magicmouse_probe(struct hid_device *hdev,
707753 }
708754 report -> size = 6 ;
709755
710- if (id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
711- if (id -> vendor == BT_VENDOR_ID_APPLE ) {
712- feature_size = sizeof (feature_mt_trackpad2_bt );
713- feature = feature_mt_trackpad2_bt ;
714- } else { /* USB_VENDOR_ID_APPLE */
715- feature_size = sizeof (feature_mt_trackpad2_usb );
716- feature = feature_mt_trackpad2_usb ;
717- }
718- } else if (id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
719- feature_size = sizeof (feature_mt_mouse2 );
720- feature = feature_mt_mouse2 ;
721- } else {
722- feature_size = sizeof (feature_mt );
723- feature = feature_mt ;
724- }
725-
726- buf = kmemdup (feature , feature_size , GFP_KERNEL );
727- if (!buf ) {
728- ret = - ENOMEM ;
729- goto err_stop_hw ;
730- }
731-
732756 /*
733757 * Some devices repond with 'invalid report id' when feature
734758 * report switching it into multitouch mode is sent to it.
@@ -737,20 +761,28 @@ static int magicmouse_probe(struct hid_device *hdev,
737761 * but there seems to be no other way of switching the mode.
738762 * Thus the super-ugly hacky success check below.
739763 */
740- ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
741- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
742- kfree (buf );
743- if (ret != - EIO && ret != feature_size ) {
764+ ret = magicmouse_enable_multitouch (hdev );
765+ if (ret != - EIO && ret < 0 ) {
744766 hid_err (hdev , "unable to request touch data (%d)\n" , ret );
745767 goto err_stop_hw ;
746768 }
769+ if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
770+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
771+ }
747772
748773 return 0 ;
749774err_stop_hw :
750775 hid_hw_stop (hdev );
751776 return ret ;
752777}
753778
779+ static void magicmouse_remove (struct hid_device * hdev )
780+ {
781+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
782+ cancel_delayed_work_sync (& msc -> work );
783+ hid_hw_stop (hdev );
784+ }
785+
754786static const struct hid_device_id magic_mice [] = {
755787 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
756788 USB_DEVICE_ID_APPLE_MAGICMOUSE ), .driver_data = 0 },
@@ -770,6 +802,7 @@ static struct hid_driver magicmouse_driver = {
770802 .name = "magicmouse" ,
771803 .id_table = magic_mice ,
772804 .probe = magicmouse_probe ,
805+ .remove = magicmouse_remove ,
773806 .raw_event = magicmouse_raw_event ,
774807 .event = magicmouse_event ,
775808 .input_mapping = magicmouse_input_mapping ,
0 commit comments