# 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

Reply via email to