diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 13:23:47 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 13:23:47 -0400 | 
| commit | 9fc377799bc9bfd8d5cb35d0d1ea2e2458cbdbb3 (patch) | |
| tree | fe93603b4e33dd50ff5f95ff769a0748b230cdf9 /drivers/usb/core/quirks.c | |
| parent | 5e23ae49960d05f578a73ecd19749c45af682c2b (diff) | |
| parent | e387ef5c47ddeaeaa3cbdc54424cdb7a28dae2c0 (diff) | |
Merge tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg Kroah-Hartman:
 "Here's the big USB patch set for the 3.6-rc1 merge window.
  Lots of little changes in here, primarily for gadget controllers and
  drivers.  There's some scsi changes that I think also went in through
  the scsi tree, but they merge just fine.  All of these patches have
  been in the linux-next tree for a while now.
  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Fix up trivial conflicts in include/scsi/scsi_device.h (same libata
conflict that Jeff had already encountered)
* tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (207 commits)
  usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams
  usb: Add quirk detection based on interface information
  usb: s3c-hsotg: Add header file protection macros in s3c-hsotg.h
  USB: ehci-s5p: Add vbus setup function to the s5p ehci glue layer
  USB: add USB_VENDOR_AND_INTERFACE_INFO() macro
  USB: notify phy when root hub port connect change
  USB: remove 8 bytes of padding from usb_host_interface on 64 bit builds
  USB: option: add ZTE MF821D
  USB: sierra: QMI mode MC7710 moved to qcserial
  USB: qcserial: adding Sierra Wireless devices
  USB: qcserial: support generic Qualcomm serial ports
  USB: qcserial: make probe more flexible
  USB: qcserial: centralize probe exit path
  USB: qcserial: consolidate usb_set_interface calls
  USB: ehci-s5p: Add support for device tree
  USB: ohci-exynos: Add support for device tree
  USB: ehci-omap: fix compile failure(v1)
  usb: host: tegra: pass correct pointer in ehci_setup()
  USB: ehci-fsl: Update ifdef check to work on 64-bit ppc
  USB: serial: keyspan: Removed unrequired parentheses.
  ...
