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 );
@@ -1857,23 +1925,27 @@ static void logi_dj_remove(struct hid_device *hdev)
1857
1925
}
1858
1926
1859
1927
static const struct hid_device_id logi_dj_receivers [] = {
1860
- {HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1928
+ { /* Logitech unifying receiver (0xc52b) */
1929
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1861
1930
USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER ),
1862
1931
.driver_data = recvr_type_dj },
1863
- {HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1932
+ { /* Logitech unifying receiver (0xc532) */
1933
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1864
1934
USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 ),
1865
1935
.driver_data = recvr_type_dj },
1866
- { /* Logitech Nano mouse only receiver */
1936
+
1937
+ { /* Logitech Nano mouse only receiver (0xc52f) */
1867
1938
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1868
1939
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER ),
1869
1940
.driver_data = recvr_type_mouse_only },
1870
- { /* Logitech Nano (non DJ) receiver */
1941
+ { /* Logitech Nano (non DJ) receiver (0xc534) */
1871
1942
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1872
1943
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 ),
1873
1944
.driver_data = recvr_type_hidpp },
1945
+
1874
1946
{ /* Logitech G700(s) receiver (0xc531) */
1875
1947
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1876
- 0xc531 ),
1948
+ USB_DEVICE_ID_LOGITECH_G700_RECEIVER ),
1877
1949
.driver_data = recvr_type_gaming_hidpp },
1878
1950
{ /* Logitech G602 receiver (0xc537) */
1879
1951
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
@@ -1883,17 +1955,18 @@ static const struct hid_device_id logi_dj_receivers[] = {
1883
1955
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1884
1956
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 ),
1885
1957
.driver_data = recvr_type_gaming_hidpp },
1958
+ { /* Logitech powerplay receiver (0xc53a) */
1959
+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1960
+ USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY ),
1961
+ .driver_data = recvr_type_gaming_hidpp },
1886
1962
{ /* Logitech lightspeed receiver (0xc53f) */
1887
1963
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1888
1964
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 ),
1889
1965
.driver_data = recvr_type_gaming_hidpp },
1966
+
1890
1967
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
1891
1968
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH , USB_DEVICE_ID_MX3000_RECEIVER ),
1892
1969
.driver_data = recvr_type_27mhz },
1893
- { /* Logitech powerplay receiver (0xc53a) */
1894
- HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1895
- USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY ),
1896
- .driver_data = recvr_type_gaming_hidpp },
1897
1970
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
1898
1971
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1899
1972
USB_DEVICE_ID_S510_RECEIVER_2 ),
@@ -1902,22 +1975,40 @@ static const struct hid_device_id logi_dj_receivers[] = {
1902
1975
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1903
1976
USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER ),
1904
1977
.driver_data = recvr_type_27mhz },
1905
- { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. */
1978
+
1979
+ { /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. (0xc70e) */
1906
1980
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1907
- 0xc70e ),
1981
+ USB_DEVICE_ID_MX5000_RECEIVER_KBD_DEV ),
1908
1982
.driver_data = recvr_type_bluetooth },
1909
- { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. */
1983
+ { /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. (0xc70a) */
1910
1984
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1911
- 0xc70a ),
1985
+ USB_DEVICE_ID_MX5000_RECEIVER_MOUSE_DEV ),
1912
1986
.driver_data = recvr_type_bluetooth },
1913
- { /* Logitech MX5500 HID++ / bluetooth receiver keyboard intf. */
1987
+ { /* Logitech MX5500 HID++ / bluetooth receiver keyboard intf. (0xc71b) */
1914
1988
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1915
- 0xc71b ),
1989
+ USB_DEVICE_ID_MX5500_RECEIVER_KBD_DEV ),
1916
1990
.driver_data = recvr_type_bluetooth },
1917
- { /* Logitech MX5500 HID++ / bluetooth receiver mouse intf. */
1991
+ { /* Logitech MX5500 HID++ / bluetooth receiver mouse intf. (0xc71c) */
1918
1992
HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1919
- 0xc71c ),
1993
+ USB_DEVICE_ID_MX5500_RECEIVER_MOUSE_DEV ),
1920
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 },
1921
2012
{}
1922
2013
};
1923
2014
0 commit comments