@@ -116,6 +116,7 @@ enum recvr_type {
116116 recvr_type_dj ,
117117 recvr_type_hidpp ,
118118 recvr_type_gaming_hidpp ,
119+ recvr_type_gaming_hidpp_ls_1_3 ,
119120 recvr_type_mouse_only ,
120121 recvr_type_27mhz ,
121122 recvr_type_bluetooth ,
@@ -211,6 +212,44 @@ static const char kbd_descriptor[] = {
211212 0xC0
212213};
213214
215+ /* Gaming Keyboard descriptor (1) */
216+ static const char kbd_lightspeed_1_3_descriptor [] = {
217+ 0x05 , 0x01 , /* Usage Page (Generic Desktop) */
218+ 0x09 , 0x06 , /* Usage (Keyboard) */
219+ 0xA1 , 0x01 , /* Collection (Application) */
220+ 0x85 , 0x01 , /* Report ID (1) */
221+ 0x05 , 0x07 , /* Usage Page (Kbrd/Keypad) */
222+ 0x19 , 0xE0 , /* Usage Minimum (0xE0) */
223+ 0x29 , 0xE7 , /* Usage Maximum (0xE7) */
224+ 0x15 , 0x00 , /* Logical Minimum (0) */
225+ 0x25 , 0x01 , /* Logical Maximum (1) */
226+ 0x75 , 0x01 , /* Report Size (1) */
227+ 0x95 , 0x08 , /* Report Count (8) */
228+ 0x81 , 0x02 , /* Input (Data,Var) */
229+ 0x95 , 0x70 , /* Report Count (112) */
230+ 0x19 , 0x04 , /* Usage Minimum (0x04) */
231+ 0x29 , 0x73 , /* Usage Maximum (0x73) */
232+ 0x81 , 0x02 , /* Input (Data,Var,Abs) */
233+ 0x95 , 0x05 , /* Report Count (5) */
234+ 0x19 , 0x87 , /* Usage Minimum (0x87) */
235+ 0x29 , 0x8B , /* Usage Maximum (0x8B) */
236+ 0x81 , 0x02 , /* Input (Data,Var,Abs) */
237+ 0x95 , 0x03 , /* Report Count (3) */
238+ 0x19 , 0x90 , /* Usage Minimum (0x90) */
239+ 0x29 , 0x92 , /* Usage Maximum (0x92) */
240+ 0x81 , 0x02 , /* Input (Data,Var,Abs) */
241+ 0x95 , 0x05 , /* Report Count (5) */
242+ 0x85 , 0x0E , /* Report ID (14) */
243+ 0x05 , 0x08 , /* Usage Page (LEDs) */
244+ 0x19 , 0x01 , /* Usage Minimum (Num Lock) */
245+ 0x29 , 0x05 , /* Usage Maximum (Kana) */
246+ 0x91 , 0x02 , /* Output (Data,Var,Abs) */
247+ 0x95 , 0x01 , /* Report Count (1) */
248+ 0x75 , 0x03 , /* Report Size (3) */
249+ 0x91 , 0x03 , /* Output (Const,Var,Abs) */
250+ 0xC0 , /* End Collection */
251+ };
252+
214253/* Mouse descriptor (2) */
215254static const char mse_descriptor [] = {
216255 0x05 , 0x01 , /* USAGE_PAGE (Generic Desktop) */
@@ -415,6 +454,51 @@ static const char mse_high_res_descriptor[] = {
415454 0xC0 , /* END_COLLECTION */
416455};
417456
457+ /* Gaming Mouse descriptor with vendor data (2) */
458+ static const char mse_high_res_ls_1_3_descriptor [] = {
459+ 0x05 , 0x01 , /* Usage Page (Generic Desktop) */
460+ 0x09 , 0x02 , /* Usage (Mouse) */
461+ 0xA1 , 0x01 , /* Collection (Application) */
462+ 0x85 , 0x02 , /* Report ID (2) */
463+ 0x09 , 0x01 , /* Usage (Pointer) */
464+ 0xA1 , 0x00 , /* Collection (Physical) */
465+ 0x95 , 0x10 , /* Report Count (16) */
466+ 0x75 , 0x01 , /* Report Size (1) */
467+ 0x15 , 0x00 , /* Logical Minimum (0) */
468+ 0x25 , 0x01 , /* Logical Maximum (1) */
469+ 0x05 , 0x09 , /* Usage Page (Button) */
470+ 0x19 , 0x01 , /* Usage Minimum (0x01) */
471+ 0x29 , 0x10 , /* Usage Maximum (0x10) */
472+ 0x81 , 0x02 , /* Input (Data,Var,Abs) */
473+ 0x95 , 0x02 , /* Report Count (2) */
474+ 0x75 , 0x10 , /* Report Size (16) */
475+ 0x16 , 0x01 , 0x80 , /* Logical Minimum (-32767) */
476+ 0x26 , 0xFF , 0x7F , /* Logical Maximum (32767) */
477+ 0x05 , 0x01 , /* Usage Page (Generic Desktop) */
478+ 0x09 , 0x30 , /* Usage (X) */
479+ 0x09 , 0x31 , /* Usage (Y) */
480+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
481+ 0x95 , 0x01 , /* Report Count (1) */
482+ 0x75 , 0x08 , /* Report Size (8) */
483+ 0x15 , 0x81 , /* Logical Minimum (-127) */
484+ 0x25 , 0x7F , /* Logical Maximum (127) */
485+ 0x09 , 0x38 , /* Usage (Wheel) */
486+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
487+ 0x95 , 0x01 , /* Report Count (1) */
488+ 0x05 , 0x0C , /* Usage Page (Consumer) */
489+ 0x0A , 0x38 , 0x02 , /* Usage (AC Pan) */
490+ 0x81 , 0x06 , /* Input (Data,Var,Rel) */
491+ 0xC0 , /* End Collection */
492+ 0x06 , 0x00 , 0xFF , /* Usage Page (Vendor Defined 0xFF00) */
493+ 0x09 , 0xF1 , /* Usage (0xF1) */
494+ 0x75 , 0x08 , /* Report Size (8) */
495+ 0x95 , 0x05 , /* Report Count (5) */
496+ 0x15 , 0x00 , /* Logical Minimum (0) */
497+ 0x26 , 0xFF , 0x00 , /* Logical Maximum (255) */
498+ 0x81 , 0x00 , /* Input (Data,Array,Abs) */
499+ 0xC0 , /* End Collection */
500+ };
501+
418502/* Consumer Control descriptor (3) */
419503static const char consumer_descriptor [] = {
420504 0x05 , 0x0C , /* USAGE_PAGE (Consumer Devices) */
@@ -520,9 +604,9 @@ static const char hidpp_descriptor[] = {
520604/* Maximum size of all defined hid reports in bytes (including report id) */
521605#define MAX_REPORT_SIZE 8
522606
523- /* Make sure all descriptors are present here */
607+ /* Make sure the largest of each descriptor type is present here */
524608#define MAX_RDESC_SIZE \
525- (sizeof(kbd_descriptor ) + \
609+ (sizeof(kbd_lightspeed_1_3_descriptor ) +\
526610 sizeof(mse_bluetooth_descriptor) + \
527611 sizeof(mse5_bluetooth_descriptor) + \
528612 sizeof(consumer_descriptor) + \
@@ -1374,12 +1458,19 @@ static int logi_dj_ll_raw_request(struct hid_device *hid,
13741458 return - EINVAL ;
13751459
13761460 if (djrcv_dev -> type != recvr_type_dj && count >= 2 ) {
1461+ unsigned char led_report_id = 0 ;
1462+
13771463 if (!djrcv_dev -> keyboard ) {
13781464 hid_warn (hid , "Received REPORT_TYPE_LEDS request before the keyboard interface was enumerated\n" );
13791465 return 0 ;
13801466 }
1467+
1468+ /* This Lightspeed receiver expects LED reports with report ID 1 */
1469+ if (djrcv_dev -> type == recvr_type_gaming_hidpp_ls_1_3 )
1470+ led_report_id = 1 ;
1471+
13811472 /* usbhid overrides the report ID and ignores the first byte */
1382- return hid_hw_raw_request (djrcv_dev -> keyboard , 0 , buf , count ,
1473+ return hid_hw_raw_request (djrcv_dev -> keyboard , led_report_id , buf , count ,
13831474 report_type , reqtype );
13841475 }
13851476
@@ -1426,7 +1517,11 @@ static int logi_dj_ll_parse(struct hid_device *hid)
14261517 if (djdev -> reports_supported & STD_KEYBOARD ) {
14271518 dbg_hid ("%s: sending a kbd descriptor, reports_supported: %llx\n" ,
14281519 __func__ , djdev -> reports_supported );
1429- rdcat (rdesc , & rsize , kbd_descriptor , sizeof (kbd_descriptor ));
1520+ if (djdev -> dj_receiver_dev -> type == recvr_type_gaming_hidpp_ls_1_3 )
1521+ rdcat (rdesc , & rsize , kbd_lightspeed_1_3_descriptor ,
1522+ sizeof (kbd_lightspeed_1_3_descriptor ));
1523+ else
1524+ rdcat (rdesc , & rsize , kbd_descriptor , sizeof (kbd_descriptor ));
14301525 }
14311526
14321527 if (djdev -> reports_supported & STD_MOUSE ) {
@@ -1436,6 +1531,9 @@ static int logi_dj_ll_parse(struct hid_device *hid)
14361531 djdev -> dj_receiver_dev -> type == recvr_type_mouse_only )
14371532 rdcat (rdesc , & rsize , mse_high_res_descriptor ,
14381533 sizeof (mse_high_res_descriptor ));
1534+ else if (djdev -> dj_receiver_dev -> type == recvr_type_gaming_hidpp_ls_1_3 )
1535+ rdcat (rdesc , & rsize , mse_high_res_ls_1_3_descriptor ,
1536+ sizeof (mse_high_res_ls_1_3_descriptor ));
14391537 else if (djdev -> dj_receiver_dev -> type == recvr_type_27mhz )
14401538 rdcat (rdesc , & rsize , mse_27mhz_descriptor ,
14411539 sizeof (mse_27mhz_descriptor ));
@@ -1695,11 +1793,12 @@ static int logi_dj_raw_event(struct hid_device *hdev,
16951793 }
16961794 /*
16971795 * Mouse-only receivers send unnumbered mouse data. The 27 MHz
1698- * receiver uses 6 byte packets, the nano receiver 8 bytes.
1796+ * receiver uses 6 byte packets, the nano receiver 8 bytes,
1797+ * the lightspeed receiver (Pro X Superlight) 13 bytes.
16991798 */
17001799 if (djrcv_dev -> unnumbered_application == HID_GD_MOUSE &&
1701- size <= 8 ) {
1702- u8 mouse_report [9 ];
1800+ size <= 13 ) {
1801+ u8 mouse_report [14 ];
17031802
17041803 /* Prepend report id */
17051804 mouse_report [0 ] = REPORT_TYPE_MOUSE ;
@@ -1776,6 +1875,7 @@ static int logi_dj_probe(struct hid_device *hdev,
17761875 case recvr_type_dj : no_dj_interfaces = 3 ; break ;
17771876 case recvr_type_hidpp : no_dj_interfaces = 2 ; break ;
17781877 case recvr_type_gaming_hidpp : no_dj_interfaces = 3 ; break ;
1878+ case recvr_type_gaming_hidpp_ls_1_3 : no_dj_interfaces = 3 ; break ;
17791879 case recvr_type_mouse_only : no_dj_interfaces = 2 ; break ;
17801880 case recvr_type_27mhz : no_dj_interfaces = 2 ; break ;
17811881 case recvr_type_bluetooth : no_dj_interfaces = 2 ; break ;
@@ -1987,6 +2087,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
19872087 HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
19882088 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 ),
19892089 .driver_data = recvr_type_gaming_hidpp },
2090+ { /* Logitech lightspeed receiver (0xc547) */
2091+ HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
2092+ USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3 ),
2093+ .driver_data = recvr_type_gaming_hidpp_ls_1_3 },
19902094
19912095 { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
19922096 HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH , USB_DEVICE_ID_MX3000_RECEIVER ),
0 commit comments