Diffstat (limited to 'drivers/usb/core/quirks.c')
| -rw-r--r-- | drivers/usb/core/quirks.c | 151 | 
1 files changed, 88 insertions, 63 deletions
| diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 32d3adc315f5..f15501f4c585 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
| @@ -15,17 +15,22 @@ | |||
| 15 | #include <linux/usb/quirks.h> | 15 | #include <linux/usb/quirks.h> | 
| 16 | #include "usb.h" | 16 | #include "usb.h" | 
| 17 | 17 | ||
| 18 | /* List of quirky USB devices. Please keep this list ordered by: | 18 | /* Lists of quirky USB devices, split in device quirks and interface quirks. | 
| 19 | * Device quirks are applied at the very beginning of the enumeration process, | ||
| 20 | * right after reading the device descriptor. They can thus only match on device | ||
| 21 | * information. | ||
| 22 | * | ||
| 23 | * Interface quirks are applied after reading all the configuration descriptors. | ||
| 24 | * They can match on both device and interface information. | ||
| 25 | * | ||
| 26 | * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as | ||
| 27 | * interface quirks, as they only influence the enumeration process which is run | ||
| 28 | * before processing the interface quirks. | ||
| 29 | * | ||
| 30 | * Please keep the lists ordered by: | ||
| 19 | * 1) Vendor ID | 31 | * 1) Vendor ID | 
| 20 | * 2) Product ID | 32 | * 2) Product ID | 
| 21 | * 3) Class ID | 33 | * 3) Class ID | 
| 22 | * | ||
| 23 | * as we want specific devices to be overridden first, and only after that, any | ||
| 24 | * class specific quirks. | ||
| 25 | * | ||
| 26 | * Right now the logic aborts if it finds a valid device in the table, we might | ||
| 27 | * want to change that in the future if it turns out that a whole class of | ||
| 28 | * devices is broken... | ||
| 29 | */ | 34 | */ | 
| 30 | static const struct usb_device_id usb_quirk_list[] = { | 35 | static const struct usb_device_id usb_quirk_list[] = { | 
| 31 | /* CBM - Flash disk */ | 36 | /* CBM - Flash disk */ | 
| @@ -38,53 +43,23 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
| 38 | /* Creative SB Audigy 2 NX */ | 43 | /* Creative SB Audigy 2 NX */ | 
| 39 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 40 | 45 | ||
| 41 | /* Logitech Webcam C200 */ | 46 | /* Logitech Quickcam Fusion */ | 
| 42 | { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, | 47 | { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 43 | |||
| 44 | /* Logitech Webcam C250 */ | ||
| 45 | { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 46 | |||
| 47 | /* Logitech Webcam C300 */ | ||
| 48 | { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 49 | |||
| 50 | /* Logitech Webcam B/C500 */ | ||
| 51 | { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 52 | |||
| 53 | /* Logitech Webcam C600 */ | ||
| 54 | { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 55 | |||
| 56 | /* Logitech Webcam Pro 9000 */ | ||
| 57 | { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 58 | 48 | ||
| 59 | /* Logitech Webcam C905 */ | 49 | /* Logitech Quickcam Orbit MP */ | 
| 60 | { USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME }, | 50 | { USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 61 | 51 | ||
| 62 | /* Logitech Webcam C210 */ | 52 | /* Logitech Quickcam Pro for Notebook */ | 
| 63 | { USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME }, | 53 | { USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 64 | 54 | ||
| 65 | /* Logitech Webcam C260 */ | 55 | /* Logitech Quickcam Pro 5000 */ | 
| 66 | { USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME }, | 56 | { USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 67 | 57 | ||
| 68 | /* Logitech Webcam C310 */ | 58 | /* Logitech Quickcam OEM Dell Notebook */ | 
| 69 | { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, | 59 | { USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 70 | 60 | ||
| 71 | /* Logitech Webcam C910 */ | 61 | /* Logitech Quickcam OEM Cisco VT Camera II */ | 
| 72 | { USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME }, | 62 | { USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME }, | 
| 73 | |||
| 74 | /* Logitech Webcam C160 */ | ||
| 75 | { USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 76 | |||
| 77 | /* Logitech Webcam C270 */ | ||
| 78 | { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 79 | |||
| 80 | /* Logitech Quickcam Pro 9000 */ | ||
| 81 | { USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 82 | |||
| 83 | /* Logitech Quickcam E3500 */ | ||
| 84 | { USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 85 | |||
| 86 | /* Logitech Quickcam Vision Pro */ | ||
| 87 | { USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 88 | 63 | ||
| 89 | /* Logitech Harmony 700-series */ | 64 | /* Logitech Harmony 700-series */ | 
| 90 | { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, | 65 | { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, | 
| @@ -156,16 +131,57 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
| 156 | { } /* terminating entry must be last */ | 131 | { } /* terminating entry must be last */ | 
| 157 | }; | 132 | }; | 
| 158 | 133 | ||
| 159 | static const struct usb_device_id *find_id(struct usb_device *udev) | 134 | static const struct usb_device_id usb_interface_quirk_list[] = { | 
| 135 | /* Logitech UVC Cameras */ | ||
| 136 | { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), | ||
| 137 | .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 138 | |||
| 139 | { } /* terminating entry must be last */ | ||
| 140 | }; | ||
| 141 | |||
| 142 | static bool usb_match_any_interface(struct usb_device *udev, | ||
| 143 | const struct usb_device_id *id) | ||
| 160 | { | 144 | { | 
| 161 | const struct usb_device_id *id = usb_quirk_list; | 145 | unsigned int i; | 
| 162 | 146 | ||
| 163 | for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || | 147 | for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) { | 
| 164 | id->driver_info; id++) { | 148 | struct usb_host_config *cfg = &udev->config[i]; | 
| 165 | if (usb_match_device(udev, id)) | 149 | unsigned int j; | 
| 166 | return id; | 150 | |
| 151 | for (j = 0; j < cfg->desc.bNumInterfaces; ++j) { | ||
| 152 | struct usb_interface_cache *cache; | ||
| 153 | struct usb_host_interface *intf; | ||
| 154 | |||
| 155 | cache = cfg->intf_cache[j]; | ||
| 156 | if (cache->num_altsetting == 0) | ||
| 157 | continue; | ||
| 158 | |||
| 159 | intf = &cache->altsetting[0]; | ||
| 160 | if (usb_match_one_id_intf(udev, intf, id)) | ||
| 161 | return true; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 168 | static u32 __usb_detect_quirks(struct usb_device *udev, | ||
| 169 | const struct usb_device_id *id) | ||
| 170 | { | ||
| 171 | u32 quirks = 0; | ||
| 172 | |||
| 173 | for (; id->match_flags; id++) { | ||
| 174 | if (!usb_match_device(udev, id)) | ||
| 175 | continue; | ||
| 176 | |||
| 177 | if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) && | ||
| 178 | !usb_match_any_interface(udev, id)) | ||
| 179 | continue; | ||
| 180 | |||
| 181 | quirks |= (u32)(id->driver_info); | ||
| 167 | } | 182 | } | 
| 168 | return NULL; | 183 | |
| 184 | return quirks; | ||
| 169 | } | 185 | } | 
| 170 | 186 | ||
| 171 | /* | 187 | /* | 
| @@ -173,14 +189,10 @@ static const struct usb_device_id *find_id(struct usb_device *udev) | |||
| 173 | */ | 189 | */ | 
| 174 | void usb_detect_quirks(struct usb_device *udev) | 190 | void usb_detect_quirks(struct usb_device *udev) | 
| 175 | { | 191 | { | 
| 176 | const struct usb_device_id *id = usb_quirk_list; | 192 | udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); | 
| 177 | |||
| 178 | id = find_id(udev); | ||
| 179 | if (id) | ||
| 180 | udev->quirks = (u32)(id->driver_info); | ||
| 181 | if (udev->quirks) | 193 | if (udev->quirks) | 
| 182 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", | 194 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", | 
| 183 | udev->quirks); | 195 | udev->quirks); | 
| 184 | 196 | ||
| 185 | /* For the present, all devices default to USB-PERSIST enabled */ | 197 | /* For the present, all devices default to USB-PERSIST enabled */ | 
| 186 | #if 0 /* was: #ifdef CONFIG_PM */ | 198 | #if 0 /* was: #ifdef CONFIG_PM */ | 
| @@ -197,3 +209,16 @@ void usb_detect_quirks(struct usb_device *udev) | |||
| 197 | udev->persist_enabled = 1; | 209 | udev->persist_enabled = 1; | 
| 198 | #endif /* CONFIG_PM */ | 210 | #endif /* CONFIG_PM */ | 
| 199 | } | 211 | } | 
| 212 | |||
| 213 | void usb_detect_interface_quirks(struct usb_device *udev) | ||
| 214 | { | ||
| 215 | u32 quirks; | ||
| 216 | |||
| 217 | quirks = __usb_detect_quirks(udev, usb_interface_quirk_list); | ||
| 218 | if (quirks == 0) | ||
| 219 | return; | ||
| 220 | |||
| 221 | dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n", | ||
| 222 | quirks); | ||
| 223 | udev->quirks |= quirks; | ||
| 224 | } | ||
