aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/devio.c189
-rw-r--r--drivers/usb/core/driver.c36
-rw-r--r--drivers/usb/core/hcd-pci.c4
-rw-r--r--drivers/usb/core/hcd.c31
-rw-r--r--drivers/usb/core/hub.c89
-rw-r--r--drivers/usb/core/quirks.c5
-rw-r--r--drivers/usb/core/usb.h14
7 files changed, 193 insertions, 175 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index e3beaf229ee..3af5e2dd1d8 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -86,6 +86,7 @@ struct async {
void __user *userbuffer;
void __user *userurb;
struct urb *urb;
+ unsigned int mem_usage;
int status;
u32 secid;
u8 bulk_addr;
@@ -108,8 +109,44 @@ enum snoop_when {
#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
-#define MAX_USBFS_BUFFER_SIZE 16384
+/* Limit on the total amount of memory we can allocate for transfers */
+static unsigned usbfs_memory_mb = 16;
+module_param(usbfs_memory_mb, uint, 0644);
+MODULE_PARM_DESC(usbfs_memory_mb,
+ "maximum MB allowed for usbfs buffers (0 = no limit)");
+/* Hard limit, necessary to avoid aithmetic overflow */
+#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
+
+static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
+
+/* Check whether it's okay to allocate more memory for a transfer */
+static int usbfs_increase_memory_usage(unsigned amount)
+{
+ unsigned lim;
+
+ /*
+ * Convert usbfs_memory_mb to bytes, avoiding overflows.
+ * 0 means use the hard limit (effectively unlimited).
+ */
+ lim = ACCESS_ONCE(usbfs_memory_mb);
+ if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
+ lim = USBFS_XFER_MAX;
+ else
+ lim <<= 20;
+
+ atomic_add(amount, &usbfs_memory_usage);
+ if (atomic_read(&usbfs_memory_usage) <= lim)
+ return 0;
+ atomic_sub(amount, &usbfs_memory_usage);
+ return -ENOMEM;
+}
+
+/* Memory for a transfer is being deallocated */
+static void usbfs_decrease_memory_usage(unsigned amount)
+{
+ atomic_sub(amount, &usbfs_memory_usage);
+}
static int connected(struct dev_state *ps)
{
@@ -249,10 +286,12 @@ static struct async *alloc_async(unsigned int numisoframes)
static void free_async(struct async *as)
{
put_pid(as->pid);
- put_cred(as->cred);
+ if (as->cred)
+ put_cred(as->cred);
kfree(as->urb->transfer_buffer);
kfree(as->urb->setup_packet);
usb_free_urb(as->urb);
+ usbfs_decrease_memory_usage(as->mem_usage);
kfree(as);
}
@@ -792,9 +831,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
if (wLength > PAGE_SIZE)
return -EINVAL;
+ ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) +
+ sizeof(struct usb_ctrlrequest));
+ if (ret)
+ return ret;
tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
- if (!tbuf)
- return -ENOMEM;
+ if (!tbuf) {
+ ret = -ENOMEM;
+ goto done;
+ }
tmo = ctrl.timeout;
snoop(&dev->dev, "control urb: bRequestType=%02x "
"bRequest=%02x wValue=%04x "
@@ -806,8 +851,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (ctrl.bRequestType & 0x80) {
if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
ctrl.wLength)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
pipe = usb_rcvctrlpipe(dev, 0);
snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0);
@@ -821,15 +866,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
tbuf, max(i, 0));
if ((i > 0) && ctrl.wLength) {
if (copy_to_user(ctrl.data, tbuf, i)) {
- free_page((unsigned long)tbuf);
- return -EFAULT;
+ ret = -EFAULT;
+ goto done;
}
}
} else {
if (ctrl.wLength) {
if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
- free_page((unsigned long)tbuf);
- return -EFAULT;
+ ret = -EFAULT;
+ goto done;
}
}
pipe = usb_sndctrlpipe(dev, 0);
@@ -843,14 +888,18 @@ static int proc_control(struct dev_state *ps, void __user *arg)
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
}
- free_page((unsigned long)tbuf);
if (i < 0 && i != -EPIPE) {
dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
"failed cmd %s rqt %u rq %u len %u ret %d\n",
current->comm, ctrl.bRequestType, ctrl.bRequest,
ctrl.wLength, i);
}
- return i;
+ ret = i;
+ done:
+ free_page((unsigned long) tbuf);
+ usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
+ sizeof(struct usb_ctrlrequest));
+ return ret;
}
static int proc_bulk(struct dev_state *ps, void __user *arg)
@@ -877,15 +926,20 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
return -EINVAL;
len1 = bulk.len;
- if (len1 > MAX_USBFS_BUFFER_SIZE)
+ if (len1 >= USBFS_XFER_MAX)
return -EINVAL;
- if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
- return -ENOMEM;
+ ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
+ if (ret)
+ return ret;
+ if (!(tbuf = kmalloc(len1, GFP_KERNEL))) {
+ ret = -ENOMEM;
+ goto done;
+ }
tmo = bulk.timeout;
if (bulk.ep & 0x80) {
if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
- kfree(tbuf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
@@ -896,15 +950,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
if (!i && len2) {
if (copy_to_user(bulk.data, tbuf, len2)) {
- kfree(tbuf);
- return -EFAULT;
+ ret = -EFAULT;
+ goto done;
}
}
} else {
if (len1) {
if (copy_from_user(tbuf, bulk.data, len1)) {
- kfree(tbuf);
- return -EFAULT;
+ ret = -EFAULT;
+ goto done;
}
}
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
@@ -914,10 +968,11 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
}
+ ret = (i < 0 ? i : len2);
+ done:
kfree(tbuf);
- if (i < 0)
- return i;
- return len2;
+ usbfs_decrease_memory_usage(len1 + sizeof(struct urb));
+ return ret;
}
static int proc_resetep(struct dev_state *ps, void __user *arg)
@@ -1062,7 +1117,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
{
struct usbdevfs_iso_packet_desc *isopkt = NULL;
struct usb_host_endpoint *ep;
- struct async *as;
+ struct async *as = NULL;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int ret, ifnum = -1;
@@ -1095,32 +1150,30 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
}
if (!ep)
return -ENOENT;
+
+ u = 0;
switch(uurb->type) {
case USBDEVFS_URB_TYPE_CONTROL:
if (!usb_endpoint_xfer_control(&ep->desc))
return -EINVAL;
- /* min 8 byte setup packet,
- * max 8 byte setup plus an arbitrary data stage */
- if (uurb->buffer_length < 8 ||
- uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
+ /* min 8 byte setup packet */
+ if (uurb->buffer_length < 8)
return -EINVAL;
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
if (!dr)
return -ENOMEM;
if (copy_from_user(dr, uurb->buffer, 8)) {
- kfree(dr);
- return -EFAULT;
+ ret = -EFAULT;
+ goto error;
}
if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
- kfree(dr);
- return -EINVAL;
+ ret = -EINVAL;
+ goto error;
}
ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
le16_to_cpup(&dr->wIndex));
- if (ret) {
- kfree(dr);
- return ret;
- }
+ if (ret)
+ goto error;
uurb->number_of_packets = 0;
uurb->buffer_length = le16_to_cpup(&dr->wLength);
uurb->buffer += 8;
@@ -1138,6 +1191,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
__le16_to_cpup(&dr->wValue),
__le16_to_cpup(&dr->wIndex),
__le16_to_cpup(&dr->wLength));
+ u = sizeof(struct usb_ctrlrequest);
break;
case USBDEVFS_URB_TYPE_BULK:
@@ -1151,8 +1205,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
goto interrupt_urb;
}
uurb->number_of_packets = 0;
- if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
- return -EINVAL;
break;
case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -1160,8 +1212,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
interrupt_urb:
uurb->number_of_packets = 0;
- if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
- return -EINVAL;
break;
case USBDEVFS_URB_TYPE_ISO:
@@ -1176,50 +1226,53 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
- kfree(isopkt);
- return -EFAULT;
+ ret = -EFAULT;
+ goto error;
}
for (totlen = u = 0; u < uurb->number_of_packets; u++) {
/* arbitrary limit,
* sufficient for USB 2.0 high-bandwidth iso */
if (isopkt[u].length > 8192) {
- kfree(isopkt);
- return -EINVAL;
+ ret = -EINVAL;
+ goto error;
}
totlen += isopkt[u].length;
}
- /* 3072 * 64 microframes */
- if (totlen > 196608) {
- kfree(isopkt);
- return -EINVAL;
- }
+ u *= sizeof(struct usb_iso_packet_descriptor);
uurb->buffer_length = totlen;
break;
default:
return -EINVAL;
}
+
+ if (uurb->buffer_length >= USBFS_XFER_MAX) {
+ ret = -EINVAL;
+ goto error;
+ }
if (uurb->buffer_length > 0 &&
!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
uurb->buffer, uurb->buffer_length)) {
- kfree(isopkt);
- kfree(dr);
- return -EFAULT;
+ ret = -EFAULT;
+ goto error;
}
as = alloc_async(uurb->number_of_packets);
if (!as) {
- kfree(isopkt);
- kfree(dr);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error;
}
+ u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length;
+ ret = usbfs_increase_memory_usage(u);
+ if (ret)
+ goto error;
+ as->mem_usage = u;
+
if (uurb->buffer_length > 0) {
as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
GFP_KERNEL);
if (!as->urb->transfer_buffer) {
- kfree(isopkt);
- kfree(dr);
- free_async(as);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error;
}
/* Isochronous input data may end up being discontiguous
* if some of the packets are short. Clear the buffer so
@@ -1253,6 +1306,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
as->urb->transfer_buffer_length = uurb->buffer_length;
as->urb->setup_packet = (unsigned char *)dr;
+ dr = NULL;
as->urb->start_frame = uurb->start_frame;
as->urb->number_of_packets = uurb->number_of_packets;
if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
@@ -1268,6 +1322,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
totlen += isopkt[u].length;
}
kfree(isopkt);
+ isopkt = NULL;
as->ps = ps;
as->userurb = arg;
if (is_in && uurb->buffer_length > 0)
@@ -1282,8 +1337,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
if (!is_in && uurb->buffer_length > 0) {
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
uurb->buffer_length)) {
- free_async(as);
- return -EFAULT;
+ ret = -EFAULT;
+ goto error;
}
}
snoop_urb(ps->dev, as->userurb, as->urb->pipe,
@@ -1329,10 +1384,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
snoop_urb(ps->dev, as->userurb, as->urb->pipe,
0, ret, COMPLETE, NULL, 0);
async_removepending(as);
- free_async(as);
- return ret;
+ goto error;
}
return 0;
+
+ error:
+ kfree(isopkt);
+ kfree(dr);
+ if (as)
+ free_async(as);
+ return ret;
}
static int proc_submiturb(struct dev_state *ps, void __user *arg)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 45887a0ff87..d40ff956881 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -45,10 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
struct usb_dynid *dynid;
u32 idVendor = 0;
u32 idProduct = 0;
+ unsigned int bInterfaceClass = 0;
int fields = 0;
int retval = 0;
- fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
+ fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,
+ &bInterfaceClass);
if (fields < 2)
return -EINVAL;
@@ -60,6 +62,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
dynid->id.idVendor = idVendor;
dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ if (fields == 3) {
+ dynid->id.bInterfaceClass = (u8)bInterfaceClass;
+ dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
+ }
spin_lock(&dynids->lock);
list_add_tail(&dynid->node, &dynids->list);
@@ -1073,17 +1079,10 @@ static int usb_suspend_interface(struct usb_device *udev,
goto done;
driver = to_usb_driver(intf->dev.driver);
- if (driver->suspend) {
- status = driver->suspend(intf, msg);
- if (status && !PMSG_IS_AUTO(msg))
- dev_err(&intf->dev, "%s error %d\n",
- "suspend", status);
- } else {
- /* Later we will unbind the driver and reprobe */
- intf->needs_binding = 1;
- dev_warn(&intf->dev, "no %s for driver %s?\n",
- "suspend", driver->name);
- }
+ /* at this time we know the driver supports suspend */
+ status = driver->suspend(intf, msg);
+ if (status && !PMSG_IS_AUTO(msg))
+ dev_err(&intf->dev, "suspend error %d\n", status);
done:
dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
@@ -1132,16 +1131,9 @@ static int usb_resume_interface(struct usb_device *udev,
"reset_resume", driver->name);
}
} else {
- if (driver->resume) {
- status = driver->resume(intf);
- if (status)
- dev_err(&intf->dev, "%s error %d\n",
- "resume", status);
- } else {
- intf->needs_binding = 1;
- dev_warn(&intf->dev, "no %s for driver %s?\n",
- "resume", driver->name);
- }
+ status = driver->resume(intf);
+ if (status)
+ dev_err(&intf->dev, "resume error %d\n", status);
}
done:
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index a004db35f6d..d136b8f4c8a 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -453,10 +453,6 @@ static int resume_common(struct device *dev, int event)
pci_set_master(pci_dev);
- clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
- if (hcd->shared_hcd)
- clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
-
if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
if (event != PM_EVENT_AUTO_RESUME)
wait_for_companions(pci_dev, hcd);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 13222d352a6..eb19cba34ac 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -658,7 +658,7 @@ error:
len > offsetof(struct usb_device_descriptor,
bDeviceProtocol))
((struct usb_device_descriptor *) ubuf)->
- bDeviceProtocol = 1;
+ bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT;
}
/* any errors get returned through the urb completion */
@@ -1168,20 +1168,6 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
if (urb->unlinked)
return -EBUSY;
urb->unlinked = status;
-
- /* IRQ setup can easily be broken so that USB controllers
- * never get completion IRQs ... maybe even the ones we need to
- * finish unlinking the initial failed usb_set_address()
- * or device descriptor fetch.
- */
- if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
- dev_warn(hcd->self.controller, "Unlink after no-IRQ? "
- "Controller is probably using the wrong IRQ.\n");
- set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
- if (hcd->shared_hcd)
- set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
- }
-
return 0;
}
EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb);
@@ -1412,11 +1398,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SG;
- if (n != urb->num_sgs) {
- urb->num_sgs = n;
+ urb->num_mapped_sgs = n;
+ if (n != urb->num_sgs)
urb->transfer_flags |=
URB_DMA_SG_COMBINED;
- }
} else if (urb->sg) {
struct scatterlist *sg = urb->sg;
urb->transfer_dma = dma_map_page(
@@ -2148,16 +2133,12 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
*/
local_irq_save(flags);
- if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
+ if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
rc = IRQ_NONE;
- } else if (hcd->driver->irq(hcd) == IRQ_NONE) {
+ else if (hcd->driver->irq(hcd) == IRQ_NONE)
rc = IRQ_NONE;
- } else {
- set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
- if (hcd->shared_hcd)
- set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+ else
rc = IRQ_HANDLED;
- }
local_irq_restore(flags);
return rc;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 79781461eec..79d339e2e70 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -84,7 +84,7 @@ struct usb_hub {
static inline int hub_is_superspeed(struct usb_device *hdev)
{
- return (hdev->descriptor.bDeviceProtocol == 3);
+ return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
}
/* Protect struct usb_device->state and ->children members
@@ -1041,58 +1041,58 @@ static int hub_configure(struct usb_hub *hub,
dev_dbg(hub_dev, "standalone hub\n");
switch (wHubCharacteristics & HUB_CHAR_LPSM) {
- case 0x00:
- dev_dbg(hub_dev, "ganged power switching\n");
- break;
- case 0x01:
- dev_dbg(hub_dev, "individual port power switching\n");
- break;
- case 0x02:
- case 0x03:
- dev_dbg(hub_dev, "no power switching (usb 1.0)\n");
- break;
+ case HUB_CHAR_COMMON_LPSM:
+ dev_dbg(hub_dev, "ganged power switching\n");
+ break;
+ case HUB_CHAR_INDV_PORT_LPSM:
+ dev_dbg(hub_dev, "individual port power switching\n");
+ break;
+ case HUB_CHAR_NO_LPSM:
+ case HUB_CHAR_LPSM:
+ dev_dbg(hub_dev, "no power switching (usb 1.0)\n");
+ break;
}
switch (wHubCharacteristics & HUB_CHAR_OCPM) {
- case 0x00:
- dev_dbg(hub_dev, "global over-current protection\n");
- break;
- case 0x08:
- dev_dbg(hub_dev, "individual port over-current protection\n");
- break;
- case 0x10:
- case 0x18:
- dev_dbg(hub_dev, "no over-current protection\n");
- break;
+ case HUB_CHAR_COMMON_OCPM:
+ dev_dbg(hub_dev, "global over-current protection\n");
+ break;
+ case HUB_CHAR_INDV_PORT_OCPM:
+ dev_dbg(hub_dev, "individual port over-current protection\n");
+ break;
+ case HUB_CHAR_NO_OCPM:
+ case HUB_CHAR_OCPM:
+ dev_dbg(hub_dev, "no over-current protection\n");
+ break;
}
spin_lock_init (&hub->tt.lock);
INIT_LIST_HEAD (&hub->tt.clear_list);
INIT_WORK(&hub->tt.clear_work, hub_tt_work);
switch (hdev->descriptor.bDeviceProtocol) {
- case 0:
- break;
- case 1:
- dev_dbg(hub_dev, "Single TT\n");
- hub->tt.hub = hdev;
- break;
- case 2:
- ret = usb_set_interface(hdev, 0, 1);
- if (ret == 0) {
- dev_dbg(hub_dev, "TT per port\n");
- hub->tt.multi = 1;
- } else
- dev_err(hub_dev, "Using single TT (err %d)\n",
- ret);
- hub->tt.hub = hdev;
- break;
- case 3:
- /* USB 3.0 hubs don't have a TT */
- break;
- default:
- dev_dbg(hub_dev, "Unrecognized hub protocol %d\n",
- hdev->descriptor.bDeviceProtocol);
- break;
+ case USB_HUB_PR_FS:
+ break;
+ case USB_HUB_PR_HS_SINGLE_TT:
+ dev_dbg(hub_dev, "Single TT\n");
+ hub->tt.hub = hdev;
+ break;
+ case USB_HUB_PR_HS_MULTI_TT:
+ ret = usb_set_interface(hdev, 0, 1);
+ if (ret == 0) {
+ dev_dbg(hub_dev, "TT per port\n");
+ hub->tt.multi = 1;
+ } else
+ dev_err(hub_dev, "Using single TT (err %d)\n",
+ ret);
+ hub->tt.hub = hdev;
+ break;
+ case USB_HUB_PR_SS:
+ /* USB 3.0 hubs don't have a TT */
+ break;
+ default:
+ dev_dbg(hub_dev, "Unrecognized hub protocol %d\n",
+ hdev->descriptor.bDeviceProtocol);
+ break;
}
/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
@@ -1360,7 +1360,6 @@ descriptor_error:
return -ENODEV;
}
-/* No BKL needed */
static int
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index ecf12e15a7e..4c65eb6a867 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -117,9 +117,12 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
- /* Guillemot Webcam Hercules Dualpix Exchange*/
+ /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */
{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Guillemot Webcam Hercules Dualpix Exchange*/
+ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 3888778582c..45e8479c377 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -132,20 +132,6 @@ static inline int is_usb_device_driver(struct device_driver *drv)
for_devices;
}
-/* translate USB error codes to codes user space understands */
-static inline int usb_translate_errors(int error_code)
-{
- switch (error_code) {
- case 0:
- case -ENOMEM:
- case -ENODEV:
- return error_code;
- default:
- return -EIO;
- }
-}
-
-
/* for labeling diagnostics */
extern const char *usbcore_name;