84
84
#define STD_MOUSE BIT(2)
85
85
#define MULTIMEDIA BIT(3)
86
86
#define POWER_KEYS BIT(4)
87
+ #define KBD_MOUSE BIT(5)
87
88
#define MEDIA_CENTER BIT(8)
88
89
#define KBD_LEDS BIT(14)
89
90
/* Fake (bitnr > NUMBER_OF_HID_REPORTS) bit to track HID++ capability */
@@ -117,6 +118,7 @@ enum recvr_type {
117
118
recvr_type_mouse_only ,
118
119
recvr_type_27mhz ,
119
120
recvr_type_bluetooth ,
121
+ recvr_type_dinovo ,
120
122
};
121
123
122
124
struct dj_report {
@@ -333,6 +335,47 @@ static const char mse_bluetooth_descriptor[] = {
333
335
0xC0 , /* END_COLLECTION */
334
336
};
335
337
338
+ /* Mouse descriptor (5) for Bluetooth receiver, normal-res hwheel, 8 buttons */
339
+ static const char mse5_bluetooth_descriptor [] = {
340
+ 0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
341
+ 0x09 , 0x02 , /* Usage (Mouse) */
342
+ 0xa1 , 0x01 , /* Collection (Application) */
343
+ 0x85 , 0x05 , /* Report ID (5) */
344
+ 0x09 , 0x01 , /* Usage (Pointer) */
345
+ 0xa1 , 0x00 , /* Collection (Physical) */
346
+ 0x05 , 0x09 , /* Usage Page (Button) */
347
+ 0x19 , 0x01 , /* Usage Minimum (1) */
348
+ 0x29 , 0x08 , /* Usage Maximum (8) */
349
+ 0x15 , 0x00 , /* Logical Minimum (0) */
350
+ 0x25 , 0x01 , /* Logical Maximum (1) */
351
+ 0x95 , 0x08 , /* Report Count (8) */
352
+ 0x75 , 0x01 , /* Report Size (1) */
353
+ 0x81 , 0x02 , /* Input (Data,Var,Abs) */
354
+ 0x05 , 0x01 , /* Usage Page (Generic Desktop) */
355
+ 0x16 , 0x01 , 0xf8 , /* Logical Minimum (-2047) */
356
+ 0x26 , 0xff , 0x07 , /* Logical Maximum (2047) */
357
+ 0x75 , 0x0c , /* Report Size (12) */
358
+ 0x95 , 0x02 , /* Report Count (2) */
359
+ 0x09 , 0x30 , /* Usage (X) */
360
+ 0x09 , 0x31 , /* Usage (Y) */
361
+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
362
+ 0x15 , 0x81 , /* Logical Minimum (-127) */
363
+ 0x25 , 0x7f , /* Logical Maximum (127) */
364
+ 0x75 , 0x08 , /* Report Size (8) */
365
+ 0x95 , 0x01 , /* Report Count (1) */
366
+ 0x09 , 0x38 , /* Usage (Wheel) */
367
+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
368
+ 0x05 , 0x0c , /* Usage Page (Consumer Devices) */
369
+ 0x0a , 0x38 , 0x02 , /* Usage (AC Pan) */
370
+ 0x15 , 0x81 , /* Logical Minimum (-127) */
371
+ 0x25 , 0x7f , /* Logical Maximum (127) */
372
+ 0x75 , 0x08 , /* Report Size (8) */
373
+ 0x95 , 0x01 , /* Report Count (1) */
374
+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
375
+ 0xc0 , /* End Collection */
376
+ 0xc0 , /* End Collection */
377
+ };
378
+
336
379
/* Gaming Mouse descriptor (2) */
337
380
static const char mse_high_res_descriptor [] = {
338
381
0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
@@ -480,6 +523,7 @@ static const char hidpp_descriptor[] = {
480
523
#define MAX_RDESC_SIZE \
481
524
(sizeof(kbd_descriptor) + \
482
525
sizeof(mse_bluetooth_descriptor) + \
526
+ sizeof(mse5_bluetooth_descriptor) + \
483
527
sizeof(consumer_descriptor) + \
484
528
sizeof(syscontrol_descriptor) + \
485
529
sizeof(media_descriptor) + \
@@ -517,6 +561,11 @@ static void delayedwork_callback(struct work_struct *work);
517
561
static LIST_HEAD (dj_hdev_list );
518
562
static DEFINE_MUTEX (dj_hdev_list_lock );
519
563
564
+ static bool recvr_type_is_bluetooth (enum recvr_type type )
565
+ {
566
+ return type == recvr_type_bluetooth || type == recvr_type_dinovo ;
567
+ }
568
+
520
569
/*
521
570
* dj/HID++ receivers are really a single logical entity, but for BIOS/Windows
522
571
* compatibility they have multiple USB interfaces. On HID++ receivers we need
@@ -534,7 +583,7 @@ static struct dj_receiver_dev *dj_find_receiver_dev(struct hid_device *hdev,
534
583
* The bluetooth receiver contains a built-in hub and has separate
535
584
* USB-devices for the keyboard and mouse interfaces.
536
585
*/
537
- sep = (type == recvr_type_bluetooth ) ? '.' : '/' ;
586
+ sep = recvr_type_is_bluetooth (type ) ? '.' : '/' ;
538
587
539
588
/* Try to find an already-probed interface from the same device */
540
589
list_for_each_entry (djrcv_dev , & dj_hdev_list , list ) {
@@ -872,6 +921,14 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev,
872
921
* touchpad to work we must also forward mouse input reports to the dj_hiddev
873
922
* created for the keyboard (instead of forwarding them to a second paired
874
923
* device with a device_type of REPORT_TYPE_MOUSE as we normally would).
924
+ *
925
+ * On Dinovo receivers the keyboard's touchpad and an optional paired actual
926
+ * mouse send separate input reports, INPUT(2) aka STD_MOUSE for the mouse
927
+ * and INPUT(5) aka KBD_MOUSE for the keyboard's touchpad.
928
+ *
929
+ * On MX5x00 receivers (which can also be paired with a Dinovo keyboard)
930
+ * INPUT(2) is used for both an optional paired actual mouse and for the
931
+ * keyboard's touchpad.
875
932
*/
876
933
static const u16 kbd_builtin_touchpad_ids [] = {
877
934
0xb309 , /* Dinovo Edge */
@@ -898,7 +955,10 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
898
955
id = (workitem -> quad_id_msb << 8 ) | workitem -> quad_id_lsb ;
899
956
for (i = 0 ; i < ARRAY_SIZE (kbd_builtin_touchpad_ids ); i ++ ) {
900
957
if (id == kbd_builtin_touchpad_ids [i ]) {
901
- workitem -> reports_supported |= STD_MOUSE ;
958
+ if (djrcv_dev -> type == recvr_type_dinovo )
959
+ workitem -> reports_supported |= KBD_MOUSE ;
960
+ else
961
+ workitem -> reports_supported |= STD_MOUSE ;
902
962
break ;
903
963
}
904
964
}
@@ -1367,14 +1427,21 @@ static int logi_dj_ll_parse(struct hid_device *hid)
1367
1427
else if (djdev -> dj_receiver_dev -> type == recvr_type_27mhz )
1368
1428
rdcat (rdesc , & rsize , mse_27mhz_descriptor ,
1369
1429
sizeof (mse_27mhz_descriptor ));
1370
- else if (djdev -> dj_receiver_dev -> type == recvr_type_bluetooth )
1430
+ else if (recvr_type_is_bluetooth ( djdev -> dj_receiver_dev -> type ) )
1371
1431
rdcat (rdesc , & rsize , mse_bluetooth_descriptor ,
1372
1432
sizeof (mse_bluetooth_descriptor ));
1373
1433
else
1374
1434
rdcat (rdesc , & rsize , mse_descriptor ,
1375
1435
sizeof (mse_descriptor ));
1376
1436
}
1377
1437
1438
+ if (djdev -> reports_supported & KBD_MOUSE ) {
1439
+ dbg_hid ("%s: sending a kbd-mouse descriptor, reports_supported: %llx\n" ,
1440
+ __func__ , djdev -> reports_supported );
1441
+ rdcat (rdesc , & rsize , mse5_bluetooth_descriptor ,
1442
+ sizeof (mse5_bluetooth_descriptor ));
1443
+ }
1444
+
1378
1445
if (djdev -> reports_supported & MULTIMEDIA ) {
1379
1446
dbg_hid ("%s: sending a multimedia report descriptor: %llx\n" ,
1380
1447
__func__ , djdev -> reports_supported );
@@ -1692,6 +1759,7 @@ static int logi_dj_probe(struct hid_device *hdev,
1692
1759
case recvr_type_mouse_only : no_dj_interfaces = 2 ; break ;
1693
1760
case recvr_type_27mhz : no_dj_interfaces = 2 ; break ;
1694
1761
case recvr_type_bluetooth : no_dj_interfaces = 2 ; break ;
1762
+ case recvr_type_dinovo : no_dj_interfaces = 2 ; break ;
1695
1763
}
1696
1764
if (hid_is_using_ll_driver (hdev , & usb_hid_driver )) {
1697
1765
intf = to_usb_interface (hdev -> dev .parent );
@@ -1924,6 +1992,23 @@ static const struct hid_device_id logi_dj_receivers[] = {
1924
1992
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1925
1993
USB_DEVICE_ID_MX5500_RECEIVER_MOUSE_DEV ),
1926
1994
.driver_data = recvr_type_bluetooth },
1995
+
1996
+ { /* Logitech Dinovo Edge HID++ / bluetooth receiver keyboard intf. (0xc713) */
1997
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1998
+ USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_KBD_DEV ),
1999
+ .driver_data = recvr_type_dinovo },
2000
+ { /* Logitech Dinovo Edge HID++ / bluetooth receiver mouse intf. (0xc714) */
2001
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
2002
+ USB_DEVICE_ID_DINOVO_EDGE_RECEIVER_MOUSE_DEV ),
2003
+ .driver_data = recvr_type_dinovo },
2004
+ { /* Logitech DiNovo Mini HID++ / bluetooth receiver mouse intf. (0xc71e) */
2005
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
2006
+ USB_DEVICE_ID_DINOVO_MINI_RECEIVER_KBD_DEV ),
2007
+ .driver_data = recvr_type_dinovo },
2008
+ { /* Logitech DiNovo Mini HID++ / bluetooth receiver keyboard intf. (0xc71f) */
2009
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
2010
+ USB_DEVICE_ID_DINOVO_MINI_RECEIVER_MOUSE_DEV ),
2011
+ .driver_data = recvr_type_dinovo },
1927
2012
{}
1928
2013
};
1929
2014
0 commit comments