summaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2019-06-05 08:44:08 -0400
committerBenjamin Tissoires <benjamin.tissoires@redhat.com>2019-06-05 09:16:26 -0400
commit3ed224e273ac5880eeab4c3043a6b06b0478dd56 (patch)
treec8bea1442142b118902a0795a1d9cd4a027a85b7 /drivers/hid
parentf9482dabfd1686987cc6044e06ae0e4c05915518 (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.c42
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
882static void logi_hidpp_dev_conn_notif_equad(struct hidpp_event *hidpp_report, 883static 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),