X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fmessage.c;h=98695c68d68745a8be2177c5ec214f22c718e96a;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=6304f2750f15e29d484d31f34a23b28070fde094;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 6304f2750..98695c68d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -91,8 +91,8 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, if (!urb) return -ENOMEM; - usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, - usb_api_blocking_completion, 0); + usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, + len, usb_api_blocking_completion, NULL); retv = usb_start_wait_urb(urb, timeout, &length); if (retv < 0) @@ -190,7 +190,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, return -ENOMEM; usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, 0); + usb_api_blocking_completion, NULL); return usb_start_wait_urb(urb,timeout,actual_length); } @@ -203,11 +203,11 @@ static void sg_clean (struct usb_sg_request *io) while (io->entries--) usb_free_urb (io->urbs [io->entries]); kfree (io->urbs); - io->urbs = 0; + io->urbs = NULL; } if (io->dev->dev.dma_mask != 0) usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); - io->dev = 0; + io->dev = NULL; } static void sg_complete (struct urb *urb, struct pt_regs *regs) @@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) * unlink pending urbs so they won't rx/tx bad data. */ for (i = 0, found = 0; i < io->entries; i++) { - if (!io->urbs [i]) + if (!io->urbs [i] || !io->urbs [i]->dev) continue; if (found) { status = usb_unlink_urb (io->urbs [i]); @@ -260,7 +260,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) found = 1; } } - urb->dev = 0; + urb->dev = NULL; /* on the last completion, signal usb_sg_wait() */ io->bytes += urb->actual_length; @@ -337,7 +337,7 @@ int usb_sg_init ( if (io->entries <= 0) return io->entries; - io->count = 0; + io->count = io->entries; io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); if (!io->urbs) goto nomem; @@ -347,7 +347,7 @@ int usb_sg_init ( if (usb_pipein (pipe)) urb_flags |= URB_SHORT_NOT_OK; - for (i = 0; i < io->entries; i++, io->count = i) { + for (i = 0; i < io->entries; i++) { unsigned len; io->urbs [i] = usb_alloc_urb (0, mem_flags); @@ -356,7 +356,7 @@ int usb_sg_init ( goto nomem; } - io->urbs [i]->dev = 0; + io->urbs [i]->dev = NULL; io->urbs [i]->pipe = pipe; io->urbs [i]->interval = period; io->urbs [i]->transfer_flags = urb_flags; @@ -459,7 +459,7 @@ void usb_sg_wait (struct usb_sg_request *io) case -ENXIO: // hc didn't queue this one case -EAGAIN: case -ENOMEM: - io->urbs [i]->dev = 0; + io->urbs[i]->dev = NULL; retval = 0; i--; yield (); @@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io) /* fail any uncompleted urbs */ default: - spin_lock_irq (&io->lock); - io->count -= entries - i; - if (io->status == -EINPROGRESS) - io->status = retval; - if (io->count == 0) - complete (&io->complete); - spin_unlock_irq (&io->lock); - - io->urbs [i]->dev = 0; + io->urbs [i]->dev = NULL; io->urbs [i]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } spin_lock_irq (&io->lock); - if (retval && io->status == -ECONNRESET) + if (retval && (io->status == 0 || io->status == -ECONNRESET)) io->status = retval; } + io->count -= entries - i; + if (io->count == 0) + complete (&io->complete); spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. @@ -566,22 +561,24 @@ void usb_sg_cancel (struct usb_sg_request *io) */ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) { - int i = 5; + int i; int result; memset(buf,0,size); // Make sure we parse really received data - while (i--) { + for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ - if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (type << 8) + index, 0, buf, size, - HZ * USB_CTRL_GET_TIMEOUT)) > 0 - || result != -EPIPE) - break; - - dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result); - result = -ENOMSG; + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); + if (result == 0 || result == -EPIPE) + continue; + if (result > 1 && ((u8 *)buf)[1] != type) { + result = -EPROTO; + continue; + } + break; } return result; } @@ -608,12 +605,128 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ -int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +int usb_get_string(struct usb_device *dev, unsigned short langid, + unsigned char index, void *buf, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, - HZ * USB_CTRL_GET_TIMEOUT); + int i; + int result; + + for (i = 0; i < 3; ++i) { + /* retry on length 0 or stall; some devices are flakey */ + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); + if (!(result == 0 || result == -EPIPE)) + break; + } + return result; +} + +static int usb_string_sub(struct usb_device *dev, unsigned int langid, + unsigned int index, unsigned char *buf) +{ + int rc; + + /* Try to read the string descriptor by asking for the maximum + * possible number of bytes */ + rc = usb_get_string(dev, langid, index, buf, 255); + + /* If that failed try to read the descriptor length, then + * ask for just that many bytes */ + if (rc < 0) { + rc = usb_get_string(dev, langid, index, buf, 2); + if (rc == 2) + rc = usb_get_string(dev, langid, index, buf, buf[0]); + } + + if (rc >= 0) { + /* There might be extra junk at the end of the descriptor */ + if (buf[0] < rc) + rc = buf[0]; + if (rc < 2) + rc = -EINVAL; + } + return rc; +} + +/** + * usb_string - returns ISO 8859-1 version of a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * This converts the UTF-16LE encoded strings returned by devices, from + * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones + * that are more usable in most kernel contexts. Note that all characters + * in the chosen descriptor that can't be encoded using ISO-8859-1 + * are converted to the question mark ("?") character, and this function + * chooses strings in the first language supported by the device. + * + * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit + * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, + * and is appropriate for use many uses of English and several other + * Western European languages. (But it doesn't include the "Euro" symbol.) + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns length of the string (>= 0) or usb_control_msg status (< 0). + */ +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + unsigned char *tbuf; + int err; + unsigned int u, idx; + + if (size <= 0 || !buf || !index) + return -EINVAL; + buf[0] = 0; + tbuf = kmalloc(256, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + /* get langid for strings if it's not yet known */ + if (!dev->have_langid) { + err = usb_string_sub(dev, 0, 0, tbuf); + if (err < 0) { + dev_err (&dev->dev, + "string descriptor 0 read error: %d\n", + err); + goto errout; + } else if (err < 4) { + dev_err (&dev->dev, "string descriptor 0 too short\n"); + err = -EINVAL; + goto errout; + } else { + dev->have_langid = -1; + dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + /* always use the first langid listed */ + dev_dbg (&dev->dev, "default language 0x%04x\n", + dev->string_langid); + } + } + + err = usb_string_sub(dev, dev->string_langid, index, tbuf); + if (err < 0) + goto errout; + + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non ISO-8859-1 character */ + else + buf[idx++] = tbuf[u]; + } + buf[idx] = 0; + err = idx; + + errout: + kfree(tbuf); + return err; } /** @@ -741,9 +854,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe) * the copy in usb-storage, for as long as we need two copies. */ - /* toggle was reset by the clear, then ep was reactivated */ + /* toggle was reset by the clear */ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); - usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); return 0; } @@ -757,9 +869,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe) * Deallocates hcd/hardware state for this endpoint ... and nukes all * pending urbs. * - * If the HCD hasn't registered a disable() function, this marks the - * endpoint as halted and sets its maxpacket size to 0 to prevent - * further submissions. + * If the HCD hasn't registered a disable() function, this sets the + * endpoint's maxpacket size to 0 to prevent further submissions. */ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) { @@ -768,13 +879,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) else { unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; - if (usb_endpoint_out(epaddr)) { - usb_endpoint_halt(dev, epnum, 1); + if (usb_endpoint_out(epaddr)) dev->epmaxpacketout[epnum] = 0; - } else { - usb_endpoint_halt(dev, epnum, 0); + else dev->epmaxpacketin[epnum] = 0; - } } } @@ -817,7 +925,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) usb_disable_endpoint(dev, i + USB_DIR_IN); } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) @@ -830,6 +937,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) interface = dev->actconfig->interface[i]; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); + usb_remove_sysfs_intf_files(interface); device_del (&interface->dev); } @@ -840,9 +948,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) put_device (&dev->actconfig->interface[i]->dev); dev->actconfig->interface[i] = NULL; } - dev->actconfig = 0; + dev->actconfig = NULL; if (dev->state == USB_STATE_CONFIGURED) - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); } } @@ -852,9 +960,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) * @dev: the device whose interface is being enabled * @epd: pointer to the endpoint descriptor * - * Marks the endpoint as running, resets its toggle, and stores - * its maxpacket value. For control endpoints, both the input - * and output sides are handled. + * Resets the endpoint toggle and stores its maxpacket value. + * For control endpoints, both the input and output sides are handled. */ void usb_enable_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *epd) @@ -866,12 +973,10 @@ void usb_enable_endpoint(struct usb_device *dev, USB_ENDPOINT_XFER_CONTROL); if (usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 1); usb_settoggle(dev, epnum, 1, 0); dev->epmaxpacketout[epnum] = maxsize; } if (!usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 0); usb_settoggle(dev, epnum, 0, 0); dev->epmaxpacketin[epnum] = maxsize; } @@ -934,6 +1039,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) int ret; int manual = 0; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + iface = usb_ifnum_to_if(dev, interface); if (!iface) { dev_dbg(&dev->dev, "selecting invalid interface %d\n", @@ -1031,6 +1139,9 @@ int usb_reset_configuration(struct usb_device *dev) int i, retval; struct usb_host_config *config; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + /* caller must own dev->serialize (config won't change) * and the usb bus readlock (so driver bindings are stable); * so calls during probe() are fine @@ -1047,12 +1158,11 @@ int usb_reset_configuration(struct usb_device *dev) config->desc.bConfigurationValue, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); if (retval < 0) { - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); return retval; } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* re-init hc/hcd interface/endpoint state */ for (i = 0; i < config->desc.bNumInterfaces; i++) { @@ -1081,7 +1191,7 @@ static void release_interface(struct device *dev) struct usb_interface_cache *intfc = altsetting_to_usb_interface_cache(intf->altsetting); - kref_put(&intfc->ref); + kref_put(&intfc->ref, usb_release_interface_cache); kfree(intf); } @@ -1144,6 +1254,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp && configuration == 0) dev_warn(&dev->dev, "config 0 descriptor??\n"); + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + /* Allocate memory for new interfaces before doing anything else, * so that if we run out then nothing will have changed. */ n = nintf = 0; @@ -1185,9 +1298,9 @@ free_interfaces: dev->actconfig = cp; if (!cp) - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); else { - dev->state = USB_STATE_CONFIGURED; + usb_set_device_state(dev, USB_STATE_CONFIGURED); /* Initialize the new interface structures and the * hc/hcd/usbcore interface/endpoint state. @@ -1259,102 +1372,6 @@ free_interfaces: return ret; } -/** - * usb_string - returns ISO 8859-1 version of a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * This converts the UTF-16LE encoded strings returned by devices, from - * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones - * that are more usable in most kernel contexts. Note that all characters - * in the chosen descriptor that can't be encoded using ISO-8859-1 - * are converted to the question mark ("?") character, and this function - * chooses strings in the first language supported by the device. - * - * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit - * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, - * and is appropriate for use many uses of English and several other - * Western European languages. (But it doesn't include the "Euro" symbol.) - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns length of the string (>= 0) or usb_control_msg status (< 0). - */ -int usb_string(struct usb_device *dev, int index, char *buf, size_t size) -{ - unsigned char *tbuf; - int err, len; - unsigned int u, idx; - - if (size <= 0 || !buf || !index) - return -EINVAL; - buf[0] = 0; - tbuf = kmalloc(256, GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - /* get langid for strings if it's not yet known */ - if (!dev->have_langid) { - err = usb_get_descriptor(dev, USB_DT_STRING, 0, tbuf, 4); - if (err < 0) { - dev_err (&dev->dev, - "string descriptor 0 read error: %d\n", - err); - goto errout; - } else if (err < 4 || tbuf[0] < 4) { - dev_err (&dev->dev, "string descriptor 0 too short\n"); - err = -EINVAL; - goto errout; - } else { - dev->have_langid = -1; - dev->string_langid = tbuf[2] | (tbuf[3]<< 8); - /* always use the first langid listed */ - dev_dbg (&dev->dev, "default language 0x%04x\n", - dev->string_langid); - } - } - - /* - * ask for the length of the string - */ - - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - if (err == -EPIPE) { - dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2); - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - } - if(err<2) - goto errout; - len=tbuf[0]; - - err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - if (err == -EPIPE) { - dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len); - err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - } - if (err < 0) - goto errout; - - size--; /* leave room for trailing NULL char in output buffer */ - for (idx = 0, u = 2; u < err; u += 2) { - if (idx >= size) - break; - if (tbuf[u+1]) /* high byte */ - buf[idx++] = '?'; /* non ISO-8859-1 character */ - else - buf[idx++] = tbuf[u]; - } - buf[idx] = 0; - err = idx; - - errout: - kfree(tbuf); - return err; -} - // synchronous request completion model EXPORT_SYMBOL(usb_control_msg); EXPORT_SYMBOL(usb_bulk_msg);