@@ -63,6 +63,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
6363#define SPI_REPORT_ID 0x02
6464#define SPI_RESET_REPORT_ID 0x60
6565#define MTP_REPORT_ID 0x75
66+ #define SENSOR_DIMENSIONS_REPORT_ID 0xd9
6667#define USB_BATTERY_TIMEOUT_SEC 60
6768
6869#define MAX_CONTACTS 16
@@ -117,6 +118,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
117118#define TRACKPAD2_RES_Y \
118119 ((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
119120
121+ /* These are fallback values, since the real values will be queried from the device. */
120122#define J314_TP_DIMENSION_X (float)13000
121123#define J314_TP_MIN_X -5900
122124#define J314_TP_MAX_X 6500
@@ -140,6 +142,7 @@ struct magicmouse_input_ops {
140142 * struct magicmouse_sc - Tracks Magic Mouse-specific data.
141143 * @input: Input device through which we report events.
142144 * @quirks: Currently unused.
145+ * @query_dimensions: Whether to query and update dimensions on first open
143146 * @ntouches: Number of touches in most recent touch report.
144147 * @scroll_accel: Number of consecutive scroll motions.
145148 * @scroll_jiffies: Time of last scroll motion.
@@ -154,6 +157,7 @@ struct magicmouse_input_ops {
154157struct magicmouse_sc {
155158 struct input_dev * input ;
156159 unsigned long quirks ;
160+ bool query_dimensions ;
157161
158162 int ntouches ;
159163 int scroll_accel ;
@@ -179,6 +183,11 @@ struct magicmouse_sc {
179183
180184static int magicmouse_enable_multitouch (struct hid_device * hdev );
181185
186+ static inline int le16_to_int (__le16 x )
187+ {
188+ return (signed short )le16_to_cpu (x );
189+ }
190+
182191static int magicmouse_open (struct input_dev * dev )
183192{
184193 struct hid_device * hdev = input_get_drvdata (dev );
@@ -196,21 +205,69 @@ static int magicmouse_open(struct input_dev *dev)
196205 * This results in -EIO from the _raw low-level transport callback,
197206 * but there seems to be no other way of switching the mode.
198207 * Thus the super-ugly hacky success check below.
208+ *
209+ * MTP devices do not need this.
199210 */
200- ret = magicmouse_enable_multitouch (hdev );
201- if (ret != - EIO && ret < 0 ) {
202- hid_err (hdev , "unable to request touch data (%d)\n" , ret );
203- return ret ;
204- }
205- if (ret == - EIO && (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
206- hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC )) {
207- schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
211+ if (hdev -> bus != BUS_HOST ) {
212+ ret = magicmouse_enable_multitouch (hdev );
213+ if (ret != - EIO && ret < 0 ) {
214+ hid_err (hdev , "unable to request touch data (%d)\n" , ret );
215+ return ret ;
216+ }
217+ if (ret == - EIO && (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
218+ hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC )) {
219+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
220+ }
208221 }
209222
210223 /*
211- * MT enable is usually not required after the first time, so don't
212- * consider it fatal.
224+ * For Apple Silicon trackpads, we want to query the dimensions on
225+ * device open. This is because doing so requires the firmware, but
226+ * we don't want to force a firmware load until the device is opened
227+ * for the first time. So do that here and update the input properties
228+ * just in time before userspace queries them.
213229 */
230+ if (msc -> query_dimensions ) {
231+ struct input_dev * input = msc -> input ;
232+ u8 buf [32 ];
233+ struct {
234+ __le32 width ;
235+ __le32 height ;
236+ __le16 min_x ;
237+ __le16 min_y ;
238+ __le16 max_x ;
239+ __le16 max_y ;
240+ } dim ;
241+ uint32_t x_span , y_span ;
242+
243+ ret = hid_hw_raw_request (hdev , SENSOR_DIMENSIONS_REPORT_ID , buf , sizeof (buf ), HID_FEATURE_REPORT , HID_REQ_GET_REPORT );
244+ if (ret < (int )(1 + sizeof (dim ))) {
245+ hid_err (hdev , "unable to request dimensions (%d)\n" , ret );
246+ return ret ;
247+ }
248+
249+ memcpy (& dim , buf + 1 , sizeof (dim ));
250+
251+ /* finger position */
252+ input_set_abs_params (input , ABS_MT_POSITION_X ,
253+ le16_to_int (dim .min_x ), le16_to_int (dim .max_x ), 0 , 0 );
254+ /* Y axis is inverted */
255+ input_set_abs_params (input , ABS_MT_POSITION_Y ,
256+ - le16_to_int (dim .max_y ), - le16_to_int (dim .min_y ), 0 , 0 );
257+ x_span = le16_to_int (dim .max_x ) - le16_to_int (dim .min_x );
258+ y_span = le16_to_int (dim .max_y ) - le16_to_int (dim .min_y );
259+
260+ /* X/Y resolution */
261+ input_abs_set_res (input , ABS_MT_POSITION_X , 100 * x_span / le32_to_cpu (dim .width ) );
262+ input_abs_set_res (input , ABS_MT_POSITION_Y , 100 * y_span / le32_to_cpu (dim .height ) );
263+
264+ /* copy info, as input_mt_init_slots() does */
265+ dev -> absinfo [ABS_X ] = dev -> absinfo [ABS_MT_POSITION_X ];
266+ dev -> absinfo [ABS_Y ] = dev -> absinfo [ABS_MT_POSITION_Y ];
267+
268+ msc -> query_dimensions = false;
269+ }
270+
214271 return 0 ;
215272}
216273
@@ -660,11 +717,6 @@ struct tp_mouse_report {
660717 u8 padding [4 ];
661718};
662719
663- static inline int le16_to_int (__le16 x )
664- {
665- return (signed short )le16_to_cpu (x );
666- }
667-
668720static void report_finger_data (struct input_dev * input , int slot ,
669721 const struct input_mt_pos * pos ,
670722 const struct tp_finger * f )
@@ -971,6 +1023,7 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
9711023{
9721024 int error ;
9731025 int mt_flags = 0 ;
1026+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
9741027
9751028 __set_bit (INPUT_PROP_BUTTONPAD , input -> propbit );
9761029 __clear_bit (BTN_0 , input -> keybit );
@@ -1036,6 +1089,18 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
10361089 if (error )
10371090 return error ;
10381091
1092+ /*
1093+ * Override the default input->open function to send the MT
1094+ * enable every time the device is opened. This ensures it works
1095+ * even if we missed a reset event due to the device being closed.
1096+ * input->close is overridden for symmetry.
1097+ *
1098+ * This also takes care of the dimensions query.
1099+ */
1100+ input -> open = magicmouse_open ;
1101+ input -> close = magicmouse_close ;
1102+ msc -> query_dimensions = true;
1103+
10391104 return 0 ;
10401105}
10411106
@@ -1046,15 +1111,6 @@ static int magicmouse_setup_input_spi(struct input_dev *input,
10461111 if (ret )
10471112 return ret ;
10481113
1049- /*
1050- * Override the default input->open function to send the MT
1051- * enable every time the device is opened. This ensures it works
1052- * even if we missed a reset event due to the device being closed.
1053- * input->close is overridden for symmetry.
1054- */
1055- input -> open = magicmouse_open ;
1056- input -> close = magicmouse_close ;
1057-
10581114 return 0 ;
10591115}
10601116
0 commit comments