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