# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.612 -> 1.613
# drivers/usb/core/usb.c 1.61 -> 1.62
# drivers/usb/core/Makefile 1.5 -> 1.6
# (new) -> 1.2 drivers/usb/core/message.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/05/30 [EMAIL PROTECTED] 1.613
# USB: Move synchronous message passing code from usb.c to message.c
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- a/drivers/usb/core/Makefile Fri May 31 16:47:05 2002
+++ b/drivers/usb/core/Makefile Fri May 31 16:47:05 2002
@@ -2,9 +2,9 @@
# Makefile for USB Core files and filesystem
#
-export-objs := usb.o hcd.o urb.o
+export-objs := usb.o hcd.o urb.o message.o
-usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o
+usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o
ifeq ($(CONFIG_USB_DEVICEFS),y)
usbcore-objs += devio.o inode.o drivers.o devices.o
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/message.c Fri May 31 16:47:05 2002
@@ -0,0 +1,661 @@
+/*
+ * message.c - synchronous message handling
+ */
+
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/byteorder.h>
+
+struct usb_api_data {
+ wait_queue_head_t wqh;
+ int done;
+};
+
+static void usb_api_blocking_completion(struct urb *urb)
+{
+ struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+
+ awd->done = 1;
+ wmb();
+ wake_up(&awd->wqh);
+}
+
+// Starts urb and waits for completion or timeout
+static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct usb_api_data awd;
+ int status;
+
+ init_waitqueue_head(&awd.wqh);
+ awd.done = 0;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&awd.wqh, &wait);
+
+ urb->context = &awd;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+ // something went wrong
+ usb_free_urb(urb);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&awd.wqh, &wait);
+ return status;
+ }
+
+ while (timeout && !awd.done)
+ {
+ timeout = schedule_timeout(timeout);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ rmb();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&awd.wqh, &wait);
+
+ if (!timeout && !awd.done) {
+ if (urb->status != -EINPROGRESS) { /* No callback?!! */
+ printk(KERN_ERR "usb: raced timeout, "
+ "pipe 0x%x status %d time left %d\n",
+ urb->pipe, urb->status, timeout);
+ status = urb->status;
+ } else {
+ printk("usb_control/bulk_msg: timeout\n");
+ usb_unlink_urb(urb); // remove urb safely
+ status = -ETIMEDOUT;
+ }
+ } else
+ status = urb->status;
+
+ if (actual_length)
+ *actual_length = urb->actual_length;
+
+ usb_free_urb(urb);
+ return status;
+}
+
+/*-------------------------------------------------------------------*/
+// returns status (negative) or length (positive)
+int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+ struct usb_ctrlrequest *cmd, void *data, int len, int
+timeout)
+{
+ struct urb *urb;
+ int retv;
+ int length;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
+ usb_api_blocking_completion, 0);
+
+ retv = usb_start_wait_urb(urb, timeout, &length);
+ if (retv < 0)
+ return retv;
+ else
+ return length;
+}
+
+/**
+ * usb_control_msg - Builds a control urb, sends it off and waits for completion
+ * @dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @request: USB message request value
+ * @requesttype: USB message request type value
+ * @value: USB message value
+ * @index: USB message index value
+ * @data: pointer to the data to send
+ * @size: length in bytes of the data to send
+ * @timeout: time in jiffies to wait for the message to complete before
+ * timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple control message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns the number of bytes transferred, otherwise a
+negative error number.
+ *
+ * Don't use this function from within an interrupt context, like a
+ * bottom half handler. If you need an asynchronous message, or need to send
+ * a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8
+requesttype,
+ __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+ struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest),
+GFP_KERNEL);
+ int ret;
+
+ if (!dr)
+ return -ENOMEM;
+
+ dr->bRequestType= requesttype;
+ dr->bRequest = request;
+ dr->wValue = cpu_to_le16p(&value);
+ dr->wIndex = cpu_to_le16p(&index);
+ dr->wLength = cpu_to_le16p(&size);
+
+ //dbg("usb_control_msg");
+
+ ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
+
+ kfree(dr);
+
+ return ret;
+}
+
+
+/**
+ * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred in
+bytes
+ * @timeout: time in jiffies to wait for the message to complete before
+ * timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple bulk message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.
+ * The number of actual bytes transferred will be stored in the
+ * actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a
+ * bottom half handler. If you need an asynchronous message, or need to
+ * send a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+ void *data, int len, int *actual_length, int timeout)
+{
+ struct urb *urb;
+
+ if (len < 0)
+ return -EINVAL;
+
+ urb=usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+
+ FILL_BULK_URB(urb, usb_dev, pipe, data, len,
+ usb_api_blocking_completion, 0);
+
+ return usb_start_wait_urb(urb,timeout,actual_length);
+}
+
+/**
+ * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
+ * @dev: the device whose descriptor is being retrieved
+ * @type: the descriptor type (USB_DT_*)
+ * @index: the number of the descriptor
+ * @buf: where to put the descriptor
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Gets a USB descriptor. Convenience functions exist to simplify
+ * getting some types of descriptors. Use
+ * usb_get_device_descriptor() for USB_DT_DEVICE,
+ * and usb_get_string() or usb_string() for USB_DT_STRING.
+ * Configuration descriptors (USB_DT_CONFIG) are part of the device
+ * structure, at least for the current configuration.
+ * In addition to a number of USB-standard descriptors, some
+ * devices also use class-specific or vendor-specific descriptors.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns the number of bytes received on success, or else the status code
+ * returned by the underlying usb_control_msg() call.
+ */
+int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
+index, void *buf, int size)
+{
+ int i = 5;
+ int result;
+
+ memset(buf,0,size); // Make sure we parse really received data
+
+ while (i--) {
+ /* retries if the returned length was 0; flakey device */
+ 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;
+ }
+ return result;
+}
+
+/**
+ * usb_get_string - gets a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @langid: code for language chosen (from string descriptor zero)
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
+ * in little-endian byte order).
+ * The usb_string() function will often be a convenient way to turn
+ * these strings into kernel-printable form.
+ *
+ * Strings may be referenced in device, configuration, interface, or other
+ * descriptors, and could also be used in vendor-specific ways.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * 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)
+{
+ 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);
+}
+
+/**
+ * usb_get_device_descriptor - (re)reads the device descriptor
+ * @dev: the device whose device descriptor is being updated
+ * Context: !in_interrupt ()
+ *
+ * Updates the copy of the device descriptor stored in the device structure,
+ * which dedicates space for this purpose. Note that several fields are
+ * converted to the host CPU's byte order: the USB version (bcdUSB), and
+ * vendors product and version fields (idVendor, idProduct, and bcdDevice).
+ * That lets device drivers compare against non-byteswapped constants.
+ *
+ * There's normally no need to use this call, although some devices
+ * will change their descriptors after events like updating firmware.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns the number of bytes received on success, or else the status code
+ * returned by the underlying usb_control_msg() call.
+ */
+int usb_get_device_descriptor(struct usb_device *dev)
+{
+ int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
+ sizeof(dev->descriptor));
+ if (ret >= 0) {
+ le16_to_cpus(&dev->descriptor.bcdUSB);
+ le16_to_cpus(&dev->descriptor.idVendor);
+ le16_to_cpus(&dev->descriptor.idProduct);
+ le16_to_cpus(&dev->descriptor.bcdDevice);
+ }
+ return ret;
+}
+
+/**
+ * usb_get_status - issues a GET_STATUS call
+ * @dev: the device whose status is being checked
+ * @type: USB_RECIP_*; for device, interface, or endpoint
+ * @target: zero (for device), else interface or endpoint number
+ * @data: pointer to two bytes of bitmap data
+ * Context: !in_interrupt ()
+ *
+ * Returns device, interface, or endpoint status. Normally only of
+ * interest to see if the device is self powered, or has enabled the
+ * remote wakeup facility; or whether a bulk or interrupt endpoint
+ * is halted ("stalled").
+ *
+ * Bits in these status bitmaps are set using the SET_FEATURE request,
+ * and cleared using the CLEAR_FEATURE request. The usb_clear_halt()
+ * function should be used to clear halt ("stall") status.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns the number of bytes received on success, or else the status code
+ * returned by the underlying usb_control_msg() call.
+ */
+int usb_get_status(struct usb_device *dev, int type, int target, void *data)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
+ HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for config/altsetting reconfig.
+void usb_set_maxpacket(struct usb_device *dev)
+{
+ int i, b;
+
+ for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
+ struct usb_interface *ifp = dev->actconfig->interface + i;
+ struct usb_interface_descriptor *as = ifp->altsetting +
+ifp->act_altsetting;
+ struct usb_endpoint_descriptor *ep = as->endpoint;
+ int e;
+
+ for (e=0; e<as->bNumEndpoints; e++) {
+ b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_CONTROL) { /* Control =>
+bidirectional */
+ dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+ dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+ }
+ else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
+ if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
+ dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+ }
+ else {
+ if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
+ dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+ }
+ }
+ }
+}
+
+/**
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ * Context: !in_interrupt ()
+ *
+ * This is used to clear halt conditions for bulk and interrupt endpoints,
+ * as reported by URB completion status. Endpoints that are halted are
+ * sometimes referred to as being "stalled". Such endpoints are unable
+ * to transmit or receive data until the halt status is cleared. Any URBs
+ * queued queued for such an endpoint should normally be unlinked before
+ * clearing the halt condition.
+ *
+ * Note that control and isochronous endpoints don't halt, although control
+ * endpoints report "protocol stall" (for unsupported requests) using the
+ * same status code used to report a true stall.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_clear_halt(struct usb_device *dev, int pipe)
+{
+ int result;
+ __u16 status;
+ unsigned char *buffer;
+ int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
+
+/*
+ if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
+ return 0;
+*/
+
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
+ HZ * USB_CTRL_SET_TIMEOUT);
+
+ /* don't clear if failed */
+ if (result < 0)
+ return result;
+
+ buffer = kmalloc(sizeof(status), GFP_KERNEL);
+ if (!buffer) {
+ err("unable to allocate memory for configuration descriptors");
+ return -ENOMEM;
+ }
+
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
+ // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
+ buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
+
+ memcpy(&status, buffer, sizeof(status));
+ kfree(buffer);
+
+ if (result < 0)
+ return result;
+
+ if (le16_to_cpu(status) & 1)
+ return -EPIPE; /* still halted */
+
+ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+ /* toggle is reset on clear */
+
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+
+ return 0;
+}
+
+/**
+ * usb_set_interface - Makes a particular alternate setting be current
+ * @dev: the device whose interface is being updated
+ * @interface: the interface being updated
+ * @alternate: the setting being chosen.
+ * Context: !in_interrupt ()
+ *
+ * This is used to enable data transfers on interfaces that may not
+ * be enabled by default. Not all devices support such configurability.
+ *
+ * Within any given configuration, each interface may have several
+ * alternative settings. These are often used to control levels of
+ * bandwidth consumption. For example, the default setting for a high
+ * speed interrupt endpoint may not send more than about 4KBytes per
+ * microframe, and isochronous endpoints may never be part of a an
+ * interface's default setting. To access such bandwidth, alternate
+ * interface setting must be made current.
+ *
+ * Note that in the Linux USB subsystem, bandwidth associated with
+ * an endpoint in a given alternate setting is not reserved until an
+ * is submitted that needs that bandwidth. Some other operating systems
+ * allocate bandwidth early, when a configuration is chosen.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+{
+ struct usb_interface *iface;
+ struct usb_interface_descriptor *iface_as;
+ int i, ret;
+
+ iface = usb_ifnum_to_if(dev, interface);
+ if (!iface) {
+ warn("selecting invalid interface %d", interface);
+ return -EINVAL;
+ }
+
+ /* 9.4.10 says devices don't need this, if the interface
+ only has one alternate setting */
+ if (iface->num_altsetting == 1) {
+ dbg("ignoring set_interface for dev %d, iface %d, alt %d",
+ dev->devnum, interface, alternate);
+ return 0;
+ }
+
+ if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
+ interface, NULL, 0, HZ * 5)) < 0)
+ return ret;
+
+ iface->act_altsetting = alternate;
+
+ /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
+ *
+ * Note:
+ * Despite EP0 is always present in all interfaces/AS, the list of
+ * endpoints from the descriptor does not contain EP0. Due to its
+ * omnipresence one might expect EP0 being considered "affected" by
+ * any SetInterface request and hence assume toggles need to be reset.
+ * However, EP0 toggles are re-synced for every individual transfer
+ * during the SETUP stage - hence EP0 toggles are "don't care" here.
+ */
+
+ iface_as = &iface->altsetting[alternate];
+ for (i = 0; i < iface_as->bNumEndpoints; i++) {
+ u8 ep = iface_as->endpoint[i].bEndpointAddress;
+
+ usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep),
+0);
+ }
+
+ /* usb_set_maxpacket() sets the maxpacket size for all EP in all
+ * interfaces but it shouldn't do any harm here: we have changed
+ * the AS for the requested interface only, hence for unaffected
+ * interfaces it's just re-application of still-valid values.
+ */
+ usb_set_maxpacket(dev);
+ return 0;
+}
+
+/**
+ * usb_set_configuration - Makes a particular device setting be current
+ * @dev: the device whose configuration is being updated
+ * @configuration: the configuration being chosen.
+ * Context: !in_interrupt ()
+ *
+ * This is used to enable non-default device modes. Not all devices
+ * support this kind of configurability. By default, configuration
+ * zero is selected after enumeration; many devices only have a single
+ * configuration.
+ *
+ * USB devices may support one or more configurations, which affect
+ * power consumption and the functionality available. For example,
+ * the default configuration is limited to using 100mA of bus power,
+ * so that when certain device functionality requires more power,
+ * and the device is bus powered, that functionality will be in some
+ * non-default device configuration. Other device modes may also be
+ * reflected as configuration options, such as whether two ISDN
+ * channels are presented as independent 64Kb/s interfaces or as one
+ * bonded 128Kb/s interface.
+ *
+ * Note that USB has an additional level of device configurability,
+ * associated with interfaces. That configurability is accessed using
+ * usb_set_interface().
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_set_configuration(struct usb_device *dev, int configuration)
+{
+ int i, ret;
+ struct usb_config_descriptor *cp = NULL;
+
+ for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
+ if (dev->config[i].bConfigurationValue == configuration) {
+ cp = &dev->config[i];
+ break;
+ }
+ }
+ if (!cp) {
+ warn("selecting invalid configuration %d", configuration);
+ return -EINVAL;
+ }
+
+ if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+ NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
+ return ret;
+
+ dev->actconfig = cp;
+ dev->toggle[0] = 0;
+ dev->toggle[1] = 0;
+ usb_set_maxpacket(dev);
+
+ return 0;
+}
+
+
+/**
+ * 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_get_string(dev, 0, 0, tbuf, 4);
+ if (err < 0) {
+ err("error getting string descriptor 0 (error=%d)", err);
+ goto errout;
+ } else if (tbuf[0] < 4) {
+ err("string descriptor 0 too short");
+ err = -EINVAL;
+ goto errout;
+ } else {
+ dev->have_langid = -1;
+ dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+ /* always use the first langid listed */
+ dbg("USB device number %d default language ID 0x%x",
+ dev->devnum, dev->string_langid);
+ }
+ }
+
+ /*
+ * Just ask for a maximum length string and then take the length
+ * that was returned.
+ */
+ err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
+ 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);
+// synchronous control message convenience routines
+EXPORT_SYMBOL(usb_get_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
+EXPORT_SYMBOL(usb_get_status);
+EXPORT_SYMBOL(usb_get_string);
+EXPORT_SYMBOL(usb_string);
+EXPORT_SYMBOL(usb_clear_halt);
+EXPORT_SYMBOL(usb_set_configuration);
+EXPORT_SYMBOL(usb_set_interface);
+
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c Fri May 31 16:47:05 2002
+++ b/drivers/usb/core/usb.c Fri May 31 16:47:05 2002
@@ -1015,189 +1015,6 @@
}
-/*-------------------------------------------------------------------*
- * SYNCHRONOUS CALLS *
- *-------------------------------------------------------------------*/
-
-struct usb_api_data {
- wait_queue_head_t wqh;
- int done;
-};
-
-static void usb_api_blocking_completion(struct urb *urb)
-{
- struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-
- awd->done = 1;
- wmb();
- wake_up(&awd->wqh);
-}
-
-// Starts urb and waits for completion or timeout
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct usb_api_data awd;
- int status;
-
- init_waitqueue_head(&awd.wqh);
- awd.done = 0;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&awd.wqh, &wait);
-
- urb->context = &awd;
- status = usb_submit_urb(urb, GFP_KERNEL);
- if (status) {
- // something went wrong
- usb_free_urb(urb);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&awd.wqh, &wait);
- return status;
- }
-
- while (timeout && !awd.done)
- {
- timeout = schedule_timeout(timeout);
- set_current_state(TASK_UNINTERRUPTIBLE);
- rmb();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&awd.wqh, &wait);
-
- if (!timeout && !awd.done) {
- if (urb->status != -EINPROGRESS) { /* No callback?!! */
- printk(KERN_ERR "usb: raced timeout, "
- "pipe 0x%x status %d time left %d\n",
- urb->pipe, urb->status, timeout);
- status = urb->status;
- } else {
- printk("usb_control/bulk_msg: timeout\n");
- usb_unlink_urb(urb); // remove urb safely
- status = -ETIMEDOUT;
- }
- } else
- status = urb->status;
-
- if (actual_length)
- *actual_length = urb->actual_length;
-
- usb_free_urb(urb);
- return status;
-}
-
-/*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
- struct usb_ctrlrequest *cmd, void *data, int len, int
timeout)
-{
- struct urb *urb;
- int retv;
- int length;
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
- usb_api_blocking_completion, 0);
-
- retv = usb_start_wait_urb(urb, timeout, &length);
- if (retv < 0)
- return retv;
- else
- return length;
-}
-
-/**
- * usb_control_msg - Builds a control urb, sends it off and waits for completion
- * @dev: pointer to the usb device to send the message to
- * @pipe: endpoint "pipe" to send the message to
- * @request: USB message request value
- * @requesttype: USB message request type value
- * @value: USB message value
- * @index: USB message index value
- * @data: pointer to the data to send
- * @size: length in bytes of the data to send
- * @timeout: time in jiffies to wait for the message to complete before
- * timing out (if 0 the wait is forever)
- * Context: !in_interrupt ()
- *
- * This function sends a simple control message to a specified endpoint
- * and waits for the message to complete, or timeout.
- *
- * If successful, it returns the number of bytes transferred, otherwise a
negative error number.
- *
- * Don't use this function from within an interrupt context, like a
- * bottom half handler. If you need an asynchronous message, or need to send
- * a message from within interrupt context, use usb_submit_urb()
- */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8
requesttype,
- __u16 value, __u16 index, void *data, __u16 size, int timeout)
-{
- struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest),
GFP_KERNEL);
- int ret;
-
- if (!dr)
- return -ENOMEM;
-
- dr->bRequestType= requesttype;
- dr->bRequest = request;
- dr->wValue = cpu_to_le16p(&value);
- dr->wIndex = cpu_to_le16p(&index);
- dr->wLength = cpu_to_le16p(&size);
-
- //dbg("usb_control_msg");
-
- ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
-
- kfree(dr);
-
- return ret;
-}
-
-
-/**
- * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- * @usb_dev: pointer to the usb device to send the message to
- * @pipe: endpoint "pipe" to send the message to
- * @data: pointer to the data to send
- * @len: length in bytes of the data to send
- * @actual_length: pointer to a location to put the actual length transferred in
bytes
- * @timeout: time in jiffies to wait for the message to complete before
- * timing out (if 0 the wait is forever)
- * Context: !in_interrupt ()
- *
- * This function sends a simple bulk message to a specified endpoint
- * and waits for the message to complete, or timeout.
- *
- * If successful, it returns 0, otherwise a negative error number.
- * The number of actual bytes transferred will be stored in the
- * actual_length paramater.
- *
- * Don't use this function from within an interrupt context, like a
- * bottom half handler. If you need an asynchronous message, or need to
- * send a message from within interrupt context, use usb_submit_urb()
- */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout)
-{
- struct urb *urb;
-
- if (len < 0)
- return -EINVAL;
-
- urb=usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
-
- FILL_BULK_URB(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, 0);
-
- return usb_start_wait_urb(urb,timeout,actual_length);
-}
-
/**
* usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried
@@ -1801,382 +1618,6 @@
0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
}
-/**
- * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
- * @dev: the device whose descriptor is being retrieved
- * @type: the descriptor type (USB_DT_*)
- * @index: the number of the descriptor
- * @buf: where to put the descriptor
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Gets a USB descriptor. Convenience functions exist to simplify
- * getting some types of descriptors. Use
- * usb_get_device_descriptor() for USB_DT_DEVICE,
- * and usb_get_string() or usb_string() for USB_DT_STRING.
- * Configuration descriptors (USB_DT_CONFIG) are part of the device
- * structure, at least for the current configuration.
- * In addition to a number of USB-standard descriptors, some
- * devices also use class-specific or vendor-specific descriptors.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns the number of bytes received on success, or else the status code
- * returned by the underlying usb_control_msg() call.
- */
-int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
index, void *buf, int size)
-{
- int i = 5;
- int result;
-
- memset(buf,0,size); // Make sure we parse really received data
-
- while (i--) {
- /* retries if the returned length was 0; flakey device */
- 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;
- }
- return result;
-}
-
-/**
- * usb_get_string - gets a string descriptor
- * @dev: the device whose string descriptor is being retrieved
- * @langid: code for language chosen (from string descriptor zero)
- * @index: the number of the descriptor
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
- * in little-endian byte order).
- * The usb_string() function will often be a convenient way to turn
- * these strings into kernel-printable form.
- *
- * Strings may be referenced in device, configuration, interface, or other
- * descriptors, and could also be used in vendor-specific ways.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * 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)
-{
- 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);
-}
-
-/**
- * usb_get_device_descriptor - (re)reads the device descriptor
- * @dev: the device whose device descriptor is being updated
- * Context: !in_interrupt ()
- *
- * Updates the copy of the device descriptor stored in the device structure,
- * which dedicates space for this purpose. Note that several fields are
- * converted to the host CPU's byte order: the USB version (bcdUSB), and
- * vendors product and version fields (idVendor, idProduct, and bcdDevice).
- * That lets device drivers compare against non-byteswapped constants.
- *
- * There's normally no need to use this call, although some devices
- * will change their descriptors after events like updating firmware.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns the number of bytes received on success, or else the status code
- * returned by the underlying usb_control_msg() call.
- */
-int usb_get_device_descriptor(struct usb_device *dev)
-{
- int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
- sizeof(dev->descriptor));
- if (ret >= 0) {
- le16_to_cpus(&dev->descriptor.bcdUSB);
- le16_to_cpus(&dev->descriptor.idVendor);
- le16_to_cpus(&dev->descriptor.idProduct);
- le16_to_cpus(&dev->descriptor.bcdDevice);
- }
- return ret;
-}
-
-/**
- * usb_get_status - issues a GET_STATUS call
- * @dev: the device whose status is being checked
- * @type: USB_RECIP_*; for device, interface, or endpoint
- * @target: zero (for device), else interface or endpoint number
- * @data: pointer to two bytes of bitmap data
- * Context: !in_interrupt ()
- *
- * Returns device, interface, or endpoint status. Normally only of
- * interest to see if the device is self powered, or has enabled the
- * remote wakeup facility; or whether a bulk or interrupt endpoint
- * is halted ("stalled").
- *
- * Bits in these status bitmaps are set using the SET_FEATURE request,
- * and cleared using the CLEAR_FEATURE request. The usb_clear_halt()
- * function should be used to clear halt ("stall") status.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns the number of bytes received on success, or else the status code
- * returned by the underlying usb_control_msg() call.
- */
-int usb_get_status(struct usb_device *dev, int type, int target, void *data)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
- HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally, for config/altsetting reconfig.
-void usb_set_maxpacket(struct usb_device *dev)
-{
- int i, b;
-
- for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
- struct usb_interface *ifp = dev->actconfig->interface + i;
- struct usb_interface_descriptor *as = ifp->altsetting +
ifp->act_altsetting;
- struct usb_endpoint_descriptor *ep = as->endpoint;
- int e;
-
- for (e=0; e<as->bNumEndpoints; e++) {
- b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_CONTROL) { /* Control =>
bidirectional */
- dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
- dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
- }
- else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
- if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
- dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
- }
- else {
- if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
- dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
- }
- }
- }
-}
-
-/**
- * usb_clear_halt - tells device to clear endpoint halt/stall condition
- * @dev: device whose endpoint is halted
- * @pipe: endpoint "pipe" being cleared
- * Context: !in_interrupt ()
- *
- * This is used to clear halt conditions for bulk and interrupt endpoints,
- * as reported by URB completion status. Endpoints that are halted are
- * sometimes referred to as being "stalled". Such endpoints are unable
- * to transmit or receive data until the halt status is cleared. Any URBs
- * queued queued for such an endpoint should normally be unlinked before
- * clearing the halt condition.
- *
- * Note that control and isochronous endpoints don't halt, although control
- * endpoints report "protocol stall" (for unsupported requests) using the
- * same status code used to report a true stall.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_clear_halt(struct usb_device *dev, int pipe)
-{
- int result;
- __u16 status;
- unsigned char *buffer;
- int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
-
-/*
- if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
- return 0;
-*/
-
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
- HZ * USB_CTRL_SET_TIMEOUT);
-
- /* don't clear if failed */
- if (result < 0)
- return result;
-
- buffer = kmalloc(sizeof(status), GFP_KERNEL);
- if (!buffer) {
- err("unable to allocate memory for configuration descriptors");
- return -ENOMEM;
- }
-
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
- // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
- buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
-
- memcpy(&status, buffer, sizeof(status));
- kfree(buffer);
-
- if (result < 0)
- return result;
-
- if (le16_to_cpu(status) & 1)
- return -EPIPE; /* still halted */
-
- usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
-
- /* toggle is reset on clear */
-
- usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-
- return 0;
-}
-
-/**
- * usb_set_interface - Makes a particular alternate setting be current
- * @dev: the device whose interface is being updated
- * @interface: the interface being updated
- * @alternate: the setting being chosen.
- * Context: !in_interrupt ()
- *
- * This is used to enable data transfers on interfaces that may not
- * be enabled by default. Not all devices support such configurability.
- *
- * Within any given configuration, each interface may have several
- * alternative settings. These are often used to control levels of
- * bandwidth consumption. For example, the default setting for a high
- * speed interrupt endpoint may not send more than about 4KBytes per
- * microframe, and isochronous endpoints may never be part of a an
- * interface's default setting. To access such bandwidth, alternate
- * interface setting must be made current.
- *
- * Note that in the Linux USB subsystem, bandwidth associated with
- * an endpoint in a given alternate setting is not reserved until an
- * is submitted that needs that bandwidth. Some other operating systems
- * allocate bandwidth early, when a configuration is chosen.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_set_interface(struct usb_device *dev, int interface, int alternate)
-{
- struct usb_interface *iface;
- struct usb_interface_descriptor *iface_as;
- int i, ret;
-
- iface = usb_ifnum_to_if(dev, interface);
- if (!iface) {
- warn("selecting invalid interface %d", interface);
- return -EINVAL;
- }
-
- /* 9.4.10 says devices don't need this, if the interface
- only has one alternate setting */
- if (iface->num_altsetting == 1) {
- dbg("ignoring set_interface for dev %d, iface %d, alt %d",
- dev->devnum, interface, alternate);
- return 0;
- }
-
- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
- interface, NULL, 0, HZ * 5)) < 0)
- return ret;
-
- iface->act_altsetting = alternate;
-
- /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
- *
- * Note:
- * Despite EP0 is always present in all interfaces/AS, the list of
- * endpoints from the descriptor does not contain EP0. Due to its
- * omnipresence one might expect EP0 being considered "affected" by
- * any SetInterface request and hence assume toggles need to be reset.
- * However, EP0 toggles are re-synced for every individual transfer
- * during the SETUP stage - hence EP0 toggles are "don't care" here.
- */
-
- iface_as = &iface->altsetting[alternate];
- for (i = 0; i < iface_as->bNumEndpoints; i++) {
- u8 ep = iface_as->endpoint[i].bEndpointAddress;
-
- usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep),
0);
- }
-
- /* usb_set_maxpacket() sets the maxpacket size for all EP in all
- * interfaces but it shouldn't do any harm here: we have changed
- * the AS for the requested interface only, hence for unaffected
- * interfaces it's just re-application of still-valid values.
- */
- usb_set_maxpacket(dev);
- return 0;
-}
-
-/**
- * usb_set_configuration - Makes a particular device setting be current
- * @dev: the device whose configuration is being updated
- * @configuration: the configuration being chosen.
- * Context: !in_interrupt ()
- *
- * This is used to enable non-default device modes. Not all devices
- * support this kind of configurability. By default, configuration
- * zero is selected after enumeration; many devices only have a single
- * configuration.
- *
- * USB devices may support one or more configurations, which affect
- * power consumption and the functionality available. For example,
- * the default configuration is limited to using 100mA of bus power,
- * so that when certain device functionality requires more power,
- * and the device is bus powered, that functionality will be in some
- * non-default device configuration. Other device modes may also be
- * reflected as configuration options, such as whether two ISDN
- * channels are presented as independent 64Kb/s interfaces or as one
- * bonded 128Kb/s interface.
- *
- * Note that USB has an additional level of device configurability,
- * associated with interfaces. That configurability is accessed using
- * usb_set_interface().
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_set_configuration(struct usb_device *dev, int configuration)
-{
- int i, ret;
- struct usb_config_descriptor *cp = NULL;
-
- for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
- if (dev->config[i].bConfigurationValue == configuration) {
- cp = &dev->config[i];
- break;
- }
- }
- if (!cp) {
- warn("selecting invalid configuration %d", configuration);
- return -EINVAL;
- }
-
- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
- return ret;
-
- dev->actconfig = cp;
- dev->toggle[0] = 0;
- dev->toggle[1] = 0;
- usb_set_maxpacket(dev);
-
- return 0;
-}
// hub-only!! ... and only in reset path, or usb_new_device()
// (used by real hubs and virtual root hubs)
@@ -2280,87 +1721,6 @@
return result;
}
-/**
- * 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_get_string(dev, 0, 0, tbuf, 4);
- if (err < 0) {
- err("error getting string descriptor 0 (error=%d)", err);
- goto errout;
- } else if (tbuf[0] < 4) {
- err("string descriptor 0 too short");
- err = -EINVAL;
- goto errout;
- } else {
- dev->have_langid = -1;
- dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
- /* always use the first langid listed */
- dbg("USB device number %d default language ID 0x%x",
- dev->devnum, dev->string_langid);
- }
- }
-
- /*
- * Just ask for a maximum length string and then take the length
- * that was returned.
- */
- err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
- 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;
-}
-
/*
* By the time we get here, the device has gotten a new device ID
* and is in the default state. We need to identify the thing and
@@ -2615,19 +1975,6 @@
EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_get_string);
-EXPORT_SYMBOL(usb_string);
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_set_configuration);
-EXPORT_SYMBOL(usb_set_interface);
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL");
_______________________________________________________________
Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel