diff options
author | Hans de Goede <hdegoede@redhat.com> | 2019-06-05 08:44:08 -0400 |
---|---|---|
committer | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2019-06-05 09:16:26 -0400 |
commit | 3ed224e273ac5880eeab4c3043a6b06b0478dd56 (patch) | |
tree | c8bea1442142b118902a0795a1d9cd4a027a85b7 /drivers/hid | |
parent | f9482dabfd1686987cc6044e06ae0e4c05915518 (diff) |
HID: logitech-dj: Fix 064d:c52f receiver support
The c52f nano receiver is a mouse only receiver. This means that it needs
some special handling compared to the c534 nano receiver:
1) It sends unnumbered mouse reports with a size of 8 bytes, so we need
to extend the unnumbered mouse report handling to support reports upto
8 bytes large
2) It mouse reports have the same high-resolution format as those from the
gaming mouse receivers
3) It can report consumer/multimedia buttons on its second interface, since
this is a mouse-only receiver these must be forwarded to the mouse child
device and not to the keyboard child-device (which will not exist)
Link: https://bugzilla.kernel.org/show_bug.cgi?id=203619
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index dfc34fe85319..ce00dc299404 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -128,6 +128,7 @@ enum recvr_type { | |||
128 | recvr_type_dj, | 128 | recvr_type_dj, |
129 | recvr_type_hidpp, | 129 | recvr_type_hidpp, |
130 | recvr_type_gaming_hidpp, | 130 | recvr_type_gaming_hidpp, |
131 | recvr_type_mouse_only, | ||
131 | recvr_type_27mhz, | 132 | recvr_type_27mhz, |
132 | recvr_type_bluetooth, | 133 | recvr_type_bluetooth, |
133 | }; | 134 | }; |
@@ -879,9 +880,12 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, | |||
879 | schedule_work(&djrcv_dev->work); | 880 | schedule_work(&djrcv_dev->work); |
880 | } | 881 | } |
881 | 882 | ||
882 | static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, | 883 | static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, |
884 | struct hidpp_event *hidpp_report, | ||
883 | struct dj_workitem *workitem) | 885 | struct dj_workitem *workitem) |
884 | { | 886 | { |
887 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); | ||
888 | |||
885 | workitem->type = WORKITEM_TYPE_PAIRED; | 889 | workitem->type = WORKITEM_TYPE_PAIRED; |
886 | workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & | 890 | workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & |
887 | HIDPP_DEVICE_TYPE_MASK; | 891 | HIDPP_DEVICE_TYPE_MASK; |
@@ -895,6 +899,8 @@ static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, | |||
895 | break; | 899 | break; |
896 | case REPORT_TYPE_MOUSE: | 900 | case REPORT_TYPE_MOUSE: |
897 | workitem->reports_supported |= STD_MOUSE | HIDPP; | 901 | workitem->reports_supported |= STD_MOUSE | HIDPP; |
902 | if (djrcv_dev->type == recvr_type_mouse_only) | ||
903 | workitem->reports_supported |= MULTIMEDIA; | ||
898 | break; | 904 | break; |
899 | } | 905 | } |
900 | } | 906 | } |
@@ -938,7 +944,7 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, | |||
938 | case 0x01: | 944 | case 0x01: |
939 | device_type = "Bluetooth"; | 945 | device_type = "Bluetooth"; |
940 | /* Bluetooth connect packet contents is the same as (e)QUAD */ | 946 | /* Bluetooth connect packet contents is the same as (e)QUAD */ |
941 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 947 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
942 | if (!(hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & | 948 | if (!(hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & |
943 | HIDPP_MANUFACTURER_MASK)) { | 949 | HIDPP_MANUFACTURER_MASK)) { |
944 | hid_info(hdev, "Non Logitech device connected on slot %d\n", | 950 | hid_info(hdev, "Non Logitech device connected on slot %d\n", |
@@ -952,18 +958,18 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, | |||
952 | break; | 958 | break; |
953 | case 0x03: | 959 | case 0x03: |
954 | device_type = "QUAD or eQUAD"; | 960 | device_type = "QUAD or eQUAD"; |
955 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 961 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
956 | break; | 962 | break; |
957 | case 0x04: | 963 | case 0x04: |
958 | device_type = "eQUAD step 4 DJ"; | 964 | device_type = "eQUAD step 4 DJ"; |
959 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 965 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
960 | break; | 966 | break; |
961 | case 0x05: | 967 | case 0x05: |
962 | device_type = "DFU Lite"; | 968 | device_type = "DFU Lite"; |
963 | break; | 969 | break; |
964 | case 0x06: | 970 | case 0x06: |
965 | device_type = "eQUAD step 4 Lite"; | 971 | device_type = "eQUAD step 4 Lite"; |
966 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 972 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
967 | break; | 973 | break; |
968 | case 0x07: | 974 | case 0x07: |
969 | device_type = "eQUAD step 4 Gaming"; | 975 | device_type = "eQUAD step 4 Gaming"; |
@@ -973,11 +979,11 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev, | |||
973 | break; | 979 | break; |
974 | case 0x0a: | 980 | case 0x0a: |
975 | device_type = "eQUAD nano Lite"; | 981 | device_type = "eQUAD nano Lite"; |
976 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 982 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
977 | break; | 983 | break; |
978 | case 0x0c: | 984 | case 0x0c: |
979 | device_type = "eQUAD Lightspeed"; | 985 | device_type = "eQUAD Lightspeed"; |
980 | logi_hidpp_dev_conn_notif_equad(hidpp_report, &workitem); | 986 | logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); |
981 | workitem.reports_supported |= STD_KEYBOARD; | 987 | workitem.reports_supported |= STD_KEYBOARD; |
982 | break; | 988 | break; |
983 | } | 989 | } |
@@ -1328,7 +1334,8 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
1328 | if (djdev->reports_supported & STD_MOUSE) { | 1334 | if (djdev->reports_supported & STD_MOUSE) { |
1329 | dbg_hid("%s: sending a mouse descriptor, reports_supported: %llx\n", | 1335 | dbg_hid("%s: sending a mouse descriptor, reports_supported: %llx\n", |
1330 | __func__, djdev->reports_supported); | 1336 | __func__, djdev->reports_supported); |
1331 | if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp) | 1337 | if (djdev->dj_receiver_dev->type == recvr_type_gaming_hidpp || |
1338 | djdev->dj_receiver_dev->type == recvr_type_mouse_only) | ||
1332 | rdcat(rdesc, &rsize, mse_high_res_descriptor, | 1339 | rdcat(rdesc, &rsize, mse_high_res_descriptor, |
1333 | sizeof(mse_high_res_descriptor)); | 1340 | sizeof(mse_high_res_descriptor)); |
1334 | else if (djdev->dj_receiver_dev->type == recvr_type_27mhz) | 1341 | else if (djdev->dj_receiver_dev->type == recvr_type_27mhz) |
@@ -1571,15 +1578,19 @@ static int logi_dj_raw_event(struct hid_device *hdev, | |||
1571 | data[0] = data[1]; | 1578 | data[0] = data[1]; |
1572 | data[1] = 0; | 1579 | data[1] = 0; |
1573 | } | 1580 | } |
1574 | /* The 27 MHz mouse-only receiver sends unnumbered mouse data */ | 1581 | /* |
1582 | * Mouse-only receivers send unnumbered mouse data. The 27 MHz | ||
1583 | * receiver uses 6 byte packets, the nano receiver 8 bytes. | ||
1584 | */ | ||
1575 | if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && | 1585 | if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && |
1576 | size == 6) { | 1586 | size <= 8) { |
1577 | u8 mouse_report[7]; | 1587 | u8 mouse_report[9]; |
1578 | 1588 | ||
1579 | /* Prepend report id */ | 1589 | /* Prepend report id */ |
1580 | mouse_report[0] = REPORT_TYPE_MOUSE; | 1590 | mouse_report[0] = REPORT_TYPE_MOUSE; |
1581 | memcpy(mouse_report + 1, data, 6); | 1591 | memcpy(mouse_report + 1, data, size); |
1582 | logi_dj_recv_forward_input_report(hdev, mouse_report, 7); | 1592 | logi_dj_recv_forward_input_report(hdev, mouse_report, |
1593 | size + 1); | ||
1583 | } | 1594 | } |
1584 | 1595 | ||
1585 | return false; | 1596 | return false; |
@@ -1650,6 +1661,7 @@ static int logi_dj_probe(struct hid_device *hdev, | |||
1650 | case recvr_type_dj: no_dj_interfaces = 3; break; | 1661 | case recvr_type_dj: no_dj_interfaces = 3; break; |
1651 | case recvr_type_hidpp: no_dj_interfaces = 2; break; | 1662 | case recvr_type_hidpp: no_dj_interfaces = 2; break; |
1652 | case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break; | 1663 | case recvr_type_gaming_hidpp: no_dj_interfaces = 3; break; |
1664 | case recvr_type_mouse_only: no_dj_interfaces = 2; break; | ||
1653 | case recvr_type_27mhz: no_dj_interfaces = 2; break; | 1665 | case recvr_type_27mhz: no_dj_interfaces = 2; break; |
1654 | case recvr_type_bluetooth: no_dj_interfaces = 2; break; | 1666 | case recvr_type_bluetooth: no_dj_interfaces = 2; break; |
1655 | } | 1667 | } |
@@ -1823,10 +1835,10 @@ static const struct hid_device_id logi_dj_receivers[] = { | |||
1823 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | 1835 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, |
1824 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2), | 1836 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2), |
1825 | .driver_data = recvr_type_dj}, | 1837 | .driver_data = recvr_type_dj}, |
1826 | { /* Logitech Nano (non DJ) receiver */ | 1838 | { /* Logitech Nano mouse only receiver */ |
1827 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | 1839 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, |
1828 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER), | 1840 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER), |
1829 | .driver_data = recvr_type_hidpp}, | 1841 | .driver_data = recvr_type_mouse_only}, |
1830 | { /* Logitech Nano (non DJ) receiver */ | 1842 | { /* Logitech Nano (non DJ) receiver */ |
1831 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | 1843 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, |
1832 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2), | 1844 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2), |