@@ -61,6 +61,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
6161#define MOUSE2_REPORT_ID 0x12
6262#define DOUBLE_REPORT_ID 0xf7
6363#define SPI_REPORT_ID 0x02
64+ #define SPI_RESET_REPORT_ID 0x60
6465#define MTP_REPORT_ID 0x75
6566#define USB_BATTERY_TIMEOUT_MS 60000
6667
@@ -176,6 +177,98 @@ struct magicmouse_sc {
176177 struct magicmouse_input_ops input_ops ;
177178};
178179
180+ static int magicmouse_enable_multitouch (struct hid_device * hdev )
181+ {
182+ const u8 * feature ;
183+ const u8 feature_mt [] = { 0xD7 , 0x01 };
184+ const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
185+ const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
186+ const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
187+ u8 * buf ;
188+ int ret ;
189+ int feature_size ;
190+
191+ if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
192+ hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ) {
193+ if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
194+ feature_size = sizeof (feature_mt_trackpad2_bt );
195+ feature = feature_mt_trackpad2_bt ;
196+ } else { /* USB_VENDOR_ID_APPLE */
197+ feature_size = sizeof (feature_mt_trackpad2_usb );
198+ feature = feature_mt_trackpad2_usb ;
199+ }
200+ } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
201+ feature_size = sizeof (feature_mt_trackpad2_usb );
202+ feature = feature_mt_trackpad2_usb ;
203+ } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
204+ feature_size = sizeof (feature_mt_mouse2 );
205+ feature = feature_mt_mouse2 ;
206+ } else {
207+ feature_size = sizeof (feature_mt );
208+ feature = feature_mt ;
209+ }
210+
211+ buf = kmemdup (feature , feature_size , GFP_KERNEL );
212+ if (!buf )
213+ return - ENOMEM ;
214+
215+ ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
216+ HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
217+ kfree (buf );
218+ return ret ;
219+ }
220+
221+ static void magicmouse_enable_mt_work (struct work_struct * work )
222+ {
223+ struct magicmouse_sc * msc =
224+ container_of (work , struct magicmouse_sc , work .work );
225+ int ret ;
226+
227+ ret = magicmouse_enable_multitouch (msc -> hdev );
228+ if (ret < 0 )
229+ hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
230+ }
231+
232+ static int magicmouse_open (struct input_dev * dev )
233+ {
234+ struct hid_device * hdev = input_get_drvdata (dev );
235+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
236+ int ret ;
237+
238+ ret = hid_hw_open (hdev );
239+ if (ret )
240+ return ret ;
241+
242+ /*
243+ * Some devices repond with 'invalid report id' when feature
244+ * report switching it into multitouch mode is sent to it.
245+ *
246+ * This results in -EIO from the _raw low-level transport callback,
247+ * but there seems to be no other way of switching the mode.
248+ * Thus the super-ugly hacky success check below.
249+ */
250+ ret = magicmouse_enable_multitouch (hdev );
251+ if (ret == - EIO && hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
252+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
253+ return 0 ;
254+ }
255+ if (ret < 0 )
256+ hid_err (hdev , "unable to request touch data (%d)\n" , ret );
257+
258+ /*
259+ * MT enable is usually not required after the first time, so don't
260+ * consider it fatal.
261+ */
262+ return 0 ;
263+ }
264+
265+ static void magicmouse_close (struct input_dev * dev )
266+ {
267+ struct hid_device * hdev = input_get_drvdata (dev );
268+
269+ hid_hw_close (hdev );
270+ }
271+
179272static int magicmouse_firm_touch (struct magicmouse_sc * msc )
180273{
181274 int touch = -1 ;
@@ -706,12 +799,19 @@ static int magicmouse_raw_event_mtp(struct hid_device *hdev,
706799static int magicmouse_raw_event_spi (struct hid_device * hdev ,
707800 struct hid_report * report , u8 * data , int size )
708801{
802+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
709803 const size_t hdr_sz = sizeof (struct tp_mouse_report );
710804
711- if (size < hdr_sz )
805+ if (! size )
712806 return 0 ;
713807
714- if (data [0 ] != TRACKPAD2_USB_REPORT_ID )
808+ if (data [0 ] == SPI_RESET_REPORT_ID ) {
809+ hid_info (hdev , "Touch controller was reset, re-enabling touch mode\n" );
810+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (10 ));
811+ return 1 ;
812+ }
813+
814+ if (data [0 ] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz )
715815 return 0 ;
716816
717817 return magicmouse_raw_event_mtp (hdev , report , data + hdr_sz , size - hdr_sz );
@@ -901,10 +1001,17 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
9011001 */
9021002 __clear_bit (EV_REP , input -> evbit );
9031003
1004+ /*
1005+ * This isn't strictly speaking needed for USB, but enabling MT on
1006+ * device open is probably more robust than only doing it once on probe
1007+ * even if USB devices are not known to suffer from the SPI reset issue.
1008+ */
1009+ input -> open = magicmouse_open ;
1010+ input -> close = magicmouse_close ;
9041011 return 0 ;
9051012}
9061013
907- static int magicmouse_setup_input_spi (struct input_dev * input ,
1014+ static int magicmouse_setup_input_mtp (struct input_dev * input ,
9081015 struct hid_device * hdev )
9091016{
9101017 int error ;
@@ -977,6 +1084,25 @@ static int magicmouse_setup_input_spi(struct input_dev *input,
9771084 return 0 ;
9781085}
9791086
1087+ static int magicmouse_setup_input_spi (struct input_dev * input ,
1088+ struct hid_device * hdev )
1089+ {
1090+ int ret = magicmouse_setup_input_mtp (input , hdev );
1091+ if (ret )
1092+ return ret ;
1093+
1094+ /*
1095+ * Override the default input->open function to send the MT
1096+ * enable every time the device is opened. This ensures it works
1097+ * even if we missed a reset event due to the device being closed.
1098+ * input->close is overridden for symmetry.
1099+ */
1100+ input -> open = magicmouse_open ;
1101+ input -> close = magicmouse_close ;
1102+
1103+ return 0 ;
1104+ }
1105+
9801106static int magicmouse_input_mapping (struct hid_device * hdev ,
9811107 struct hid_input * hi , struct hid_field * field ,
9821108 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -1015,58 +1141,6 @@ static int magicmouse_input_configured(struct hid_device *hdev,
10151141 return 0 ;
10161142}
10171143
1018- static int magicmouse_enable_multitouch (struct hid_device * hdev )
1019- {
1020- const u8 * feature ;
1021- const u8 feature_mt [] = { 0xD7 , 0x01 };
1022- const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
1023- const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
1024- const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
1025- u8 * buf ;
1026- int ret ;
1027- int feature_size ;
1028-
1029- if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
1030- hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ) {
1031- if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
1032- feature_size = sizeof (feature_mt_trackpad2_bt );
1033- feature = feature_mt_trackpad2_bt ;
1034- } else { /* USB_VENDOR_ID_APPLE */
1035- feature_size = sizeof (feature_mt_trackpad2_usb );
1036- feature = feature_mt_trackpad2_usb ;
1037- }
1038- } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
1039- feature_size = sizeof (feature_mt_trackpad2_usb );
1040- feature = feature_mt_trackpad2_usb ;
1041- } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
1042- feature_size = sizeof (feature_mt_mouse2 );
1043- feature = feature_mt_mouse2 ;
1044- } else {
1045- feature_size = sizeof (feature_mt );
1046- feature = feature_mt ;
1047- }
1048-
1049- buf = kmemdup (feature , feature_size , GFP_KERNEL );
1050- if (!buf )
1051- return - ENOMEM ;
1052-
1053- ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
1054- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
1055- kfree (buf );
1056- return ret ;
1057- }
1058-
1059- static void magicmouse_enable_mt_work (struct work_struct * work )
1060- {
1061- struct magicmouse_sc * msc =
1062- container_of (work , struct magicmouse_sc , work .work );
1063- int ret ;
1064-
1065- ret = magicmouse_enable_multitouch (msc -> hdev );
1066- if (ret < 0 )
1067- hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
1068- }
1069-
10701144static int magicmouse_fetch_battery (struct hid_device * hdev )
10711145{
10721146#ifdef CONFIG_HID_BATTERY_STRENGTH
@@ -1127,7 +1201,7 @@ static int magicmouse_probe(struct hid_device *hdev,
11271201 // conflicts with the report ID.
11281202 if (id -> bus == BUS_HOST ) {
11291203 msc -> input_ops .raw_event = magicmouse_raw_event_mtp ;
1130- msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
1204+ msc -> input_ops .setup_input = magicmouse_setup_input_mtp ;
11311205 } else if (id -> bus == BUS_SPI ) {
11321206 msc -> input_ops .raw_event = magicmouse_raw_event_spi ;
11331207 msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
@@ -1210,21 +1284,10 @@ static int magicmouse_probe(struct hid_device *hdev,
12101284 if (id -> bus == BUS_HOST )
12111285 return 0 ;
12121286
1213- /*
1214- * Some devices repond with 'invalid report id' when feature
1215- * report switching it into multitouch mode is sent to it.
1216- *
1217- * This results in -EIO from the _raw low-level transport callback,
1218- * but there seems to be no other way of switching the mode.
1219- * Thus the super-ugly hacky success check below.
1220- */
1221- ret = magicmouse_enable_multitouch (hdev );
1222- if (ret != - EIO && ret < 0 ) {
1223- hid_err (hdev , "unable to request touch data (%d)\n" , ret );
1224- goto err_stop_hw ;
1225- }
1226- if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
1227- schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
1287+ /* SPI devices need to watch for reset events to re-send the MT enable */
1288+ if (id -> bus == BUS_SPI ) {
1289+ report = hid_register_report (hdev , HID_INPUT_REPORT , SPI_RESET_REPORT_ID , 0 );
1290+ report -> size = 2 ;
12281291 }
12291292
12301293 return 0 ;
0 commit comments