1616#include <linux/input/mt.h>
1717#include <linux/module.h>
1818#include <linux/slab.h>
19+ #include <linux/workqueue.h>
1920
2021#include "hid-ids.h"
2122
@@ -54,6 +55,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
5455#define TRACKPAD2_USB_REPORT_ID 0x02
5556#define TRACKPAD2_BT_REPORT_ID 0x31
5657#define MOUSE_REPORT_ID 0x29
58+ #define MOUSE2_REPORT_ID 0x12
5759#define DOUBLE_REPORT_ID 0xf7
5860/* These definitions are not precise, but they're close enough. (Bits
5961 * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
@@ -127,6 +129,9 @@ struct magicmouse_sc {
127129 u8 size ;
128130 } touches [16 ];
129131 int tracking_ids [16 ];
132+
133+ struct hid_device * hdev ;
134+ struct delayed_work work ;
130135};
131136
132137static int magicmouse_firm_touch (struct magicmouse_sc * msc )
@@ -195,7 +200,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
195200 int id , x , y , size , orientation , touch_major , touch_minor , state , down ;
196201 int pressure = 0 ;
197202
198- if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ) {
203+ if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
204+ input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
199205 id = (tdata [6 ] << 2 | tdata [5 ] >> 6 ) & 0xf ;
200206 x = (tdata [1 ] << 28 | tdata [0 ] << 20 ) >> 20 ;
201207 y = - ((tdata [2 ] << 24 | tdata [1 ] << 16 ) >> 20 );
@@ -296,7 +302,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
296302 input_report_abs (input , ABS_MT_PRESSURE , pressure );
297303
298304 if (report_undeciphered ) {
299- if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE )
305+ if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
306+ input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 )
300307 input_event (input , EV_MSC , MSC_RAW , tdata [7 ]);
301308 else if (input -> id .product !=
302309 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 )
@@ -380,6 +387,34 @@ static int magicmouse_raw_event(struct hid_device *hdev,
380387 * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
381388 */
382389 break ;
390+ case MOUSE2_REPORT_ID :
391+ /* Size is either 8 or (14 + 8 * N) */
392+ if (size != 8 && (size < 14 || (size - 14 ) % 8 != 0 ))
393+ return 0 ;
394+ npoints = (size - 14 ) / 8 ;
395+ if (npoints > 15 ) {
396+ hid_warn (hdev , "invalid size value (%d) for MOUSE2_REPORT_ID\n" ,
397+ size );
398+ return 0 ;
399+ }
400+ msc -> ntouches = 0 ;
401+ for (ii = 0 ; ii < npoints ; ii ++ )
402+ magicmouse_emit_touch (msc , ii , data + ii * 8 + 14 );
403+
404+ /* When emulating three-button mode, it is important
405+ * to have the current touch information before
406+ * generating a click event.
407+ */
408+ x = (int )((data [3 ] << 24 ) | (data [2 ] << 16 )) >> 16 ;
409+ y = (int )((data [5 ] << 24 ) | (data [4 ] << 16 )) >> 16 ;
410+ clicks = data [1 ];
411+
412+ /* The following bits provide a device specific timestamp. They
413+ * are unused here.
414+ *
415+ * ts = data[11] >> 6 | data[12] << 2 | data[13] << 10;
416+ */
417+ break ;
383418 case DOUBLE_REPORT_ID :
384419 /* Sometimes the trackpad sends two touch reports in one
385420 * packet.
@@ -392,7 +427,8 @@ static int magicmouse_raw_event(struct hid_device *hdev,
392427 return 0 ;
393428 }
394429
395- if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ) {
430+ if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
431+ input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
396432 magicmouse_emit_buttons (msc , clicks & 3 );
397433 input_report_rel (input , REL_X , x );
398434 input_report_rel (input , REL_Y , y );
@@ -408,14 +444,32 @@ static int magicmouse_raw_event(struct hid_device *hdev,
408444 return 1 ;
409445}
410446
447+ static int magicmouse_event (struct hid_device * hdev , struct hid_field * field ,
448+ struct hid_usage * usage , __s32 value )
449+ {
450+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
451+ if (msc -> input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
452+ field -> report -> id == MOUSE2_REPORT_ID ) {
453+ /*
454+ * magic_mouse_raw_event has done all the work. Skip hidinput.
455+ *
456+ * Specifically, hidinput may modify BTN_LEFT and BTN_RIGHT,
457+ * breaking emulate_3button.
458+ */
459+ return 1 ;
460+ }
461+ return 0 ;
462+ }
463+
411464static int magicmouse_setup_input (struct input_dev * input , struct hid_device * hdev )
412465{
413466 int error ;
414467 int mt_flags = 0 ;
415468
416469 __set_bit (EV_KEY , input -> evbit );
417470
418- if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ) {
471+ if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
472+ input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
419473 __set_bit (BTN_LEFT , input -> keybit );
420474 __set_bit (BTN_RIGHT , input -> keybit );
421475 if (emulate_3button )
@@ -480,7 +534,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
480534 * the origin at the same position, and just uses the additive
481535 * inverse of the reported Y.
482536 */
483- if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ) {
537+ if (input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
538+ input -> id .product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
484539 input_set_abs_params (input , ABS_MT_ORIENTATION , -31 , 32 , 1 , 0 );
485540 input_set_abs_params (input , ABS_MT_POSITION_X ,
486541 MOUSE_MIN_X , MOUSE_MAX_X , 4 , 0 );
@@ -580,19 +635,60 @@ static int magicmouse_input_configured(struct hid_device *hdev,
580635 return 0 ;
581636}
582637
583-
584- static int magicmouse_probe (struct hid_device * hdev ,
585- const struct hid_device_id * id )
638+ static int magicmouse_enable_multitouch (struct hid_device * hdev )
586639{
587640 const u8 * feature ;
588641 const u8 feature_mt [] = { 0xD7 , 0x01 };
642+ const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
589643 const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
590644 const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
591645 u8 * buf ;
646+ int ret ;
647+ int feature_size ;
648+
649+ if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
650+ if (hdev -> vendor == BT_VENDOR_ID_APPLE ) {
651+ feature_size = sizeof (feature_mt_trackpad2_bt );
652+ feature = feature_mt_trackpad2_bt ;
653+ } else { /* USB_VENDOR_ID_APPLE */
654+ feature_size = sizeof (feature_mt_trackpad2_usb );
655+ feature = feature_mt_trackpad2_usb ;
656+ }
657+ } else if (hdev -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
658+ feature_size = sizeof (feature_mt_mouse2 );
659+ feature = feature_mt_mouse2 ;
660+ } else {
661+ feature_size = sizeof (feature_mt );
662+ feature = feature_mt ;
663+ }
664+
665+ buf = kmemdup (feature , feature_size , GFP_KERNEL );
666+ if (!buf )
667+ return - ENOMEM ;
668+
669+ ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
670+ HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
671+ kfree (buf );
672+ return ret ;
673+ }
674+
675+ static void magicmouse_enable_mt_work (struct work_struct * work )
676+ {
677+ struct magicmouse_sc * msc =
678+ container_of (work , struct magicmouse_sc , work .work );
679+ int ret ;
680+
681+ ret = magicmouse_enable_multitouch (msc -> hdev );
682+ if (ret < 0 )
683+ hid_err (msc -> hdev , "unable to request touch data (%d)\n" , ret );
684+ }
685+
686+ static int magicmouse_probe (struct hid_device * hdev ,
687+ const struct hid_device_id * id )
688+ {
592689 struct magicmouse_sc * msc ;
593690 struct hid_report * report ;
594691 int ret ;
595- int feature_size ;
596692
597693 if (id -> vendor == USB_VENDOR_ID_APPLE &&
598694 id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
@@ -606,6 +702,8 @@ static int magicmouse_probe(struct hid_device *hdev,
606702 }
607703
608704 msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
705+ msc -> hdev = hdev ;
706+ INIT_DEFERRABLE_WORK (& msc -> work , magicmouse_enable_mt_work );
609707
610708 msc -> quirks = id -> driver_data ;
611709 hid_set_drvdata (hdev , msc );
@@ -631,6 +729,9 @@ static int magicmouse_probe(struct hid_device *hdev,
631729 if (id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE )
632730 report = hid_register_report (hdev , HID_INPUT_REPORT ,
633731 MOUSE_REPORT_ID , 0 );
732+ else if (id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 )
733+ report = hid_register_report (hdev , HID_INPUT_REPORT ,
734+ MOUSE2_REPORT_ID , 0 );
634735 else if (id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
635736 if (id -> vendor == BT_VENDOR_ID_APPLE )
636737 report = hid_register_report (hdev , HID_INPUT_REPORT ,
@@ -652,25 +753,6 @@ static int magicmouse_probe(struct hid_device *hdev,
652753 }
653754 report -> size = 6 ;
654755
655- if (id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
656- if (id -> vendor == BT_VENDOR_ID_APPLE ) {
657- feature_size = sizeof (feature_mt_trackpad2_bt );
658- feature = feature_mt_trackpad2_bt ;
659- } else { /* USB_VENDOR_ID_APPLE */
660- feature_size = sizeof (feature_mt_trackpad2_usb );
661- feature = feature_mt_trackpad2_usb ;
662- }
663- } else {
664- feature_size = sizeof (feature_mt );
665- feature = feature_mt ;
666- }
667-
668- buf = kmemdup (feature , feature_size , GFP_KERNEL );
669- if (!buf ) {
670- ret = - ENOMEM ;
671- goto err_stop_hw ;
672- }
673-
674756 /*
675757 * Some devices repond with 'invalid report id' when feature
676758 * report switching it into multitouch mode is sent to it.
@@ -679,23 +761,33 @@ static int magicmouse_probe(struct hid_device *hdev,
679761 * but there seems to be no other way of switching the mode.
680762 * Thus the super-ugly hacky success check below.
681763 */
682- ret = hid_hw_raw_request (hdev , buf [0 ], buf , feature_size ,
683- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
684- kfree (buf );
685- if (ret != - EIO && ret != feature_size ) {
764+ ret = magicmouse_enable_multitouch (hdev );
765+ if (ret != - EIO && ret < 0 ) {
686766 hid_err (hdev , "unable to request touch data (%d)\n" , ret );
687767 goto err_stop_hw ;
688768 }
769+ if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
770+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
771+ }
689772
690773 return 0 ;
691774err_stop_hw :
692775 hid_hw_stop (hdev );
693776 return ret ;
694777}
695778
779+ static void magicmouse_remove (struct hid_device * hdev )
780+ {
781+ struct magicmouse_sc * msc = hid_get_drvdata (hdev );
782+ cancel_delayed_work_sync (& msc -> work );
783+ hid_hw_stop (hdev );
784+ }
785+
696786static const struct hid_device_id magic_mice [] = {
697787 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
698788 USB_DEVICE_ID_APPLE_MAGICMOUSE ), .driver_data = 0 },
789+ { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE ,
790+ USB_DEVICE_ID_APPLE_MAGICMOUSE2 ), .driver_data = 0 },
699791 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
700792 USB_DEVICE_ID_APPLE_MAGICTRACKPAD ), .driver_data = 0 },
701793 { HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE ,
@@ -710,7 +802,9 @@ static struct hid_driver magicmouse_driver = {
710802 .name = "magicmouse" ,
711803 .id_table = magic_mice ,
712804 .probe = magicmouse_probe ,
805+ .remove = magicmouse_remove ,
713806 .raw_event = magicmouse_raw_event ,
807+ .event = magicmouse_event ,
714808 .input_mapping = magicmouse_input_mapping ,
715809 .input_configured = magicmouse_input_configured ,
716810};
0 commit comments