@@ -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 ,
@@ -533,6 +545,157 @@ static int magicmouse_raw_event_usb(struct hid_device *hdev,
533545 return 1 ;
534546}
535547
548+ /**
549+ * struct tp_finger - single trackpad finger structure, le16-aligned
550+ *
551+ * @unknown1: unknown
552+ * @unknown2: unknown
553+ * @abs_x: absolute x coordinate
554+ * @abs_y: absolute y coordinate
555+ * @rel_x: relative x coordinate
556+ * @rel_y: relative y coordinate
557+ * @tool_major: tool area, major axis
558+ * @tool_minor: tool area, minor axis
559+ * @orientation: 16384 when point, else 15 bit angle
560+ * @touch_major: touch area, major axis
561+ * @touch_minor: touch area, minor axis
562+ * @unused: zeros
563+ * @pressure: pressure on forcetouch touchpad
564+ * @multi: one finger: varies, more fingers: constant
565+ * @crc16: on last finger: crc over the whole message struct
566+ * (i.e. message header + this struct) minus the last
567+ * @crc16 field; unknown on all other fingers.
568+ */
569+ struct tp_finger {
570+ __le16 unknown1 ;
571+ __le16 unknown2 ;
572+ __le16 abs_x ;
573+ __le16 abs_y ;
574+ __le16 rel_x ;
575+ __le16 rel_y ;
576+ __le16 tool_major ;
577+ __le16 tool_minor ;
578+ __le16 orientation ;
579+ __le16 touch_major ;
580+ __le16 touch_minor ;
581+ __le16 unused [2 ];
582+ __le16 pressure ;
583+ __le16 multi ;
584+ } __attribute__((packed , aligned (2 )));
585+
586+ /**
587+ * struct trackpad report
588+ *
589+ * @report_id: reportid
590+ * @buttons: HID Usage Buttons 3 1-bit reports
591+ * @num_fingers: the number of fingers being reported in @fingers
592+ * @clicked: same as @buttons
593+ */
594+ struct tp_header {
595+ // HID mouse report
596+ u8 report_id ;
597+ u8 buttons ;
598+ u8 rel_x ;
599+ u8 rel_y ;
600+ u8 padding [4 ];
601+ // HID vendor part, up to 1751 bytes
602+ u8 unknown [22 ];
603+ u8 num_fingers ;
604+ u8 clicked ;
605+ u8 unknown3 [14 ];
606+ };
607+
608+ static inline int le16_to_int (__le16 x )
609+ {
610+ return (signed short )le16_to_cpu (x );
611+ }
612+
613+ static void report_finger_data (struct input_dev * input , int slot ,
614+ const struct input_mt_pos * pos ,
615+ const struct tp_finger * f )
616+ {
617+ input_mt_slot (input , slot );
618+ input_mt_report_slot_state (input , MT_TOOL_FINGER , true);
619+
620+ input_report_abs (input , ABS_MT_TOUCH_MAJOR ,
621+ le16_to_int (f -> touch_major ) << 1 );
622+ input_report_abs (input , ABS_MT_TOUCH_MINOR ,
623+ le16_to_int (f -> touch_minor ) << 1 );
624+ input_report_abs (input , ABS_MT_WIDTH_MAJOR ,
625+ le16_to_int (f -> tool_major ) << 1 );
626+ input_report_abs (input , ABS_MT_WIDTH_MINOR ,
627+ le16_to_int (f -> tool_minor ) << 1 );
628+ input_report_abs (input , ABS_MT_ORIENTATION ,
629+ J314_TP_MAX_FINGER_ORIENTATION - le16_to_int (f -> orientation ));
630+ input_report_abs (input , ABS_MT_PRESSURE , le16_to_int (f -> pressure ));
631+ input_report_abs (input , ABS_MT_POSITION_X , pos -> x );
632+ input_report_abs (input , ABS_MT_POSITION_Y , pos -> y );
633+ }
634+
635+ static int magicmouse_raw_event_spi (struct hid_device * hdev ,
636+ struct hid_report * report , u8 * data , int size )
637+ {
638+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
639+ struct input_dev * input = msc -> input ;
640+ struct tp_header * tp_hdr ;
641+ struct tp_finger * f ;
642+ int i , n ;
643+ u32 npoints ;
644+ const size_t hdr_sz = sizeof (struct tp_header );
645+ const size_t touch_sz = sizeof (struct tp_finger );
646+ u8 map_contacs [MAX_CONTACTS ];
647+
648+ // hid_warn(hdev, "%s\n", __func__);
649+ // print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
650+ // size, false);
651+
652+ if (data [0 ] != TRACKPAD2_USB_REPORT_ID )
653+ return 0 ;
654+
655+ /* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
656+ if (size < hdr_sz || ((size - hdr_sz ) % touch_sz ) != 0 )
657+ return 0 ;
658+
659+ tp_hdr = (struct tp_header * )data ;
660+
661+ npoints = (size - hdr_sz ) / touch_sz ;
662+ if (npoints < tp_hdr -> num_fingers || npoints > MAX_CONTACTS ) {
663+ hid_warn (hdev ,
664+ "unexpected number of touches (%u) for "
665+ "report\n" ,
666+ npoints );
667+ return 0 ;
668+ }
669+
670+ n = 0 ;
671+ for (i = 0 ; i < tp_hdr -> num_fingers ; i ++ ) {
672+ f = (struct tp_finger * )(data + hdr_sz + i * touch_sz );
673+ if (le16_to_int (f -> touch_major ) == 0 )
674+ continue ;
675+
676+ hid_dbg (hdev , "ev x:%04x y:%04x\n" , le16_to_int (f -> abs_x ),
677+ le16_to_int (f -> abs_y ));
678+ msc -> pos [n ].x = le16_to_int (f -> abs_x );
679+ msc -> pos [n ].y = - le16_to_int (f -> abs_y );
680+ map_contacs [n ] = i ;
681+ n ++ ;
682+ }
683+
684+ input_mt_assign_slots (input , msc -> tracking_ids , msc -> pos , n , 0 );
685+
686+ for (i = 0 ; i < n ; i ++ ) {
687+ int idx = map_contacs [i ];
688+ f = (struct tp_finger * )(data + hdr_sz + idx * touch_sz );
689+ report_finger_data (input , msc -> tracking_ids [i ], & msc -> pos [i ], f );
690+ }
691+
692+ input_mt_sync_frame (input );
693+ input_report_key (input , BTN_MOUSE , data [1 ] & 1 );
694+
695+ input_sync (input );
696+ return 1 ;
697+ }
698+
536699static int magicmouse_event (struct hid_device * hdev , struct hid_field * field ,
537700 struct hid_usage * usage , __s32 value )
538701{
@@ -717,6 +880,79 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
717880 return 0 ;
718881}
719882
883+ static int magicmouse_setup_input_spi (struct input_dev * input ,
884+ struct hid_device * hdev )
885+ {
886+ int error ;
887+ int mt_flags = 0 ;
888+
889+ __set_bit (INPUT_PROP_BUTTONPAD , input -> propbit );
890+ __clear_bit (BTN_0 , input -> keybit );
891+ __clear_bit (BTN_RIGHT , input -> keybit );
892+ __clear_bit (BTN_MIDDLE , input -> keybit );
893+ __clear_bit (EV_REL , input -> evbit );
894+ __clear_bit (REL_X , input -> relbit );
895+ __clear_bit (REL_Y , input -> relbit );
896+
897+ mt_flags = INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK ;
898+
899+ /* finger touch area */
900+ input_set_abs_params (input , ABS_MT_TOUCH_MAJOR , 0 , 5000 , 0 , 0 );
901+ input_set_abs_params (input , ABS_MT_TOUCH_MINOR , 0 , 5000 , 0 , 0 );
902+
903+ /* finger approach area */
904+ input_set_abs_params (input , ABS_MT_WIDTH_MAJOR , 0 , 5000 , 0 , 0 );
905+ input_set_abs_params (input , ABS_MT_WIDTH_MINOR , 0 , 5000 , 0 , 0 );
906+
907+ /* Note: Touch Y position from the device is inverted relative
908+ * to how pointer motion is reported (and relative to how USB
909+ * HID recommends the coordinates work). This driver keeps
910+ * the origin at the same position, and just uses the additive
911+ * inverse of the reported Y.
912+ */
913+
914+ input_set_abs_params (input , ABS_MT_PRESSURE , 0 , 6000 , 0 , 0 );
915+
916+ /*
917+ * This makes libinput recognize this as a PressurePad and
918+ * stop trying to use pressure for touch size. Pressure unit
919+ * seems to be ~grams on these touchpads.
920+ */
921+ input_abs_set_res (input , ABS_MT_PRESSURE , 1 );
922+
923+ /* finger orientation */
924+ input_set_abs_params (input , ABS_MT_ORIENTATION , - J314_TP_MAX_FINGER_ORIENTATION ,
925+ J314_TP_MAX_FINGER_ORIENTATION , 0 , 0 );
926+
927+ /* finger position */
928+ input_set_abs_params (input , ABS_MT_POSITION_X , J314_TP_MIN_X , J314_TP_MAX_X ,
929+ 0 , 0 );
930+ /* Y axis is inverted */
931+ input_set_abs_params (input , ABS_MT_POSITION_Y , - J314_TP_MAX_Y , - J314_TP_MIN_Y ,
932+ 0 , 0 );
933+
934+ /* X/Y resolution */
935+ input_abs_set_res (input , ABS_MT_POSITION_X , J314_TP_RES_X );
936+ input_abs_set_res (input , ABS_MT_POSITION_Y , J314_TP_RES_Y );
937+
938+ input_set_events_per_packet (input , 60 );
939+
940+ /* touchpad button */
941+ input_set_capability (input , EV_KEY , BTN_MOUSE );
942+
943+ /*
944+ * hid-input may mark device as using autorepeat, but the trackpad does
945+ * not actually want it.
946+ */
947+ __clear_bit (EV_REP , input -> evbit );
948+
949+ error = input_mt_init_slots (input , MAX_CONTACTS , mt_flags );
950+ if (error )
951+ return error ;
952+
953+ return 0 ;
954+ }
955+
720956static int magicmouse_input_mapping (struct hid_device * hdev ,
721957 struct hid_input * hi , struct hid_field * field ,
722958 struct hid_usage * usage , unsigned long * * bit , int * max )
@@ -775,6 +1011,9 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
7751011 feature_size = sizeof (feature_mt_trackpad2_usb );
7761012 feature = feature_mt_trackpad2_usb ;
7771013 }
1014+ } else if (hdev -> vendor == SPI_VENDOR_ID_APPLE ) {
1015+ feature_size = sizeof (feature_mt_trackpad2_usb );
1016+ feature = feature_mt_trackpad2_usb ;
7781017 } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
7791018 feature_size = sizeof (feature_mt_mouse2 );
7801019 feature = feature_mt_mouse2 ;
@@ -850,14 +1089,26 @@ static int magicmouse_probe(struct hid_device *hdev,
8501089 struct hid_report * report ;
8511090 int ret ;
8521091
1092+ if (id -> bus == BUS_SPI && id -> vendor == SPI_VENDOR_ID_APPLE &&
1093+ hdev -> type != HID_TYPE_SPI_MOUSE )
1094+ return - ENODEV ;
1095+
8531096 msc = devm_kzalloc (& hdev -> dev , sizeof (* msc ), GFP_KERNEL );
8541097 if (msc == NULL ) {
8551098 hid_err (hdev , "can't alloc magicmouse descriptor\n" );
8561099 return - ENOMEM ;
8571100 }
8581101
859- msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
860- msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1102+ // internal trackpad use a data format use input ops to avoid
1103+ // conflicts with the report ID.
1104+ if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1105+ msc -> input_ops .raw_event = magicmouse_raw_event_spi ;
1106+ msc -> input_ops .setup_input = magicmouse_setup_input_spi ;
1107+
1108+ } else {
1109+ msc -> input_ops .raw_event = magicmouse_raw_event_usb ;
1110+ msc -> input_ops .setup_input = magicmouse_setup_input_usb ;
1111+ }
8611112
8621113 msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
8631114 msc -> hdev = hdev ;
@@ -910,6 +1161,8 @@ static int magicmouse_probe(struct hid_device *hdev,
9101161 else /* USB_VENDOR_ID_APPLE */
9111162 report = hid_register_report (hdev , HID_INPUT_REPORT ,
9121163 TRACKPAD2_USB_REPORT_ID , 0 );
1164+ } else if (id -> vendor == SPI_VENDOR_ID_APPLE ) {
1165+ report = hid_register_report (hdev , HID_INPUT_REPORT , 2 , 0 );
9131166 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
9141167 report = hid_register_report (hdev , HID_INPUT_REPORT ,
9151168 TRACKPAD_REPORT_ID , 0 );
@@ -1009,6 +1262,8 @@ static const struct hid_device_id magic_mice[] = {
10091262 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ), .driver_data = 0 },
10101263 { HID_USB_DEVICE (USB_VENDOR_ID_APPLE ,
10111264 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC ), .driver_data = 0 },
1265+ { HID_SPI_DEVICE (SPI_VENDOR_ID_APPLE , HID_ANY_ID ),
1266+ .driver_data = 0 },
10121267 { }
10131268};
10141269MODULE_DEVICE_TABLE (hid , magic_mice );
0 commit comments