16
16
#include <linux/input/mt.h>
17
17
#include <linux/module.h>
18
18
#include <linux/slab.h>
19
+ #include <linux/workqueue.h>
19
20
20
21
#include "hid-ids.h"
21
22
@@ -54,6 +55,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
54
55
#define TRACKPAD2_USB_REPORT_ID 0x02
55
56
#define TRACKPAD2_BT_REPORT_ID 0x31
56
57
#define MOUSE_REPORT_ID 0x29
58
+ #define MOUSE2_REPORT_ID 0x12
57
59
#define DOUBLE_REPORT_ID 0xf7
58
60
/* These definitions are not precise, but they're close enough. (Bits
59
61
* 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
@@ -127,6 +129,9 @@ struct magicmouse_sc {
127
129
u8 size ;
128
130
} touches [16 ];
129
131
int tracking_ids [16 ];
132
+
133
+ struct hid_device * hdev ;
134
+ struct delayed_work work ;
130
135
};
131
136
132
137
static 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
195
200
int id , x , y , size , orientation , touch_major , touch_minor , state , down ;
196
201
int pressure = 0 ;
197
202
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 ) {
199
205
id = (tdata [6 ] << 2 | tdata [5 ] >> 6 ) & 0xf ;
200
206
x = (tdata [1 ] << 28 | tdata [0 ] << 20 ) >> 20 ;
201
207
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
296
302
input_report_abs (input , ABS_MT_PRESSURE , pressure );
297
303
298
304
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 )
300
307
input_event (input , EV_MSC , MSC_RAW , tdata [7 ]);
301
308
else if (input -> id .product !=
302
309
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 )
@@ -380,6 +387,34 @@ static int magicmouse_raw_event(struct hid_device *hdev,
380
387
* ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
381
388
*/
382
389
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 ;
383
418
case DOUBLE_REPORT_ID :
384
419
/* Sometimes the trackpad sends two touch reports in one
385
420
* packet.
@@ -392,7 +427,8 @@ static int magicmouse_raw_event(struct hid_device *hdev,
392
427
return 0 ;
393
428
}
394
429
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 ) {
396
432
magicmouse_emit_buttons (msc , clicks & 3 );
397
433
input_report_rel (input , REL_X , x );
398
434
input_report_rel (input , REL_Y , y );
@@ -408,14 +444,32 @@ static int magicmouse_raw_event(struct hid_device *hdev,
408
444
return 1 ;
409
445
}
410
446
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
+
411
464
static int magicmouse_setup_input (struct input_dev * input , struct hid_device * hdev )
412
465
{
413
466
int error ;
414
467
int mt_flags = 0 ;
415
468
416
469
__set_bit (EV_KEY , input -> evbit );
417
470
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 ) {
419
473
__set_bit (BTN_LEFT , input -> keybit );
420
474
__set_bit (BTN_RIGHT , input -> keybit );
421
475
if (emulate_3button )
@@ -480,7 +534,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
480
534
* the origin at the same position, and just uses the additive
481
535
* inverse of the reported Y.
482
536
*/
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 ) {
484
539
input_set_abs_params (input , ABS_MT_ORIENTATION , -31 , 32 , 1 , 0 );
485
540
input_set_abs_params (input , ABS_MT_POSITION_X ,
486
541
MOUSE_MIN_X , MOUSE_MAX_X , 4 , 0 );
@@ -580,19 +635,60 @@ static int magicmouse_input_configured(struct hid_device *hdev,
580
635
return 0 ;
581
636
}
582
637
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 )
586
639
{
587
640
const u8 * feature ;
588
641
const u8 feature_mt [] = { 0xD7 , 0x01 };
642
+ const u8 feature_mt_mouse2 [] = { 0xF1 , 0x02 , 0x01 };
589
643
const u8 feature_mt_trackpad2_usb [] = { 0x02 , 0x01 };
590
644
const u8 feature_mt_trackpad2_bt [] = { 0xF1 , 0x02 , 0x01 };
591
645
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
+ {
592
689
struct magicmouse_sc * msc ;
593
690
struct hid_report * report ;
594
691
int ret ;
595
- int feature_size ;
596
692
597
693
if (id -> vendor == USB_VENDOR_ID_APPLE &&
598
694
id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
@@ -606,6 +702,8 @@ static int magicmouse_probe(struct hid_device *hdev,
606
702
}
607
703
608
704
msc -> scroll_accel = SCROLL_ACCEL_DEFAULT ;
705
+ msc -> hdev = hdev ;
706
+ INIT_DEFERRABLE_WORK (& msc -> work , magicmouse_enable_mt_work );
609
707
610
708
msc -> quirks = id -> driver_data ;
611
709
hid_set_drvdata (hdev , msc );
@@ -631,6 +729,9 @@ static int magicmouse_probe(struct hid_device *hdev,
631
729
if (id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE )
632
730
report = hid_register_report (hdev , HID_INPUT_REPORT ,
633
731
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 );
634
735
else if (id -> product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ) {
635
736
if (id -> vendor == BT_VENDOR_ID_APPLE )
636
737
report = hid_register_report (hdev , HID_INPUT_REPORT ,
@@ -652,25 +753,6 @@ static int magicmouse_probe(struct hid_device *hdev,
652
753
}
653
754
report -> size = 6 ;
654
755
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
-
674
756
/*
675
757
* Some devices repond with 'invalid report id' when feature
676
758
* report switching it into multitouch mode is sent to it.
@@ -679,23 +761,33 @@ static int magicmouse_probe(struct hid_device *hdev,
679
761
* but there seems to be no other way of switching the mode.
680
762
* Thus the super-ugly hacky success check below.
681
763
*/
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 ) {
686
766
hid_err (hdev , "unable to request touch data (%d)\n" , ret );
687
767
goto err_stop_hw ;
688
768
}
769
+ if (ret == - EIO && id -> product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ) {
770
+ schedule_delayed_work (& msc -> work , msecs_to_jiffies (500 ));
771
+ }
689
772
690
773
return 0 ;
691
774
err_stop_hw :
692
775
hid_hw_stop (hdev );
693
776
return ret ;
694
777
}
695
778
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
+
696
786
static const struct hid_device_id magic_mice [] = {
697
787
{ HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
698
788
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 },
699
791
{ HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_APPLE ,
700
792
USB_DEVICE_ID_APPLE_MAGICTRACKPAD ), .driver_data = 0 },
701
793
{ HID_BLUETOOTH_DEVICE (BT_VENDOR_ID_APPLE ,
@@ -710,7 +802,9 @@ static struct hid_driver magicmouse_driver = {
710
802
.name = "magicmouse" ,
711
803
.id_table = magic_mice ,
712
804
.probe = magicmouse_probe ,
805
+ .remove = magicmouse_remove ,
713
806
.raw_event = magicmouse_raw_event ,
807
+ .event = magicmouse_event ,
714
808
.input_mapping = magicmouse_input_mapping ,
715
809
.input_configured = magicmouse_input_configured ,
716
810
};
0 commit comments