diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2019-04-20 14:21:47 +0300 |
---|---|---|
committer | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2019-04-23 19:00:05 +0300 |
commit | 82c0beb858543f56311fd22609771a671081bd2a (patch) | |
tree | b60a21a5ec3814268ee4283a5c36d94efa05a5d1 /drivers/hid/hid-logitech-dj.c | |
parent | c034041284e8f2c7bd377b5cce445ef630ec5458 (diff) | |
download | linux-82c0beb858543f56311fd22609771a671081bd2a.tar.xz |
HID: logitech-dj: remove USB dependency
It is better to rely on the actual content of the report descriptors
to enable or not a HID interface.
While at it, remove the other USB dependency to have a fully USB
agnostic driver.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 68 |
1 files changed, 35 insertions, 33 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index eafe75d55664..23d3e039ebbb 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -25,8 +25,8 @@ #include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> -#include <linux/usb.h> #include <linux/kfifo.h> +#include <linux/delay.h> #include <asm/unaligned.h> #include "hid-ids.h" @@ -378,8 +378,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, { /* Called in delayed work context */ struct hid_device *djrcv_hdev = djrcv_dev->hdev; - struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent); - struct usb_device *usbdev = interface_to_usbdev(intf); struct hid_device *dj_hiddev; struct dj_device *dj_dev; @@ -412,7 +410,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->dev.parent = &djrcv_hdev->dev; dj_hiddev->bus = BUS_USB; - dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); + dj_hiddev->vendor = djrcv_hdev->vendor; dj_hiddev->product = (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB] << 8) | @@ -423,7 +421,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; - usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); + memcpy(dj_hiddev->phys, djrcv_hdev->phys, sizeof(djrcv_hdev->phys)); snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys)); @@ -1008,23 +1006,44 @@ static int logi_dj_raw_event(struct hid_device *hdev, static int logi_dj_probe(struct hid_device *hdev, const struct hid_device_id *id) { - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct hid_report_enum *rep_enum; + struct hid_report *rep; struct dj_receiver_dev *djrcv_dev; + bool has_hidpp = false; int retval; - dbg_hid("%s called for ifnum %d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); + /* + * Call to usbhid to fetch the HID descriptors of the current + * interface subsequently call to the hid/hid-core to parse the + * fetched descriptors. + */ + retval = hid_parse(hdev); + if (retval) { + dev_err(&hdev->dev, + "%s:parse failed\n", __func__); + return retval; + } - /* Ignore interfaces 0 and 1, they will not carry any data, dont create - * any hid_device for them */ - if (intf->cur_altsetting->desc.bInterfaceNumber != - LOGITECH_DJ_INTERFACE_NUMBER) { - dbg_hid("%s: ignoring ifnum %d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - return -ENODEV; + rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* + * Check for the HID++ application. + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ + list_for_each_entry(rep, &rep_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; } - /* Treat interface 2 */ + /* + * Ignore interfaces without DJ/HID++ collection, they will not carry + * any data, dont create any hid_device for them. + */ + if (!has_hidpp) + return -ENODEV; + + /* Treat DJ/HID++ interface */ djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL); if (!djrcv_dev) { @@ -1045,22 +1064,6 @@ static int logi_dj_probe(struct hid_device *hdev, } hid_set_drvdata(hdev, djrcv_dev); - /* Call to usbhid to fetch the HID descriptors of interface 2 and - * subsequently call to the hid/hid-core to parse the fetched - * descriptors, this will in turn create the hidraw and hiddev nodes - * for interface 2 of the receiver */ - retval = hid_parse(hdev); - if (retval) { - dev_err(&hdev->dev, - "%s:parse of interface 2 failed\n", __func__); - goto hid_parse_fail; - } - - if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, - 0, DJREPORT_SHORT_LENGTH - 1)) { - retval = -ENODEV; - goto hid_parse_fail; - } /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ @@ -1107,7 +1110,6 @@ switch_to_dj_mode_fail: hid_hw_stop(hdev); hid_hw_start_fail: -hid_parse_fail: kfifo_free(&djrcv_dev->notif_fifo); kfree(djrcv_dev); return retval; |