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