diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/storage/uas.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 06409a6ca2f4..52e5ec1b2e8a 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -582,6 +582,34 @@ static struct usb_device_id uas_usb_ids[] = { }; MODULE_DEVICE_TABLE(usb, uas_usb_ids); +static int uas_is_interface(struct usb_host_interface *intf) +{ + return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE && + intf->desc.bInterfaceSubClass == USB_SC_SCSI && + intf->desc.bInterfaceProtocol == USB_PR_UAS); +} + +static int uas_switch_interface(struct usb_device *udev, + struct usb_interface *intf) +{ + int i; + + if (uas_is_interface(intf->cur_altsetting)) + return 0; + + for (i = 0; i < intf->num_altsetting; i++) { + struct usb_host_interface *alt = &intf->altsetting[i]; + if (alt == intf->cur_altsetting) + continue; + if (uas_is_interface(alt)) + return usb_set_interface(udev, + alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); + } + + return -ENODEV; +} + static void uas_configure_endpoints(struct uas_dev_info *devinfo) { struct usb_host_endpoint *eps[4] = { }; @@ -655,13 +683,8 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) struct uas_dev_info *devinfo; struct usb_device *udev = interface_to_usbdev(intf); - if (id->bInterfaceProtocol == 0x50) { - int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -/* XXX: Shouldn't assume that 1 is the alternative we want */ - int ret = usb_set_interface(udev, ifnum, 1); - if (ret) - return -ENODEV; - } + if (uas_switch_interface(udev, intf)) + return -ENODEV; devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL); if (!devinfo) |