@@ -113,6 +113,18 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
113113#define TRACKPAD2_RES_Y \
114114 ((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
115115
116+ #define J314_TP_DIMENSION_X (float)13000
117+ #define J314_TP_MIN_X -5900
118+ #define J314_TP_MAX_X 6500
119+ #define J314_TP_RES_X \
120+ ((J314_TP_MAX_X - J314_TP_MIN_X) / (J314_TP_DIMENSION_X / 100))
121+ #define J314_TP_DIMENSION_Y (float)8100
122+ #define J314_TP_MIN_Y -200
123+ #define J314_TP_MAX_Y 7400
124+ #define J314_TP_RES_Y \
125+ ((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100))
126+
127+ #define J314_TP_MAX_FINGER_ORIENTATION 16384
116128
117129struct magicmouse_input_ops {
118130 int (* raw_event )(struct hid_device * hdev ,
@@ -524,6 +536,157 @@ static int magicmouse_raw_event_usb(struct hid_device *hdev,
524536 return 1 ;
525537}
526538
539+ /**
540+ * struct tp_finger - single trackpad finger structure, le16-aligned
541+ *
542+ * @unknown1: unknown
543+ * @unknown2: unknown
544+ * @abs_x: absolute x coordinate
545+ * @abs_y: absolute y coordinate
546+ * @rel_x: relative x coordinate
547+ * @rel_y: relative y coordinate
548+ * @tool_major: tool area, major axis
549+ * @tool_minor: tool area, minor axis
550+ * @orientation: 16384 when point, else 15 bit angle
551+ * @touch_major: touch area, major axis
552+ * @touch_minor: touch area, minor axis
553+ * @unused: zeros
554+ * @pressure: pressure on forcetouch touchpad
555+ * @multi: one finger: varies, more fingers: constant
556+ * @crc16: on last finger: crc over the whole message struct
557+ * (i.e. message header + this struct) minus the last
558+ * @crc16 field; unknown on all other fingers.
559+ */
560+ struct tp_finger {
561+ __le16 unknown1 ;
562+ __le16 unknown2 ;
563+ __le16 abs_x ;
564+ __le16 abs_y ;
565+ __le16 rel_x ;
566+ __le16 rel_y ;
567+ __le16 tool_major ;
568+ __le16 tool_minor ;
569+ __le16 orientation ;
570+ __le16 touch_major ;
571+ __le16 touch_minor ;
572+ __le16 unused [2 ];
573+ __le16 pressure ;
574+ __le16 multi ;
575+ } __attribute__((packed , aligned (2 )));
576+
577+ /**
578+ * struct trackpad report
579+ *
580+ * @report_id: reportid
581+ * @buttons: HID Usage Buttons 3 1-bit reports
582+ * @num_fingers: the number of fingers being reported in @fingers
583+ * @clicked: same as @buttons
584+ */
585+ struct tp_header {
586+ // HID mouse report
587+ u8 report_id ;
588+ u8 buttons ;
589+ u8 rel_x ;
590+ u8 rel_y ;
591+ u8 padding [4 ];
592+ // HID vendor part, up to 1751 bytes
593+ u8 unknown [22 ];
594+ u8 num_fingers ;
595+ u8 clicked ;
596+ u8 unknown3 [14 ];
597+ };
598+
599+ static inline int le16_to_int (__le16 x )
600+ {
601+ return (signed short )le16_to_cpu (x );
602+ }
603+
604+ static void report_finger_data (struct input_dev * input , int slot ,
605+ const struct input_mt_pos * pos ,
606+ const struct tp_finger * f )
607+ {
608+ input_mt_slot (input , slot );
609+ input_mt_report_slot_state (input , MT_TOOL_FINGER , true);
610+
611+ input_report_abs (input , ABS_MT_TOUCH_MAJOR ,
612+ le16_to_int (f -> touch_major ) << 1 );
613+ input_report_abs (input , ABS_MT_TOUCH_MINOR ,
614+ le16_to_int (f -> touch_minor ) << 1 );
615+ input_report_abs (input , ABS_MT_WIDTH_MAJOR ,
616+ le16_to_int (f -> tool_major ) << 1 );
617+ input_report_abs (input , ABS_MT_WIDTH_MINOR ,
618+ le16_to_int (f -> tool_minor ) << 1 );
619+ input_report_abs (input , ABS_MT_ORIENTATION ,
620+ J314_TP_MAX_FINGER_ORIENTATION - le16_to_int (f -> orientation ));
621+ input_report_abs (input , ABS_MT_PRESSURE , le16_to_int (f -> pressure ));
622+ input_report_abs (input , ABS_MT_POSITION_X , pos -> x );
623+ input_report_abs (input , ABS_MT_POSITION_Y , pos -> y );
624+ }
625+
626+ static int magicmouse_raw_event_spi (struct hid_device * hdev ,
627+ struct hid_report * report , u8 * data , int size )
628+ {
629+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
630+ struct input_dev * input = msc -> input ;
631+ struct tp_header * tp_hdr ;
632+ struct tp_finger * f ;
633+ int i , n ;
634+ u32 npoints ;
635+ const size_t hdr_sz = sizeof (struct tp_header );
636+ const size_t touch_sz = sizeof (struct tp_finger );
637+ u8 map_contacs [MAX_CONTACTS ];
638+
639+ // hid_warn(hdev, "%s\n", __func__);
640+ // print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
641+ // size, false);
642+
643+ if (data [0 ] != TRACKPAD2_USB_REPORT_ID )
644+ return 0 ;
645+
646+ /* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
647+ if (size < hdr_sz || ((size - hdr_sz ) % touch_sz ) != 0 )
648+ return 0 ;
649+
650+ tp_hdr = (struct tp_header * )data ;
651+
652+ npoints = (size - hdr_sz ) / touch_sz ;
653+ if (npoints < tp_hdr -> num_fingers || npoints > MAX_CONTACTS ) {
654+ hid_warn (hdev ,
655+ "unexpected number of touches (%u) for "
656+ "report\n" ,
657+ npoints );
658+ return 0 ;
659+ }
660+
661+ n = 0 ;
662+ for (i = 0 ; i < tp_hdr -> num_fingers ; i ++ ) {
663+ f = (struct tp_finger * )(data + hdr_sz + i * touch_sz );
664+ if (le16_to_int (f -> touch_major ) == 0 )
665+ continue ;
666+
667+ hid_dbg (hdev , "ev x:%04x y:%04x\n" , le16_to_int (f -> abs_x ),
668+ le16_to_int (f -> abs_y ));
669+ msc -> pos [n ].x = le16_to_int (f -> abs_x );
670+ msc -> pos [n ].y = - le16_to_int (f -> abs_y );
671+ map_contacs [n ] = i ;
672+ n ++ ;
673+ }
674+
675+ input_mt_assign_slots (input , msc -> tracking_ids , msc -> pos , n , 0 );
676+
677+ for (i = 0 ; i < n ; i ++ ) {
678+ int idx = map_contacs [i ];
679+ f = (struct tp_finger * )(data + hdr_sz + idx * touch_sz );
680+ report_finger_data (input , msc -> tracking_ids [i ], & msc -> pos [i ], f );
681+ }
682+
683+ input_mt_sync_frame (input );
684+ input_report_key (input , BTN_MOUSE , data [1 ] & 1 );
685+
686+ input_sync (input );
687+ return 1 ;
688+ }
689+
527690static int magicmouse_event (struct hid_device * hdev , struct hid_field * field ,
528691 struct hid_usage * usage , __s32 value )
529692{
@@ -703,6 +866,79 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
703866 return 0 ;
704867}
705868
869+ static int magicmouse_setup_input_spi (struct input_dev * input ,
870+ struct hid_device * hdev )
871+ {
872+ int error ;
873+ int mt_flags = 0 ;
874+
875+ __set_bit (INPUT_PROP_BUTTONPAD , input -> propbit );
876+ __clear_bit (BTN_0 , input -> keybit );
877+ __clear_bit (BTN_RIGHT , input -> keybit );
878+ __clear_bit (BTN_MIDDLE , input -> keybit );
879+ __clear_bit (EV_REL , input -> evbit );
880+ __clear_bit (REL_X , input -> relbit );
881+ __clear_bit (REL_Y , input -> relbit );
882+
883+ mt_flags = INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK ;
884+
885+ /* finger touch area */
886+ input_set_abs_params (input , ABS_MT_TOUCH_MAJOR , 0 , 5000 , 0 , 0 );
887+ input_set_abs_params (input , ABS_MT_TOUCH_MINOR , 0 , 5000 , 0 , 0 );
888+
889+ /* finger approach area */
890+ input_set_abs_params (input , ABS_MT_WIDTH_MAJOR , 0 , 5000 , 0 , 0 );
891+ input_set_abs_params (input , ABS_MT_WIDTH_MINOR , 0 , 5000 , 0 , 0 );
892+
893+ /* Note: Touch Y position from the device is inverted relative
894+ * to how pointer motion is reported (and relative to how USB
895+ * HID recommends the coordinates work). This driver keeps
896+ * the origin at the same position, and just uses the additive
897+ * inverse of the reported Y.
898+ */
899+
900+ input_set_abs_params (input , ABS_MT_PRESSURE , 0 , 6000 , 0 , 0 );
901+
902+ /*
903+ * This makes libinput recognize this as a PressurePad and
904+ * stop trying to use pressure for touch size. Pressure unit
905+ * seems to be ~grams on these touchpads.
906+ */
907+ input_abs_set_res (input , ABS_MT_PRESSURE , 1 );
908+
909+ /* finger orientation */
910+ input_set_abs_params (input , ABS_MT_ORIENTATION , - J314_TP_MAX_FINGER_ORIENTATION ,
911+ J314_TP_MAX_FINGER_ORIENTATION , 0 , 0 );
912+
913+ /* finger position */
914+ input_set_abs_params (input , ABS_MT_POSITION_X , J314_TP_MIN_X , J314_TP_MAX_X ,
915+ 0 , 0 );
916+ /* Y axis is inverted */
917+ input_set_abs_params (input , ABS_MT_POSITION_Y , - J314_TP_MAX_Y , - J314_TP_MIN_Y ,
918+ 0 , 0 );
919+
920+ /* X/Y resolution */
921+ input_abs_set_res (input , ABS_MT_POSITION_X , J314_TP_RES_X );
922+ input_abs_set_res (input , ABS_MT_POSITION_Y , J314_TP_RES_Y );
923+
924+ input_set_events_per_packet (input , 60 );
925+
926+ /* touchpad button */
927+ input_set_capability (input , EV_KEY , BTN_MOUSE );
928+
929+ /*
930+ * hid-input may mark device as using autorepeat, but the trackpad does
931+ * not actually want it.
932+ */
933+ __clear_bit (EV_REP , input -> evbit );
934+
935+ error = input_mt_init_slots (input , MAX_CONTACTS , mt_flags );
936+ if (error )
937+ return error ;
938+
939+ return 0 ;
940+ }
941+
706942static int magicmouse_input_mapping (struct hid_device * hdev ,
707943 struct hid_input * hi , struct hid_field * field ,
708944 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -758,6 +994,9 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
758994 feature_size = sizeof (feature_mt_trackpad2_usb );
759995 feature = feature_mt_trackpad2_usb ;
760996 }
997+ } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
998+ feature_size = sizeof (feature_mt_trackpad2_usb );
999+ feature = feature_mt_trackpad2_usb ;
7611000 } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
7621001 feature_size = sizeof (feature_mt_mouse2 );
7631002 feature = feature_mt_mouse2 ;
@@ -832,14 +1071,26 @@ static int magicmouse_probe(struct hid_device *hdev,
8321071 struct hid_report * report ;
8331072 int ret ;
8341073
1074+ if (id -> bus == BUS_SPI && id -> vendor == SPI_VENDOR_ID_APPLE &&
1075+ hdev -> type != HID_TYPE_SPI_MOUSE )
1076+ return - ENODEV ;
1077+
8351078 msc = devm_kzalloc (& hdev -> dev , sizeof (* msc ), GFP_KERNEL );
8361079 if (msc == NULL ) {
8371080 hid_err (hdev , "can't alloc magicmouse descriptor\n" );
8381081 return - ENOMEM ;
8391082 }
8401083
841- msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
842- msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1084+ // internal trackpad use a data format use input ops to avoid
1085+ // conflicts with the report ID.
1086+ if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1087+ msc -> input_ops .raw_event = magicmouse_raw_event_spi ;
1088+ msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
1089+
1090+ } else {
1091+ msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
1092+ msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1093+ }
8431094
8441095 msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
8451096 msc -> hdev = hdev ;
@@ -889,6 +1140,8 @@ static int magicmouse_probe(struct hid_device *hdev,
8891140 else /* USB_VENDOR_ID_APPLE */
8901141 report = hid_register_report (hdev , HID_INPUT_REPORT ,
8911142 TRACKPAD2_USB_REPORT_ID , 0 );
1143+ } else if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1144+ report = hid_register_report (hdev , HID_INPUT_REPORT , 2 , 0 );
8921145 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
8931146 report = hid_register_report (hdev , HID_INPUT_REPORT ,
8941147 TRACKPAD_REPORT_ID , 0 );
@@ -983,6 +1236,8 @@ static const struct hid_device_id magic_mice[] = {
9831236 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ), .driver_data = 0 },
9841237 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,
9851238 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ), .driver_data = 0 },
1239+ { HID_SPI_DEVICE (SPI_VENDOR_ID_APPLE , HID_ANY_ID ),
1240+ .driver_data = 0 },
9861241 { }
9871242};
9881243MODULE_DEVICE_TABLE (hid , magic_mice );
0 commit comments