@@ -60,6 +60,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
6060#define MOUSE2_REPORT_ID 0x12
6161#define DOUBLE_REPORT_ID 0xf7
6262#define SPI_REPORT_ID 0x02
63+ #define SPI_RESET_REPORT_ID 0x60
6364#define MTP_REPORT_ID 0x75
6465#define USB_BATTERY_TIMEOUT_MS 60000
6566
@@ -175,6 +176,98 @@ struct magicmouse_sc {
175176 struct magicmouse_input_ops input_ops ;
176177};
177178
179+ static int magicmouse_enable_multitouch (struct hid_device * hdev )
180+ {
181+ const u8 * feature ;
182+ const u8 feature_mt [] = { 0xD7 , 0x01 };
183+ const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
184+ const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
185+ const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
186+ u8 * buf ;
187+ int ret ;
188+ int feature_size ;
189+
190+ if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
191+ hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ) {
192+ if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
193+ feature_size = sizeof (feature_mt_trackpad2_bt );
194+ feature = feature_mt_trackpad2_bt ;
195+ } else { /* USB_VENDOR_ID_APPLE */
196+ feature_size = sizeof (feature_mt_trackpad2_usb );
197+ feature = feature_mt_trackpad2_usb ;
198+ }
199+ } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
200+ feature_size = sizeof (feature_mt_trackpad2_usb );
201+ feature = feature_mt_trackpad2_usb ;
202+ } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
203+ feature_size = sizeof (feature_mt_mouse2 );
204+ feature = feature_mt_mouse2 ;
205+ } else {
206+ feature_size = sizeof (feature_mt );
207+ feature = feature_mt ;
208+ }
209+
210+ buf = kmemdup (feature , feature_size , GFP_KERNEL );
211+ if (!buf )
212+ return - ENOMEM ;
213+
214+ ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
215+ HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
216+ kfree (buf );
217+ return ret ;
218+ }
219+
220+ static void magicmouse_enable_mt_work (struct work_struct * work )
221+ {
222+ struct magicmouse_sc * msc =
223+ container_of (work , struct magicmouse_sc , work .work );
224+ int ret ;
225+
226+ ret = magicmouse_enable_multitouch (msc -> hdev );
227+ if (ret < 0 )
228+ hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
229+ }
230+
231+ static int magicmouse_open (struct input_dev * dev )
232+ {
233+ struct hid_device * hdev = input_get_drvdata (dev );
234+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
235+ int ret ;
236+
237+ ret = hid_hw_open (hdev );
238+ if (ret )
239+ return ret ;
240+
241+ /*
242+ * Some devices repond with 'invalid report id' when feature
243+ * report switching it into multitouch mode is sent to it.
244+ *
245+ * This results in -EIO from the _raw low-level transport callback,
246+ * but there seems to be no other way of switching the mode.
247+ * Thus the super-ugly hacky success check below.
248+ */
249+ ret = magicmouse_enable_multitouch (hdev );
250+ if (ret == - EIO && hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
251+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
252+ return 0 ;
253+ }
254+ if (ret < 0 )
255+ hid_err (hdev , "unable to request touch data (%d)\n" , ret );
256+
257+ /*
258+ * MT enable is usually not required after the first time, so don't
259+ * consider it fatal.
260+ */
261+ return 0 ;
262+ }
263+
264+ static void magicmouse_close (struct input_dev * dev )
265+ {
266+ struct hid_device * hdev = input_get_drvdata (dev );
267+
268+ hid_hw_close (hdev );
269+ }
270+
178271static int magicmouse_firm_touch (struct magicmouse_sc * msc )
179272{
180273 int touch = -1 ;
@@ -705,12 +798,19 @@ static int magicmouse_raw_event_mtp(struct hid_device *hdev,
705798static int magicmouse_raw_event_spi (struct hid_device * hdev ,
706799 struct hid_report * report , u8 * data , int size )
707800{
801+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
708802 const size_t hdr_sz = sizeof (struct tp_mouse_report );
709803
710- if (size < hdr_sz )
804+ if (! size )
711805 return 0 ;
712806
713- if (data [0 ] != TRACKPAD2_USB_REPORT_ID )
807+ if (data [0 ] == SPI_RESET_REPORT_ID ) {
808+ hid_info (hdev , "Touch controller was reset, re-enabling touch mode\n" );
809+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (10 ));
810+ return 1 ;
811+ }
812+
813+ if (data [0 ] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz )
714814 return 0 ;
715815
716816 return magicmouse_raw_event_mtp (hdev , report , data + hdr_sz , size - hdr_sz );
@@ -897,10 +997,17 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
897997 */
898998 __clear_bit (EV_REP , input -> evbit );
899999
1000+ /*
1001+ * This isn't strictly speaking needed for USB, but enabling MT on
1002+ * device open is probably more robust than only doing it once on probe
1003+ * even if USB devices are not known to suffer from the SPI reset issue.
1004+ */
1005+ input -> open = magicmouse_open ;
1006+ input -> close = magicmouse_close ;
9001007 return 0 ;
9011008}
9021009
903- static int magicmouse_setup_input_spi (struct input_dev * input ,
1010+ static int magicmouse_setup_input_mtp (struct input_dev * input ,
9041011 struct hid_device * hdev )
9051012{
9061013 int error ;
@@ -973,6 +1080,25 @@ static int magicmouse_setup_input_spi(struct input_dev *input,
9731080 return 0 ;
9741081}
9751082
1083+ static int magicmouse_setup_input_spi (struct input_dev * input ,
1084+ struct hid_device * hdev )
1085+ {
1086+ int ret = magicmouse_setup_input_mtp (input , hdev );
1087+ if (ret )
1088+ return ret ;
1089+
1090+ /*
1091+ * Override the default input->open function to send the MT
1092+ * enable every time the device is opened. This ensures it works
1093+ * even if we missed a reset event due to the device being closed.
1094+ * input->close is overridden for symmetry.
1095+ */
1096+ input -> open = magicmouse_open ;
1097+ input -> close = magicmouse_close ;
1098+
1099+ return 0 ;
1100+ }
1101+
9761102static int magicmouse_input_mapping (struct hid_device * hdev ,
9771103 struct hid_input * hi , struct hid_field * field ,
9781104 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -1011,58 +1137,6 @@ static int magicmouse_input_configured(struct hid_device *hdev,
10111137 return 0 ;
10121138}
10131139
1014- static int magicmouse_enable_multitouch (struct hid_device * hdev )
1015- {
1016- const u8 * feature ;
1017- const u8 feature_mt [] = { 0xD7 , 0x01 };
1018- const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
1019- const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
1020- const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
1021- u8 * buf ;
1022- int ret ;
1023- int feature_size ;
1024-
1025- if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
1026- hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ) {
1027- if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
1028- feature_size = sizeof (feature_mt_trackpad2_bt );
1029- feature = feature_mt_trackpad2_bt ;
1030- } else { /* USB_VENDOR_ID_APPLE */
1031- feature_size = sizeof (feature_mt_trackpad2_usb );
1032- feature = feature_mt_trackpad2_usb ;
1033- }
1034- } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
1035- feature_size = sizeof (feature_mt_trackpad2_usb );
1036- feature = feature_mt_trackpad2_usb ;
1037- } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
1038- feature_size = sizeof (feature_mt_mouse2 );
1039- feature = feature_mt_mouse2 ;
1040- } else {
1041- feature_size = sizeof (feature_mt );
1042- feature = feature_mt ;
1043- }
1044-
1045- buf = kmemdup (feature , feature_size , GFP_KERNEL );
1046- if (!buf )
1047- return - ENOMEM ;
1048-
1049- ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
1050- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
1051- kfree (buf );
1052- return ret ;
1053- }
1054-
1055- static void magicmouse_enable_mt_work (struct work_struct * work )
1056- {
1057- struct magicmouse_sc * msc =
1058- container_of (work , struct magicmouse_sc , work .work );
1059- int ret ;
1060-
1061- ret = magicmouse_enable_multitouch (msc -> hdev );
1062- if (ret < 0 )
1063- hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
1064- }
1065-
10661140static int magicmouse_fetch_battery (struct hid_device * hdev )
10671141{
10681142#ifdef CONFIG_HID_BATTERY_STRENGTH
@@ -1123,7 +1197,7 @@ static int magicmouse_probe(struct hid_device *hdev,
11231197 // conflicts with the report ID.
11241198 if (id -> bus == BUS_HOST ) {
11251199 msc -> input_ops .raw_event = magicmouse_raw_event_mtp ;
1126- msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
1200+ msc -> input_ops .setup_input = magicmouse_setup_input_mtp ;
11271201 } else if (id -> bus == BUS_SPI ) {
11281202 msc -> input_ops .raw_event = magicmouse_raw_event_spi ;
11291203 msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
@@ -1206,21 +1280,10 @@ static int magicmouse_probe(struct hid_device *hdev,
12061280 if (id -> bus == BUS_HOST )
12071281 return 0 ;
12081282
1209- /*
1210- * Some devices repond with 'invalid report id' when feature
1211- * report switching it into multitouch mode is sent to it.
1212- *
1213- * This results in -EIO from the _raw low-level transport callback,
1214- * but there seems to be no other way of switching the mode.
1215- * Thus the super-ugly hacky success check below.
1216- */
1217- ret = magicmouse_enable_multitouch (hdev );
1218- if (ret != - EIO && ret < 0 ) {
1219- hid_err (hdev , "unable to request touch data (%d)\n" , ret );
1220- goto err_stop_hw ;
1221- }
1222- if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
1223- schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
1283+ /* SPI devices need to watch for reset events to re-send the MT enable */
1284+ if (id -> bus == BUS_SPI ) {
1285+ report = hid_register_report (hdev , HID_INPUT_REPORT , SPI_RESET_REPORT_ID , 0 );
1286+ report -> size = 2 ;
12241287 }
12251288
12261289 return 0 ;
0 commit comments