aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-logitech-hidpp.c71
3 files changed, 57 insertions, 16 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a694f67a..190260c52adc 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1902,6 +1902,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1902 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, 1902 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
1903 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, 1903 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
1904 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) }, 1904 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
1905 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
1905 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, 1906 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
1906 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, 1907 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
1907 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, 1908 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ac1feea51be3..269e758d450d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -619,6 +619,7 @@
619#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 619#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
620#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 620#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
621#define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f 621#define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f
622#define USB_DEVICE_ID_LOGITECH_G920_WHEEL 0xc262
622#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 623#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
623#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 624#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
624#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287 625#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 0f53dc8c79b1..98b8f096d7ee 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -49,11 +49,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
49#define HIDPP_QUIRK_CLASS_WTP BIT(0) 49#define HIDPP_QUIRK_CLASS_WTP BIT(0)
50#define HIDPP_QUIRK_CLASS_M560 BIT(1) 50#define HIDPP_QUIRK_CLASS_M560 BIT(1)
51#define HIDPP_QUIRK_CLASS_K400 BIT(2) 51#define HIDPP_QUIRK_CLASS_K400 BIT(2)
52#define HIDPP_QUIRK_CLASS_G920 BIT(3)
52 53
53/* bits 2..20 are reserved for classes */ 54/* bits 2..20 are reserved for classes */
54#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) 55#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
55#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) 56#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
56#define HIDPP_QUIRK_NO_HIDINPUT BIT(23) 57#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
58#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
57 59
58#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \ 60#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \
59 HIDPP_QUIRK_CONNECT_EVENTS) 61 HIDPP_QUIRK_CONNECT_EVENTS)
@@ -146,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
146static int __hidpp_send_report(struct hid_device *hdev, 148static int __hidpp_send_report(struct hid_device *hdev,
147 struct hidpp_report *hidpp_report) 149 struct hidpp_report *hidpp_report)
148{ 150{
151 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
149 int fields_count, ret; 152 int fields_count, ret;
150 153
154 hidpp = hid_get_drvdata(hdev);
155
151 switch (hidpp_report->report_id) { 156 switch (hidpp_report->report_id) {
152 case REPORT_ID_HIDPP_SHORT: 157 case REPORT_ID_HIDPP_SHORT:
153 fields_count = HIDPP_REPORT_SHORT_LENGTH; 158 fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -168,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
168 */ 173 */
169 hidpp_report->device_index = 0xff; 174 hidpp_report->device_index = 0xff;
170 175
171 ret = hid_hw_raw_request(hdev, hidpp_report->report_id, 176 if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
172 (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT, 177 ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, fields_count);
173 HID_REQ_SET_REPORT); 178 } else {
179 ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
180 (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
181 HID_REQ_SET_REPORT);
182 }
174 183
175 return ret == fields_count ? 0 : -1; 184 return ret == fields_count ? 0 : -1;
176} 185}
@@ -1430,10 +1439,12 @@ static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying)
1430 else 1439 else
1431 name = hidpp_get_device_name(hidpp); 1440 name = hidpp_get_device_name(hidpp);
1432 1441
1433 if (!name) 1442 if (!name) {
1434 hid_err(hdev, "unable to retrieve the name of the device"); 1443 hid_err(hdev, "unable to retrieve the name of the device");
1435 else 1444 } else {
1445 dbg_hid("HID++: Got name: %s\n", name);
1436 snprintf(hdev->name, sizeof(hdev->name), "%s", name); 1446 snprintf(hdev->name, sizeof(hdev->name), "%s", name);
1447 }
1437 1448
1438 kfree(name); 1449 kfree(name);
1439} 1450}
@@ -1596,6 +1607,25 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1596 goto hid_parse_fail; 1607 goto hid_parse_fail;
1597 } 1608 }
1598 1609
1610 if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
1611 connect_mask &= ~HID_CONNECT_HIDINPUT;
1612
1613 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
1614 ret = hid_hw_start(hdev, connect_mask);
1615 if (ret) {
1616 hid_err(hdev, "hw start failed\n");
1617 goto hid_hw_start_fail;
1618 }
1619 ret = hid_hw_open(hdev);
1620 if (ret < 0) {
1621 dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
1622 __func__, ret);
1623 hid_hw_stop(hdev);
1624 goto hid_hw_start_fail;
1625 }
1626 }
1627
1628
1599 /* Allow incoming packets */ 1629 /* Allow incoming packets */
1600 hid_device_io_start(hdev); 1630 hid_device_io_start(hdev);
1601 1631
@@ -1604,8 +1634,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1604 if (!connected) { 1634 if (!connected) {
1605 ret = -ENODEV; 1635 ret = -ENODEV;
1606 hid_err(hdev, "Device not connected"); 1636 hid_err(hdev, "Device not connected");
1607 hid_device_io_stop(hdev); 1637 goto hid_hw_open_failed;
1608 goto hid_parse_fail;
1609 } 1638 }
1610 1639
1611 hid_info(hdev, "HID++ %u.%u device connected.\n", 1640 hid_info(hdev, "HID++ %u.%u device connected.\n",
@@ -1618,19 +1647,18 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1618 if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) { 1647 if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
1619 ret = wtp_get_config(hidpp); 1648 ret = wtp_get_config(hidpp);
1620 if (ret) 1649 if (ret)
1621 goto hid_parse_fail; 1650 goto hid_hw_open_failed;
1622 } 1651 }
1623 1652
1624 /* Block incoming packets */ 1653 /* Block incoming packets */
1625 hid_device_io_stop(hdev); 1654 hid_device_io_stop(hdev);
1626 1655
1627 if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) 1656 if (!(hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
1628 connect_mask &= ~HID_CONNECT_HIDINPUT; 1657 ret = hid_hw_start(hdev, connect_mask);
1629 1658 if (ret) {
1630 ret = hid_hw_start(hdev, connect_mask); 1659 hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
1631 if (ret) { 1660 goto hid_hw_start_fail;
1632 hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); 1661 }
1633 goto hid_hw_start_fail;
1634 } 1662 }
1635 1663
1636 if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) { 1664 if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
@@ -1642,6 +1670,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
1642 1670
1643 return ret; 1671 return ret;
1644 1672
1673hid_hw_open_failed:
1674 hid_device_io_stop(hdev);
1675 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
1676 hid_hw_close(hdev);
1677 hid_hw_stop(hdev);
1678 }
1645hid_hw_start_fail: 1679hid_hw_start_fail:
1646hid_parse_fail: 1680hid_parse_fail:
1647 cancel_work_sync(&hidpp->work); 1681 cancel_work_sync(&hidpp->work);
@@ -1655,9 +1689,11 @@ static void hidpp_remove(struct hid_device *hdev)
1655{ 1689{
1656 struct hidpp_device *hidpp = hid_get_drvdata(hdev); 1690 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
1657 1691
1692 if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)
1693 hid_hw_close(hdev);
1694 hid_hw_stop(hdev);
1658 cancel_work_sync(&hidpp->work); 1695 cancel_work_sync(&hidpp->work);
1659 mutex_destroy(&hidpp->send_mutex); 1696 mutex_destroy(&hidpp->send_mutex);
1660 hid_hw_stop(hdev);
1661} 1697}
1662 1698
1663static const struct hid_device_id hidpp_devices[] = { 1699static const struct hid_device_id hidpp_devices[] = {
@@ -1685,6 +1721,9 @@ static const struct hid_device_id hidpp_devices[] = {
1685 1721
1686 { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, 1722 { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
1687 USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, 1723 USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
1724
1725 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
1726 .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
1688 {} 1727 {}
1689}; 1728};
1690 1729