@@ -114,6 +114,18 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
114114#define TRACKPAD2_RES_Y \
115115 ((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
116116
117+ #define J314_TP_DIMENSION_X (float)13000
118+ #define J314_TP_MIN_X -5900
119+ #define J314_TP_MAX_X 6500
120+ #define J314_TP_RES_X \
121+ ((J314_TP_MAX_X - J314_TP_MIN_X) / (J314_TP_DIMENSION_X / 100))
122+ #define J314_TP_DIMENSION_Y (float)8100
123+ #define J314_TP_MIN_Y -200
124+ #define J314_TP_MAX_Y 7400
125+ #define J314_TP_RES_Y \
126+ ((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100))
127+
128+ #define J314_TP_MAX_FINGER_ORIENTATION 16384
117129
118130struct magicmouse_input_ops {
119131 int (* raw_event )(struct hid_device * hdev ,
@@ -534,6 +546,157 @@ static int magicmouse_raw_event_usb(struct hid_device *hdev,
534546 return 1 ;
535547}
536548
549+ /**
550+ * struct tp_finger - single trackpad finger structure, le16-aligned
551+ *
552+ * @unknown1: unknown
553+ * @unknown2: unknown
554+ * @abs_x: absolute x coordinate
555+ * @abs_y: absolute y coordinate
556+ * @rel_x: relative x coordinate
557+ * @rel_y: relative y coordinate
558+ * @tool_major: tool area, major axis
559+ * @tool_minor: tool area, minor axis
560+ * @orientation: 16384 when point, else 15 bit angle
561+ * @touch_major: touch area, major axis
562+ * @touch_minor: touch area, minor axis
563+ * @unused: zeros
564+ * @pressure: pressure on forcetouch touchpad
565+ * @multi: one finger: varies, more fingers: constant
566+ * @crc16: on last finger: crc over the whole message struct
567+ * (i.e. message header + this struct) minus the last
568+ * @crc16 field; unknown on all other fingers.
569+ */
570+ struct tp_finger {
571+ __le16 unknown1 ;
572+ __le16 unknown2 ;
573+ __le16 abs_x ;
574+ __le16 abs_y ;
575+ __le16 rel_x ;
576+ __le16 rel_y ;
577+ __le16 tool_major ;
578+ __le16 tool_minor ;
579+ __le16 orientation ;
580+ __le16 touch_major ;
581+ __le16 touch_minor ;
582+ __le16 unused [2 ];
583+ __le16 pressure ;
584+ __le16 multi ;
585+ } __attribute__((packed , aligned (2 )));
586+
587+ /**
588+ * struct trackpad report
589+ *
590+ * @report_id: reportid
591+ * @buttons: HID Usage Buttons 3 1-bit reports
592+ * @num_fingers: the number of fingers being reported in @fingers
593+ * @clicked: same as @buttons
594+ */
595+ struct tp_header {
596+ // HID mouse report
597+ u8 report_id ;
598+ u8 buttons ;
599+ u8 rel_x ;
600+ u8 rel_y ;
601+ u8 padding [4 ];
602+ // HID vendor part, up to 1751 bytes
603+ u8 unknown [22 ];
604+ u8 num_fingers ;
605+ u8 clicked ;
606+ u8 unknown3 [14 ];
607+ };
608+
609+ static inline int le16_to_int (__le16 x )
610+ {
611+ return (signed short )le16_to_cpu (x );
612+ }
613+
614+ static void report_finger_data (struct input_dev * input , int slot ,
615+ const struct input_mt_pos * pos ,
616+ const struct tp_finger * f )
617+ {
618+ input_mt_slot (input , slot );
619+ input_mt_report_slot_state (input , MT_TOOL_FINGER , true);
620+
621+ input_report_abs (input , ABS_MT_TOUCH_MAJOR ,
622+ le16_to_int (f -> touch_major ) << 1 );
623+ input_report_abs (input , ABS_MT_TOUCH_MINOR ,
624+ le16_to_int (f -> touch_minor ) << 1 );
625+ input_report_abs (input , ABS_MT_WIDTH_MAJOR ,
626+ le16_to_int (f -> tool_major ) << 1 );
627+ input_report_abs (input , ABS_MT_WIDTH_MINOR ,
628+ le16_to_int (f -> tool_minor ) << 1 );
629+ input_report_abs (input , ABS_MT_ORIENTATION ,
630+ J314_TP_MAX_FINGER_ORIENTATION - le16_to_int (f -> orientation ));
631+ input_report_abs (input , ABS_MT_PRESSURE , le16_to_int (f -> pressure ));
632+ input_report_abs (input , ABS_MT_POSITION_X , pos -> x );
633+ input_report_abs (input , ABS_MT_POSITION_Y , pos -> y );
634+ }
635+
636+ static int magicmouse_raw_event_spi (struct hid_device * hdev ,
637+ struct hid_report * report , u8 * data , int size )
638+ {
639+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
640+ struct input_dev * input = msc -> input ;
641+ struct tp_header * tp_hdr ;
642+ struct tp_finger * f ;
643+ int i , n ;
644+ u32 npoints ;
645+ const size_t hdr_sz = sizeof (struct tp_header );
646+ const size_t touch_sz = sizeof (struct tp_finger );
647+ u8 map_contacs [MAX_CONTACTS ];
648+
649+ // hid_warn(hdev, "%s\n", __func__);
650+ // print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
651+ // size, false);
652+
653+ if (data [0 ] != TRACKPAD2_USB_REPORT_ID )
654+ return 0 ;
655+
656+ /* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
657+ if (size < hdr_sz || ((size - hdr_sz ) % touch_sz ) != 0 )
658+ return 0 ;
659+
660+ tp_hdr = (struct tp_header * )data ;
661+
662+ npoints = (size - hdr_sz ) / touch_sz ;
663+ if (npoints < tp_hdr -> num_fingers || npoints > MAX_CONTACTS ) {
664+ hid_warn (hdev ,
665+ "unexpected number of touches (%u) for "
666+ "report\n" ,
667+ npoints );
668+ return 0 ;
669+ }
670+
671+ n = 0 ;
672+ for (i = 0 ; i < tp_hdr -> num_fingers ; i ++ ) {
673+ f = (struct tp_finger * )(data + hdr_sz + i * touch_sz );
674+ if (le16_to_int (f -> touch_major ) == 0 )
675+ continue ;
676+
677+ hid_dbg (hdev , "ev x:%04x y:%04x\n" , le16_to_int (f -> abs_x ),
678+ le16_to_int (f -> abs_y ));
679+ msc -> pos [n ].x = le16_to_int (f -> abs_x );
680+ msc -> pos [n ].y = - le16_to_int (f -> abs_y );
681+ map_contacs [n ] = i ;
682+ n ++ ;
683+ }
684+
685+ input_mt_assign_slots (input , msc -> tracking_ids , msc -> pos , n , 0 );
686+
687+ for (i = 0 ; i < n ; i ++ ) {
688+ int idx = map_contacs [i ];
689+ f = (struct tp_finger * )(data + hdr_sz + idx * touch_sz );
690+ report_finger_data (input , msc -> tracking_ids [i ], & msc -> pos [i ], f );
691+ }
692+
693+ input_mt_sync_frame (input );
694+ input_report_key (input , BTN_MOUSE , data [1 ] & 1 );
695+
696+ input_sync (input );
697+ return 1 ;
698+ }
699+
537700static int magicmouse_event (struct hid_device * hdev , struct hid_field * field ,
538701 struct hid_usage * usage , __s32 value )
539702{
@@ -721,6 +884,79 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
721884 return 0 ;
722885}
723886
887+ static int magicmouse_setup_input_spi (struct input_dev * input ,
888+ struct hid_device * hdev )
889+ {
890+ int error ;
891+ int mt_flags = 0 ;
892+
893+ __set_bit (INPUT_PROP_BUTTONPAD , input -> propbit );
894+ __clear_bit (BTN_0 , input -> keybit );
895+ __clear_bit (BTN_RIGHT , input -> keybit );
896+ __clear_bit (BTN_MIDDLE , input -> keybit );
897+ __clear_bit (EV_REL , input -> evbit );
898+ __clear_bit (REL_X , input -> relbit );
899+ __clear_bit (REL_Y , input -> relbit );
900+
901+ mt_flags = INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK ;
902+
903+ /* finger touch area */
904+ input_set_abs_params (input , ABS_MT_TOUCH_MAJOR , 0 , 5000 , 0 , 0 );
905+ input_set_abs_params (input , ABS_MT_TOUCH_MINOR , 0 , 5000 , 0 , 0 );
906+
907+ /* finger approach area */
908+ input_set_abs_params (input , ABS_MT_WIDTH_MAJOR , 0 , 5000 , 0 , 0 );
909+ input_set_abs_params (input , ABS_MT_WIDTH_MINOR , 0 , 5000 , 0 , 0 );
910+
911+ /* Note: Touch Y position from the device is inverted relative
912+ * to how pointer motion is reported (and relative to how USB
913+ * HID recommends the coordinates work). This driver keeps
914+ * the origin at the same position, and just uses the additive
915+ * inverse of the reported Y.
916+ */
917+
918+ input_set_abs_params (input , ABS_MT_PRESSURE , 0 , 6000 , 0 , 0 );
919+
920+ /*
921+ * This makes libinput recognize this as a PressurePad and
922+ * stop trying to use pressure for touch size. Pressure unit
923+ * seems to be ~grams on these touchpads.
924+ */
925+ input_abs_set_res (input , ABS_MT_PRESSURE , 1 );
926+
927+ /* finger orientation */
928+ input_set_abs_params (input , ABS_MT_ORIENTATION , - J314_TP_MAX_FINGER_ORIENTATION ,
929+ J314_TP_MAX_FINGER_ORIENTATION , 0 , 0 );
930+
931+ /* finger position */
932+ input_set_abs_params (input , ABS_MT_POSITION_X , J314_TP_MIN_X , J314_TP_MAX_X ,
933+ 0 , 0 );
934+ /* Y axis is inverted */
935+ input_set_abs_params (input , ABS_MT_POSITION_Y , - J314_TP_MAX_Y , - J314_TP_MIN_Y ,
936+ 0 , 0 );
937+
938+ /* X/Y resolution */
939+ input_abs_set_res (input , ABS_MT_POSITION_X , J314_TP_RES_X );
940+ input_abs_set_res (input , ABS_MT_POSITION_Y , J314_TP_RES_Y );
941+
942+ input_set_events_per_packet (input , 60 );
943+
944+ /* touchpad button */
945+ input_set_capability (input , EV_KEY , BTN_MOUSE );
946+
947+ /*
948+ * hid-input may mark device as using autorepeat, but the trackpad does
949+ * not actually want it.
950+ */
951+ __clear_bit (EV_REP , input -> evbit );
952+
953+ error = input_mt_init_slots (input , MAX_CONTACTS , mt_flags );
954+ if (error )
955+ return error ;
956+
957+ return 0 ;
958+ }
959+
724960static int magicmouse_input_mapping (struct hid_device * hdev ,
725961 struct hid_input * hi , struct hid_field * field ,
726962 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -779,6 +1015,9 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
7791015 feature_size = sizeof (feature_mt_trackpad2_usb );
7801016 feature = feature_mt_trackpad2_usb ;
7811017 }
1018+ } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
1019+ feature_size = sizeof (feature_mt_trackpad2_usb );
1020+ feature = feature_mt_trackpad2_usb ;
7821021 } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
7831022 feature_size = sizeof (feature_mt_mouse2 );
7841023 feature = feature_mt_mouse2 ;
@@ -854,14 +1093,26 @@ static int magicmouse_probe(struct hid_device *hdev,
8541093 struct hid_report * report ;
8551094 int ret ;
8561095
1096+ if (id -> bus == BUS_SPI && id -> vendor == SPI_VENDOR_ID_APPLE &&
1097+ hdev -> type != HID_TYPE_SPI_MOUSE )
1098+ return - ENODEV ;
1099+
8571100 msc = devm_kzalloc (& hdev -> dev , sizeof (* msc ), GFP_KERNEL );
8581101 if (msc == NULL ) {
8591102 hid_err (hdev , "can't alloc magicmouse descriptor\n" );
8601103 return - ENOMEM ;
8611104 }
8621105
863- msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
864- msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1106+ // internal trackpad use a data format use input ops to avoid
1107+ // conflicts with the report ID.
1108+ if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1109+ msc -> input_ops .raw_event = magicmouse_raw_event_spi ;
1110+ msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
1111+
1112+ } else {
1113+ msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
1114+ msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1115+ }
8651116
8661117 msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
8671118 msc -> hdev = hdev ;
@@ -914,6 +1165,8 @@ static int magicmouse_probe(struct hid_device *hdev,
9141165 else /* USB_VENDOR_ID_APPLE */
9151166 report = hid_register_report (hdev , HID_INPUT_REPORT ,
9161167 TRACKPAD2_USB_REPORT_ID , 0 );
1168+ } else if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1169+ report = hid_register_report (hdev , HID_INPUT_REPORT , 2 , 0 );
9171170 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
9181171 report = hid_register_report (hdev , HID_INPUT_REPORT ,
9191172 TRACKPAD_REPORT_ID , 0 );
@@ -1013,6 +1266,8 @@ static const struct hid_device_id magic_mice[] = {
10131266 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ), .driver_data = 0 },
10141267 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,
10151268 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ), .driver_data = 0 },
1269+ { HID_SPI_DEVICE (SPI_VENDOR_ID_APPLE , HID_ANY_ID ),
1270+ .driver_data = 0 },
10161271 { }
10171272};
10181273MODULE_DEVICE_TABLE (hid , magic_mice );
0 commit comments