hid: put usb_interface instead of usb_device into hid->dev
PATCH 1/1 hid: put usb_interface instead of usb_device into hid->dev
The commit 4916b3a57fc94664677d439b911b8aaf86c7ec23 introduced a hid regression between 2.6.19 and 2.6.20-rc1. The device put in input_dev->cdev is now of type usb_device instead of usb_interface.
Before:
Quoted 2 lines
# readlink -f /sys/class/input/input6/event4/device /sys/devices/pci0000:00/0000:00:10.0/usb2/2-1/2-1:1.1
After:
Quoted 2 lines
# readlink -f /sys/class/input/input3/event3/device /sys/devices/pci0000:00/0000:00:10.0/usb1/1-1
This causes breakage:
Quoted 6 lines
# udevinfo -q all -n /dev/input/event3 P: /class/input/input3/event3 N: input/event3 S: input/by-path/pci-1-1--event- E: ID_SERIAL=noserial E: ID_PATH=pci-1-1-
No ID_MODEL, ID_VENDOR, ID_REVISION, ID_TYPE etc etc.
Fix this by assigning the intf->dev into hid->dev, and fixing all the users.
---
I recommend this fix to go to the stable tree before 2.6.20 is released.
drivers/usb/input/hid-core.c +15 -15
@@ -106,18 +106,18 @@ static void hid_reset(struct work_structif (test_bit (HID_CLEAR_HALT , &usbhid->iofl)) {dev_dbg (&usbhid->intf->dev,"clear halt\n" ); - rc =usb_clear_halt (to_usb_device (hid->dev), usbhid->urbin->pipe); + rc =usb_clear_halt (hid_to_usb_dev (hid), usbhid->urbin->pipe);clear_bit (HID_CLEAR_HALT , &usbhid->iofl);hid_start_in (hid); }else if (test_bit (HID_RESET_PENDING , &usbhid->iofl)) {dev_dbg (&usbhid->intf->dev,"resetting device\n" ); - rc = rc_lock =usb_lock_device_for_reset (to_usb_device (hid->dev), usbhid->intf); + rc = rc_lock =usb_lock_device_for_reset (hid_to_usb_dev (hid), usbhid->intf);if (rc_lock >=0 ) { - rc =usb_reset_composite_device (to_usb_device (hid->dev), usbhid->intf); + rc =usb_reset_composite_device (hid_to_usb_dev (hid), usbhid->intf);if (rc_lock) -usb_unlock_device (to_usb_device (hid->dev)); +usb_unlock_device (hid_to_usb_dev (hid)); }clear_bit (HID_RESET_PENDING , &usbhid->iofl); }
@@ -129,8 +129,8 @@ static void hid_reset(struct work_structbreak ;default :err ("can't reset device, %s-%s/input%d, status %d" , -to_usb_device (hid->dev)->bus->bus_name, -to_usb_device (hid->dev)->devpath, +hid_to_usb_dev (hid)->bus->bus_name, +hid_to_usb_dev (hid)->devpath, usbhid->ifnum, rc);/* FALLTHROUGH */ case -EHOSTUNREACH :
@@ -217,8 +217,8 @@ static void hid_irq_in(struct urb *urb)clear_bit (HID_IN_RUNNING , &usbhid->iofl);if (status != -EPERM ) {err ("can't resubmit intr, %s-%s/input%d, status %d" , -to_usb_device (hid->dev)->bus->bus_name, -to_usb_device (hid->dev)->devpath, +hid_to_usb_dev (hid)->bus->bus_name, +hid_to_usb_dev (hid)->devpath, usbhid->ifnum, status);hid_io_error (hid); }
@@ -251,7 +251,7 @@ static int hid_submit_out(struct hid_devhid_output_report (report, usbhid->outbuf); usbhid->urbout->transfer_buffer_length = ((report->size -1 ) >>3 ) +1 + (report->id >0 ); - usbhid->urbout->dev =to_usb_device (hid->dev); + usbhid->urbout->dev =hid_to_usb_dev (hid);dbg ("submitting out urb" );
@@ -276,13 +276,13 @@ static int hid_submit_ctrl(struct hid_de len = ((report->size -1 ) >>3 ) +1 + (report->id >0 );if (dir ==USB_DIR_OUT ) {hid_output_report (report, usbhid->ctrlbuf); - usbhid->urbctrl->pipe =usb_sndctrlpipe (to_usb_device (hid->dev),0 ); + usbhid->urbctrl->pipe =usb_sndctrlpipe (hid_to_usb_dev (hid),0 ); usbhid->urbctrl->transfer_buffer_length = len; }else {int maxpacket, padlen; - usbhid->urbctrl->pipe =usb_rcvctrlpipe (to_usb_device (hid->dev),0 ); - maxpacket =usb_maxpacket (to_usb_device (hid->dev), usbhid->urbctrl->pipe,0 ); + usbhid->urbctrl->pipe =usb_rcvctrlpipe (hid_to_usb_dev (hid),0 ); + maxpacket =usb_maxpacket (hid_to_usb_dev (hid), usbhid->urbctrl->pipe,0 );if (maxpacket >0 ) { padlen = (len + maxpacket -1 ) / maxpacket; padlen *= maxpacket;
@@ -292,7 +292,7 @@ static int hid_submit_ctrl(struct hid_de padlen =0 ; usbhid->urbctrl->transfer_buffer_length = padlen; } - usbhid->urbctrl->dev =to_usb_device (hid->dev); + usbhid->urbctrl->dev =hid_to_usb_dev (hid); usbhid->cr->bRequestType =USB_TYPE_CLASS |USB_RECIP_INTERFACE | dir; usbhid->cr->bRequest = (dir ==USB_DIR_OUT ) ?HID_REQ_SET_REPORT :HID_REQ_GET_REPORT ;
@@ -1187,7 +1187,7 @@ static struct hid_device *usb_hid_config hid->version =le16_to_cpu (hdesc->bcdHID); hid->country = hdesc->bCountryCode; - hid->dev = &dev->dev; + hid->dev = &intf->dev; usbhid->intf = intf; usbhid->ifnum = interface->desc.bInterfaceNumber;
@@ -1282,7 +1282,7 @@ static void hid_disconnect(struct usb_inusb_free_urb (usbhid->urbctrl);usb_free_urb (usbhid->urbout); -hid_free_buffers (to_usb_device (hid->dev), hid); +hid_free_buffers (hid_to_usb_dev (hid), hid);hid_free_device (hid); }
drivers/usb/input/hiddev.c +1 -1
@@ -384,7 +384,7 @@ static int hiddev_ioctl(struct inode *instruct hiddev_list *list = file->private_data;struct hiddev *hiddev = list->hiddev;struct hid_device *hid = hiddev->hid; -struct usb_device *dev =to_usb_device (hid->dev); +struct usb_device *dev =hid_to_usb_dev (hid);struct hiddev_collection_info cinfo;struct hiddev_report_info rinfo;struct hiddev_field_info finfo;
drivers/usb/input/hid-ff.c +3 -2
@@ -33,6 +33,7 @@#include <linux/usb.h> #include <linux/hid.h> +#include "usbhid.h" /* * This table contains pointers to initializers. To add support for new
@@ -70,8 +71,8 @@ static struct hid_ff_initializer inits[]int hid_ff_init (struct hid_device * hid) {struct hid_ff_initializer *init; -int vendor =le16_to_cpu (to_usb_device (hid->dev)->descriptor.idVendor); -int product =le16_to_cpu (to_usb_device (hid->dev)->descriptor.idProduct); +int vendor =le16_to_cpu (hid_to_usb_dev (hid)->descriptor.idVendor); +int product =le16_to_cpu (hid_to_usb_dev (hid)->descriptor.idProduct);for (init = inits; init->idVendor; init++)if (init->idVendor == vendor && init->idProduct == product)
drivers/usb/input/usbhid.h +3 -0
@@ -80,5 +80,8 @@ struct usbhid_device { }; +#define hid_to_usb_dev (hid_dev) \ + container_of(hid_dev->dev->parent, struct usb_device, dev) +#endif
Signature · 1 line
Anssi Hannula
Quoted 3 lines · Anssi Hannula
The commit
4916b3a57fc94664677d439b911b8aaf86c7ec23introduced a hid regression between 2.6.19 and 2.6.20-rc1. The device put ininput_dev->cdevis now of typeusb_deviceinstead ofusb_interface.
Yes, this is apparently a bug. Thanks a lot for the patch.
Quoted 8 lines
Fix this by assigning the
intf->devintohid->dev, and fixing all the users.Signed-off-by Anssi Hannula <[email protected]>---
I recommend this fix to go to the stable tree before 2.6.20 is released.
Looks OK to me. I have queued it in HID tree - I am going to push this upstream in a few days.
Signature · 1 line
Jiri Kosina