diff options
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
-rw-r--r-- | drivers/hid/hid-logitech-hidpp.c | 71 |
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); | |||
146 | static int __hidpp_send_report(struct hid_device *hdev, | 148 | static 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 | ||
1673 | hid_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 | } | ||
1645 | hid_hw_start_fail: | 1679 | hid_hw_start_fail: |
1646 | hid_parse_fail: | 1680 | hid_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 | ||
1663 | static const struct hid_device_id hidpp_devices[] = { | 1699 | static 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 | ||