# 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	mochel@osdl.org	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");
