16
16
#include <linux/input/mt.h>
17
17
#include <linux/module.h>
18
18
#include <linux/slab.h>
19
+ #include <linux/workqueue.h>
19
20
20
21
#include "hid-ids.h"
21
22
@@ -128,6 +129,9 @@ struct magicmouse_sc {
128
129
u8 size ;
129
130
} touches [16 ];
130
131
int tracking_ids [16 ];
132
+
133
+ struct hid_device * hdev ;
134
+ struct delayed_work work ;
131
135
};
132
136
133
137
static int magicmouse_firm_touch (struct magicmouse_sc * msc )
@@ -631,20 +635,60 @@ static int magicmouse_input_configured(struct hid_device *hdev,
631
635
return 0 ;
632
636
}
633
637
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 )
637
639
{
638
640
const u8 * feature ;
639
641
const u8 feature_mt [] = { 0xD7 , 0x01 };
640
642
const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
641
643
const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
642
644
const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
643
645
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
+ {
644
689
struct magicmouse_sc * msc ;
645
690
struct hid_report * report ;
646
691
int ret ;
647
- int feature_size ;
648
692
649
693
if (id -> vendor == USB_VENDOR_ID_APPLE &&
650
694
id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
@@ -658,6 +702,8 @@ static int magicmouse_probe(struct hid_device *hdev,
658
702
}
659
703
660
704
msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
705
+ msc -> hdev = hdev ;
706
+ INIT_DEFERRABLE_WORK (& msc -> work , magicmouse_enable_mt_work );
661
707
662
708
msc -> quirks = id -> driver_data ;
663
709
hid_set_drvdata (hdev , msc );
@@ -707,28 +753,6 @@ static int magicmouse_probe(struct hid_device *hdev,
707
753
}
708
754
report -> size = 6 ;
709
755
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
-
732
756
/*
733
757
* Some devices repond with 'invalid report id' when feature
734
758
* report switching it into multitouch mode is sent to it.
@@ -737,20 +761,28 @@ static int magicmouse_probe(struct hid_device *hdev,
737
761
* but there seems to be no other way of switching the mode.
738
762
* Thus the super-ugly hacky success check below.
739
763
*/
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 ) {
744
766
hid_err (hdev , "unable to request touch data (%d)\n" , ret );
745
767
goto err_stop_hw ;
746
768
}
769
+ if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
770
+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
771
+ }
747
772
748
773
return 0 ;
749
774
err_stop_hw :
750
775
hid_hw_stop (hdev );
751
776
return ret ;
752
777
}
753
778
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
+
754
786
static const struct hid_device_id magic_mice [] = {
755
787
{ HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
756
788
USB_DEVICE_ID_APPLE_MAGICMOUSE ), .driver_data = 0 },
@@ -770,6 +802,7 @@ static struct hid_driver magicmouse_driver = {
770
802
.name = "magicmouse" ,
771
803
.id_table = magic_mice ,
772
804
.probe = magicmouse_probe ,
805
+ .remove = magicmouse_remove ,
773
806
.raw_event = magicmouse_raw_event ,
774
807
.event = magicmouse_event ,
775
808
.input_mapping = magicmouse_input_mapping ,
0 commit comments