diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Sun Feb  8 20:57:49 2004
+++ b/MAINTAINERS	Sun Feb  8 20:57:49 2004
@@ -2239,8 +2239,8 @@
 S:	Supported
 
 USB UHCI DRIVER
-P:	Johannes Erdfelt
-M:	johannes@erdfelt.com
+P:	Alan Stern
+M:	stern@rowland.harvard.edu
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	Sun Feb  8 20:57:49 2004
@@ -204,12 +204,23 @@
 				  int *result_length, u8 cmd_result[])
 {
 	int result, actual_len, i;
-	u8 b[COMMAND_PACKET_SIZE + 4];
-	u8 c[COMMAND_PACKET_SIZE + 4];
+	u8 *b;
+	u8 *c;
+	
+	b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
+	c = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
+	if (!c) {
+		kfree(b);
+		return -ENOMEM;
+	}
 
 	dprintk("%s\n", __FUNCTION__);
 
 	if ((result = down_interruptible(&dec->usb_sem))) {
+		kfree(b);
+		kfree(c);
 		printk("%s: Failed to down usb semaphore.\n", __FUNCTION__);
 		return result;
 	}
@@ -230,22 +241,26 @@
 	}
 
 	result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
-			      sizeof(b), &actual_len, HZ);
+			      COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
 
 	if (result) {
 		printk("%s: command bulk message failed: error %d\n",
 		       __FUNCTION__, result);
 		up(&dec->usb_sem);
+		kfree(b);
+		kfree(c);
 		return result;
 	}
 
 	result = usb_bulk_msg(dec->udev, dec->result_pipe, c,
-			      sizeof(c), &actual_len, HZ);
+			      COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
 
 	if (result) {
 		printk("%s: result bulk message failed: error %d\n",
 		       __FUNCTION__, result);
 		up(&dec->usb_sem);
+		kfree(b);
+		kfree(c);
 		return result;
 	} else {
 		if (debug) {
@@ -262,6 +277,8 @@
 
 		up(&dec->usb_sem);
 
+		kfree(b);
+		kfree(c);
 		return 0;
 	}
 }
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/Makefile	Sun Feb  8 20:57:49 2004
@@ -46,7 +46,6 @@
 obj-$(CONFIG_USB_HPUSBSCSI)	+= image/
 obj-$(CONFIG_USB_MDC800)	+= image/
 obj-$(CONFIG_USB_MICROTEK)	+= image/
-obj-$(CONFIG_USB_SCANNER)	+= image/
 
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/class/cdc-acm.c	Sun Feb  8 20:57:49 2004
@@ -399,6 +399,7 @@
 static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
 {
 	struct acm *acm = tty->driver_data;
+	int stat;
 
 	if (!ACM_READY(acm))
 		return -EINVAL;
@@ -418,8 +419,12 @@
 	acm->writeurb->transfer_buffer_length = count;
 	acm->writeurb->dev = acm->dev;
 
-	if (usb_submit_urb(acm->writeurb, GFP_KERNEL))
+	/* GFP_KERNEL probably works if from_user */
+	stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
+	if (stat < 0) {
 		dbg("usb_submit_urb(write bulk) failed");
+		return stat;
+	}
 
 	return count;
 }
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- a/drivers/usb/core/Makefile	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/core/Makefile	Sun Feb  8 20:57:49 2004
@@ -2,7 +2,7 @@
 # Makefile for USB Core files and filesystem
 #
 
-usbcore-objs	:= usb.o usb-debug.o hub.o hcd.o urb.o message.o \
+usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o \
 			config.o file.o buffer.o driverfs.o
 
 ifeq ($(CONFIG_PCI),y)
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/core/hcd.c	Sun Feb  8 20:57:49 2004
@@ -34,7 +34,10 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/uts.h>			/* for UTS_SYSNAME */
-#include <linux/pci.h>			/* for hcd->pdev and dma addressing */
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <asm/byteorder.h>
 
@@ -1474,16 +1477,16 @@
 	if (hcd->controller->dma_mask) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-			pci_unmap_single (hcd->pdev, urb->setup_dma,
+			dma_unmap_single (hcd->controller, urb->setup_dma,
 					sizeof (struct usb_ctrlrequest),
-					PCI_DMA_TODEVICE);
+					DMA_TO_DEVICE);
 		if (urb->transfer_buffer_length != 0
 			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
-			pci_unmap_single (hcd->pdev, urb->transfer_dma,
+			dma_unmap_single (hcd->controller, urb->transfer_dma,
 					urb->transfer_buffer_length,
 					usb_pipein (urb->pipe)
-					    ? PCI_DMA_FROMDEVICE
-					    : PCI_DMA_TODEVICE);
+					    ? DMA_FROM_DEVICE
+					    : DMA_TO_DEVICE);
 	}
 
 	/* pass ownership to the completion handler */
@@ -1513,7 +1516,9 @@
 		return IRQ_NONE;
 
 	hcd->saw_irq = 1;
-	hcd->driver->irq (hcd, r);
+	if (hcd->driver->irq (hcd, r) == IRQ_NONE)
+		return IRQ_NONE;
+
 	if (hcd->state != start && hcd->state == USB_STATE_HALT)
 		usb_hc_died (hcd);
 	return IRQ_HANDLED;
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/core/hcd.h	Sun Feb  8 20:57:49 2004
@@ -163,7 +163,7 @@
 	const char	*description;	/* "ehci-hcd" etc */
 
 	/* irq handler */
-	void	(*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
+	irqreturn_t	(*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
 
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/core/hub.c	Sun Feb  8 20:57:49 2004
@@ -179,7 +179,7 @@
 hub_clear_tt_buffer (struct usb_device *hub, u16 devinfo, u16 tt)
 {
 	return usb_control_msg (hub, usb_rcvctrlpipe (hub, 0),
-		HUB_CLEAR_TT_BUFFER, USB_DIR_IN | USB_RECIP_OTHER,
+		HUB_CLEAR_TT_BUFFER, USB_RT_PORT,
 		devinfo, tt, 0, 0, HZ);
 }
 
diff -Nru a/drivers/usb/core/usb-debug.c b/drivers/usb/core/usb-debug.c
--- a/drivers/usb/core/usb-debug.c	Sun Feb  8 20:57:49 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,201 +0,0 @@
-/*
- * debug.c - USB debug helper routines.
- *
- * I just want these out of the way where they aren't in your
- * face, but so that you can still use them..
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-static void usb_show_endpoint(struct usb_host_endpoint *endpoint)
-{
-	usb_show_endpoint_descriptor(&endpoint->desc);
-}
-
-static void usb_show_interface(struct usb_host_interface *altsetting)
-{
-	int i;
-
-	usb_show_interface_descriptor(&altsetting->desc);
-
-	for (i = 0; i < altsetting->desc.bNumEndpoints; i++)
-		usb_show_endpoint(altsetting->endpoint + i);
-}
-
-static void usb_show_config(struct usb_host_config *config)
-{
-	int i, j;
-	struct usb_interface *ifp;
-
-	usb_show_config_descriptor(&config->desc);
-	for (i = 0; i < config->desc.bNumInterfaces; i++) {
-		ifp = config->interface[i];
-
-		if (!ifp)
-			break;
-
-		printk("\n  Interface: %d\n", i);
-		for (j = 0; j < ifp->num_altsetting; j++)
-			usb_show_interface(ifp->altsetting + j);
-	}
-}
-
-void usb_show_device(struct usb_device *dev)
-{
-	int i;
-
-	usb_show_device_descriptor(&dev->descriptor);
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
-		usb_show_config(dev->config + i);
-}
-
-/*
- * Parse and show the different USB descriptors.
- */
-void usb_show_device_descriptor(struct usb_device_descriptor *desc)
-{
-	if (!desc)
-	{
-		printk("Invalid USB device descriptor (NULL POINTER)\n");
-		return;
-	}
-	printk("  Length              = %2d%s\n", desc->bLength,
-		desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
-	printk("  DescriptorType      = %02x\n", desc->bDescriptorType);
-
-	printk("  USB version         = %x.%02x\n",
-		desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
-	printk("  Vendor:Product      = %04x:%04x\n",
-		desc->idVendor, desc->idProduct);
-	printk("  MaxPacketSize0      = %d\n", desc->bMaxPacketSize0);
-	printk("  NumConfigurations   = %d\n", desc->bNumConfigurations);
-	printk("  Device version      = %x.%02x\n",
-		desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
-
-	printk("  Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
-		desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
-	switch (desc->bDeviceClass) {
-	case 0:
-		printk("    Per-interface classes\n");
-		break;
-	case USB_CLASS_AUDIO:
-		printk("    Audio device class\n");
-		break;
-	case USB_CLASS_COMM:
-		printk("    Communications class\n");
-		break;
-	case USB_CLASS_HID:
-		printk("    Human Interface Devices class\n");
-		break;
-	case USB_CLASS_PRINTER:
-		printk("    Printer device class\n");
-		break;
-	case USB_CLASS_MASS_STORAGE:
-		printk("    Mass Storage device class\n");
-		break;
-	case USB_CLASS_HUB:
-		printk("    Hub device class\n");
-		break;
-	case USB_CLASS_VENDOR_SPEC:
-		printk("    Vendor class\n");
-		break;
-	default:
-		printk("    Unknown class\n");
-	}
-}
-
-void usb_show_config_descriptor(struct usb_config_descriptor *desc)
-{
-	printk("Configuration:\n");
-	printk("  bLength             = %4d%s\n", desc->bLength,
-		desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
-	printk("  bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("  wTotalLength        = %04x\n", desc->wTotalLength);
-	printk("  bNumInterfaces      =   %02x\n", desc->bNumInterfaces);
-	printk("  bConfigurationValue =   %02x\n", desc->bConfigurationValue);
-	printk("  iConfiguration      =   %02x\n", desc->iConfiguration);
-	printk("  bmAttributes        =   %02x\n", desc->bmAttributes);
-	printk("  bMaxPower            = %4dmA\n", desc->bMaxPower * 2);
-}
-
-void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
-{
-	printk("  Alternate Setting: %2d\n", desc->bAlternateSetting);
-	printk("    bLength             = %4d%s\n", desc->bLength,
-		desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
-	printk("    bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("    bInterfaceNumber    =   %02x\n", desc->bInterfaceNumber);
-	printk("    bAlternateSetting   =   %02x\n", desc->bAlternateSetting);
-	printk("    bNumEndpoints       =   %02x\n", desc->bNumEndpoints);
-	printk("    bInterface Class:SubClass:Protocol =   %02x:%02x:%02x\n",
-		desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
-	printk("    iInterface          =   %02x\n", desc->iInterface);
-}
-
-void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
-{
-	char *LengthCommentString = (desc->bLength ==
-		USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
-		USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
-	char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
-
-	printk("    Endpoint:\n");
-	printk("      bLength             = %4d%s\n",
-		desc->bLength, LengthCommentString);
-	printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("      bEndpointAddress    =   %02x (%s)\n", desc->bEndpointAddress,
-		(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-			USB_ENDPOINT_XFER_CONTROL ? "i/o" :
-		(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
-	printk("      bmAttributes        =   %02x (%s)\n", desc->bmAttributes,
-		EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
-	printk("      wMaxPacketSize      = %04x\n", desc->wMaxPacketSize);
-	printk("      bInterval           =   %02x\n", desc->bInterval);
-
-	/* Audio extensions to the endpoint descriptor */
-	if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
-		printk("      bRefresh            =   %02x\n", desc->bRefresh);
-		printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
-	}
-}
-
-void usb_show_string(struct usb_device *dev, char *id, int index)
-{
-	char *buf;
-
-	if (!index)
-		return;
-	if (!(buf = kmalloc(256, GFP_KERNEL)))
-		return;
-	if (usb_string(dev, index, buf, 256) > 0)
-		dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
-	kfree(buf);
-}
-
-void usb_dump_urb (struct urb *urb)
-{
-	printk ("urb                   :%p\n", urb);
-	printk ("dev                   :%p\n", urb->dev);
-	printk ("pipe                  :%08X\n", urb->pipe);
-	printk ("status                :%d\n", urb->status);
-	printk ("transfer_flags        :%08X\n", urb->transfer_flags);
-	printk ("transfer_buffer       :%p\n", urb->transfer_buffer);
-	printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
-	printk ("actual_length         :%d\n", urb->actual_length);
-	printk ("setup_packet          :%p\n", urb->setup_packet);
-	printk ("start_frame           :%d\n", urb->start_frame);
-	printk ("number_of_packets     :%d\n", urb->number_of_packets);
-	printk ("interval              :%d\n", urb->interval);
-	printk ("error_count           :%d\n", urb->error_count);
-	printk ("context               :%p\n", urb->context);
-	printk ("complete              :%p\n", urb->complete);
-}
-
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/core/usb.c	Sun Feb  8 20:57:49 2004
@@ -984,6 +984,19 @@
 	return retval;
 }
 
+static inline void usb_show_string(struct usb_device *dev, char *id, int index)
+{
+	char *buf;
+
+	if (!index)
+		return;
+	if (!(buf = kmalloc(256, GFP_KERNEL)))
+		return;
+	if (usb_string(dev, index, buf, 256) > 0)
+		dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
+	kfree(buf);
+}
+
 /*
  * By the time we get here, we chose a new device address
  * and is in the default state. We need to identify the thing and
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/gadget/ether.c	Sun Feb  8 20:57:49 2004
@@ -19,7 +19,7 @@
  */
 
 
-#define DEBUG 1
+// #define DEBUG 1
 // #define VERBOSE
 
 #include <linux/config.h>
@@ -885,8 +885,11 @@
 #ifndef	DEV_CONFIG_CDC
 	if (result == 0) {
 		netif_carrier_on (dev->net);
-		if (netif_running (dev->net))
+		if (netif_running (dev->net)) {
+			spin_unlock (&dev->lock);
 			eth_start (dev, GFP_ATOMIC);
+			spin_lock (&dev->lock);
+		}
 	} else {
 		(void) usb_ep_disable (dev->in_ep);
 		dev->in_ep = 0;
@@ -1246,8 +1249,11 @@
 #ifdef	EP_STATUS_NUM
 				issue_start_status (dev);
 #endif
-				if (netif_running (dev->net))
+				if (netif_running (dev->net)) {
+					spin_unlock (&dev->lock);
 					eth_start (dev, GFP_ATOMIC);
+					spin_lock (&dev->lock);
+				}
 			} else {
 				netif_stop_queue (dev->net);
 				netif_carrier_off (dev->net);
@@ -1414,16 +1420,14 @@
 rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
 {
 	struct sk_buff		*skb;
-	int			retval = 0;
+	int			retval = -ENOMEM;
 	size_t			size;
 
 	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
 
 	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
-		defer_kevent (dev, WORK_RX_MEMORY);
-		list_add (&req->list, &dev->rx_reqs);
-		return -ENOMEM;
+		goto enomem;
 	}
 
 	req->buf = skb->data;
@@ -1433,11 +1437,14 @@
 
 	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
 	if (retval == -ENOMEM)
+enomem:
 		defer_kevent (dev, WORK_RX_MEMORY);
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
 		dev_kfree_skb_any (skb);
+		spin_lock (&dev->lock);
 		list_add (&req->list, &dev->rx_reqs);
+		spin_unlock (&dev->lock);
 	}
 	return retval;
 }
@@ -1502,6 +1509,7 @@
 		dev_kfree_skb_any (skb);
 	if (!netif_running (dev->net)) {
 clean:
+		/* nobody reading rx_reqs, so no dev->lock */
 		list_add (&req->list, &dev->rx_reqs);
 		req = 0;
 	}
@@ -1568,19 +1576,26 @@
 static void rx_fill (struct eth_dev *dev, int gfp_flags)
 {
 	struct usb_request	*req;
+	unsigned long		flags;
 
 	clear_bit (WORK_RX_MEMORY, &dev->todo);
 
 	/* fill unused rxq slots with some skb */
+	spin_lock_irqsave (&dev->lock, flags);
 	while (!list_empty (&dev->rx_reqs)) {
 		req = container_of (dev->rx_reqs.next,
 				struct usb_request, list);
 		list_del_init (&req->list);
+		spin_unlock_irqrestore (&dev->lock, flags);
+
 		if (rx_submit (dev, req, gfp_flags) < 0) {
 			defer_kevent (dev, WORK_RX_MEMORY);
 			return;
 		}
+
+		spin_lock_irqsave (&dev->lock, flags);
 	}
+	spin_unlock_irqrestore (&dev->lock, flags);
 }
 
 static void eth_work (void *_dev)
@@ -1616,7 +1631,9 @@
 	}
 	dev->stats.tx_packets++;
 
+	spin_lock (&dev->lock);
 	list_add (&req->list, &dev->tx_reqs);
+	spin_unlock (&dev->lock);
 	dev_kfree_skb_any (skb);
 
 	atomic_dec (&dev->tx_qlen);
@@ -1630,11 +1647,14 @@
 	int			length = skb->len;
 	int			retval;
 	struct usb_request	*req = 0;
+	unsigned long		flags;
 
+	spin_lock_irqsave (&dev->lock, flags);
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
 	list_del (&req->list);
 	if (list_empty (&dev->tx_reqs))
 		netif_stop_queue (net);
+	spin_unlock_irqrestore (&dev->lock, flags);
 
 	/* no buffer copies needed, unless the network stack did it
 	 * or the hardware can't use skb buffers.
@@ -1675,9 +1695,11 @@
 	if (retval) {
 		dev->stats.tx_dropped++;
 		dev_kfree_skb_any (skb);
+		spin_lock_irqsave (&dev->lock, flags);
 		if (list_empty (&dev->tx_reqs))
 			netif_start_queue (net);
 		list_add (&req->list, &dev->tx_reqs);
+		spin_unlock_irqrestore (&dev->lock, flags);
 	}
 	return 0;
 }
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/gadget/file_storage.c	Sun Feb  8 20:57:49 2004
@@ -1,7 +1,7 @@
 /*
  * file_storage.c -- File-backed USB Storage Gadget, for USB development
  *
- * Copyright (C) 2003 Alan Stern
+ * Copyright (C) 2003, 2004 Alan Stern
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -244,7 +244,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"14 January 2004"
+#define DRIVER_VERSION		"26 January 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -435,7 +435,7 @@
 #define LDBG(lun,fmt,args...) \
 	yprintk(lun , KERN_DEBUG , fmt , ## args)
 #define MDBG(fmt,args...) \
-	printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args)
+	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
 #else
 #define DBG(fsg,fmt,args...) \
 	do { } while (0)
@@ -473,7 +473,7 @@
 	yprintk(lun , KERN_INFO , fmt , ## args)
 
 #define MINFO(fmt,args...) \
-	printk(KERN_INFO DRIVER_NAME ": " fmt, ## args)
+	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
 
 
 /*-------------------------------------------------------------------------*/
@@ -848,6 +848,7 @@
 	unsigned int		nluns;
 	struct lun		*luns;
 	struct lun		*curlun;
+	struct completion	lun_released;
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -3771,6 +3772,13 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void lun_release(struct device *dev)
+{
+	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
+
+	complete(&fsg->lun_released);
+}
+
 static void fsg_unbind(struct usb_gadget *gadget)
 {
 	struct fsg_dev		*fsg = get_gadget_data(gadget);
@@ -3782,12 +3790,14 @@
 	clear_bit(REGISTERED, &fsg->atomic_bitflags);
 
 	/* Unregister the sysfs attribute files and the LUNs */
+	init_completion(&fsg->lun_released);
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		if (curlun->registered) {
 			device_remove_file(&curlun->dev, &dev_attr_ro);
 			device_remove_file(&curlun->dev, &dev_attr_file);
-			device_unregister_wait(&curlun->dev);
+			device_unregister(&curlun->dev);
+			wait_for_completion(&fsg->lun_released);
 			curlun->registered = 0;
 		}
 	}
@@ -4140,6 +4150,7 @@
 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
 		else {
 			curlun->registered = 1;
+			curlun->dev.release = lun_release;
 			device_create_file(&curlun->dev, &dev_attr_ro);
 			device_create_file(&curlun->dev, &dev_attr_file);
 		}
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/gadget/net2280.c	Sun Feb  8 20:57:49 2004
@@ -534,7 +534,10 @@
 	}
 
 	/* write just one packet at a time */
-	count = min (ep->ep.maxpacket, total);
+	count = ep->ep.maxpacket;
+	if (count > total)	/* min() cannot be used on a bitfield */
+		count = total;
+
 	VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
 			ep->ep.name, count,
 			(count != ep->ep.maxpacket) ? " (short)" : "",
@@ -2197,7 +2200,8 @@
 		unsigned	len;
 
 		len = req->req.length - req->req.actual;
-		len = min (ep->ep.maxpacket, len);
+		if (len > ep->ep.maxpacket)
+			len = ep->ep.maxpacket;
 		req->req.actual += len;
 
 		/* if we wrote it all, we're usually done */
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.c	Sun Feb  8 20:57:49 2004
@@ -1,6 +1,6 @@
 /*
  * linux/drivers/usb/gadget/pxa2xx_udc.c
- * Intel PXA2xx on-chip full speed USB device controllers
+ * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers
  *
  * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
  * Copyright (C) 2003 Robert Schwebel, Pengutronix
@@ -59,27 +59,26 @@
 
 #include <asm/arch/udc.h>
 
-#include "pxa2xx_udc.h"
-
 
 /*
  * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx
  * series processors.  The UDC for the IXP 4xx series is very similar.
+ * There are fifteen endpoints, in addition to ep0.
  *
  * Such controller drivers work with a gadget driver.  The gadget driver
  * returns descriptors, implements configuration and data protocols used
  * by the host to interact with this device, and allocates endpoints to
  * the different protocol interfaces.  The controller driver virtualizes
  * usb hardware so that the gadget drivers will be more portable.
- *
+ * 
  * This UDC hardware wants to implement a bit too much USB protocol, so
  * it constrains the sorts of USB configuration change events that work.
  * The errata for these chips are misleading; some "fixed" bugs from
  * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
  */
 
-#define	DRIVER_VERSION	"7-Nov-2003"
-#define DRIVER_DESC	"PXA 2xx USB Device Controller driver"
+#define	DRIVER_VERSION	"14-Dec-2003"
+#define	DRIVER_DESC	"PXA 2xx USB Device Controller driver"
 
 
 static const char driver_name [] = "pxa2xx_udc";
@@ -95,6 +94,19 @@
 #define	UDC_PROC_FILE
 #endif
 
+#ifdef CONFIG_ARCH_IXP425
+#undef USE_DMA
+
+/* cpu-specific register addresses are compiled in to this code */
+#ifdef CONFIG_ARCH_PXA
+#error "Can't configure both IXP and PXA"
+#endif
+
+#endif
+
+#include "pxa2xx_udc.h"
+
+
 #ifdef CONFIG_EMBEDDED
 /* few strings, and little code to use them */
 #undef	DEBUG
@@ -215,7 +227,8 @@
 	if (!_ep || !desc || ep->desc || _ep->name == ep0name
 			|| desc->bDescriptorType != USB_DT_ENDPOINT
 			|| ep->bEndpointAddress != desc->bEndpointAddress
-			|| ep->ep.maxpacket < desc->wMaxPacketSize) {
+			|| ep->fifo_size < le16_to_cpu
+						(desc->wMaxPacketSize)) {
 		DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
 		return -EINVAL;
 	}
@@ -230,7 +243,8 @@
 
 	/* hardware _could_ do smaller, but driver doesn't */
 	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-				&& desc->wMaxPacketSize != BULK_FIFO_SIZE)
+				&& le16_to_cpu (desc->wMaxPacketSize)
+						!= BULK_FIFO_SIZE)
 			|| !desc->wMaxPacketSize) {
 		DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
 		return -ERANGE;
@@ -246,6 +260,7 @@
 	ep->dma = -1;
 	ep->stopped = 0;
 	ep->pio_irqs = ep->dma_irqs = 0;
+	ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
 
 	/* flush fifo (mostly for OUT buffers) */
 	pxa2xx_ep_fifo_flush (_ep);
@@ -254,18 +269,18 @@
 
 #ifdef	USE_DMA
 	/* for (some) bulk and ISO endpoints, try to get a DMA channel and
-	 * bind it to the endpoint.  otherwise use PIO.
+	 * bind it to the endpoint.  otherwise use PIO. 
 	 */
 	switch (ep->bmAttributes) {
 	case USB_ENDPOINT_XFER_ISOC:
-		if (desc->wMaxPacketSize % 32)
+		if (le16_to_cpu(desc->wMaxPacketSize) % 32)
 			break;
 		// fall through
 	case USB_ENDPOINT_XFER_BULK:
 		if (!use_dma || !ep->reg_drcmr)
 			break;
 		ep->dma = pxa_request_dma ((char *)_ep->name,
-				(desc->wMaxPacketSize > 64)
+ 				(le16_to_cpu (desc->wMaxPacketSize) > 64)
 					? DMA_PRIO_MEDIUM /* some iso */
 					: DMA_PRIO_LOW,
 				dma_nodesc_handler, ep);
@@ -437,7 +452,7 @@
 {
 	unsigned		max;
 
-	max = ep->desc->wMaxPacketSize;
+	max = le16_to_cpu(ep->desc->wMaxPacketSize);
 	do {
 		unsigned	count;
 		int		is_last, is_short;
@@ -454,13 +469,7 @@
 			else
 				is_last = 1;
 			/* interrupt/iso maxpacket may not fill the fifo */
-			is_short = unlikely (max < ep->ep.maxpacket);
-
-			/* FIXME ep.maxpacket should be the current size,
-			 * modified (for periodic endpoints) when the
-			 * ep is enabled.  do that, re-init as needed,
-			 * and change maxpacket refs accordingly.
-			 */
+			is_short = unlikely (max < ep->fifo_size);
 		}
 
 		DBG(DBG_VERY_NOISY, "wrote %s %d bytes%s%s %d left %p\n",
@@ -598,7 +607,7 @@
 			req->req.actual += min (count, bufferspace);
 		} else /* zlp */
 			count = 0;
-		is_short = (count < ep->desc->wMaxPacketSize);
+		is_short = (count < ep->ep.maxpacket);
 		DBG(DBG_VERY_NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
 			ep->ep.name, udccs, count,
 			is_short ? "/S" : "",
@@ -897,13 +906,14 @@
 	 * we can report per-packet status.  that also helps with dma.
 	 */
 	if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
-			&& req->req.length > ep->desc->wMaxPacketSize))
+			&& req->req.length > le16_to_cpu
+						(ep->desc->wMaxPacketSize)))
 		return -EMSGSIZE;
 
 #ifdef	USE_DMA
 	// FIXME caller may already have done the dma mapping
 	if (ep->dma >= 0) {
-		_req->dma = dma_map_single(&dev->dev.dev,
+		_req->dma = dma_map_single(dev->dev,
 			_req->buf, _req->length,
 			((ep->bEndpointAddress & USB_DIR_IN) != 0)
 				? DMA_TO_DEVICE
@@ -1017,11 +1027,21 @@
 	unsigned long		flags;
 
 	ep = container_of(_ep, struct pxa2xx_ep, ep);
-	req = container_of(_req, struct pxa2xx_request, req);
-	if (!_ep || !_req || ep->ep.name == ep0name)
+	if (!_ep || ep->ep.name == ep0name)
 		return -EINVAL;
 
 	local_irq_save(flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry (req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		local_irq_restore(flags);
+		return -EINVAL;
+	}
+
 #ifdef	USE_DMA
 	if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
 		cancel_dma(ep);
@@ -1034,13 +1054,10 @@
 		}
 	} else
 #endif
-	if (!list_empty(&req->queue))
 		done(ep, req, -ECONNRESET);
-	else
-		req = 0;
-	local_irq_restore(flags);
 
-	return req ? 0 : -EOPNOTSUPP;
+	local_irq_restore(flags);
+	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1386,8 +1403,10 @@
 
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 
+#ifdef	CONFIG_ARCH_PXA
         /* Disable clock for USB device */
         CKEN &= ~CKEN11_USB;
+#endif
 
 	ep0_idle (dev);
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1430,8 +1449,10 @@
 {
 	udc_clear_mask_UDCCR(UDCCR_UDE);
 
+#ifdef	CONFIG_ARCH_PXA
         /* Enable clock for USB device */
         CKEN |= CKEN11_USB;
+#endif
 
 	/* try to clear these bits before we enable the udc */
 	udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
@@ -1590,9 +1611,10 @@
 	local_irq_disable();
 	udc_disable(dev);
 	stop_activity(dev, driver);
+	local_irq_enable();
+
 	driver->unbind(&dev->gadget);
 	dev->driver = 0;
-	local_irq_enable();
 
 	device_del (&dev->gadget.dev);
 	device_remove_file(dev->dev, &dev_attr_function);
@@ -1776,7 +1798,6 @@
 					 * else use AREN (later) not SA|OPR
 					 * USIR0_IR0 acts edge sensitive
 					 */
-					dev->req_pending = 0;
 				}
 				break;
 			/* ... and here, even more ... */
@@ -1853,6 +1874,7 @@
 			/* pxa210/250 erratum 131 for B0/B1 says RNE lies.
 			 * still observed on a pxa255 a0.
 			 */
+			DBG(DBG_VERBOSE, "e131\n");
 			nuke(ep, -EPROTO);
 
 			/* read SETUP data, but don't trust it too much */
@@ -2043,7 +2065,7 @@
 				stop_activity (dev, dev->driver);
 
 			} else {
-				dev_info(&dev->gadget.dev, "USB reset\n");
+				INFO("USB reset\n");
 				dev->gadget.speed = USB_SPEED_FULL;
 				LED_CONNECTED_ON;
 				memset(&dev->stats, 0, sizeof dev->stats);
@@ -2133,11 +2155,12 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 1,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS1,
 		.reg_uddr	= &UDDR1,
-		.reg_drcmr	= &DRCMR25,
+		drcmr (25)
 	},
 	.ep[2] = {
 		.ep = {
@@ -2146,12 +2169,13 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = 2,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS2,
 		.reg_ubcr	= &UBCR2,
 		.reg_uddr	= &UDDR2,
-		.reg_drcmr	= &DRCMR26,
+		drcmr (26)
 	},
 #ifndef CONFIG_USB_PXA2XX_SMALL
 	.ep[3] = {
@@ -2161,11 +2185,12 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 3,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS3,
 		.reg_uddr	= &UDDR3,
-		.reg_drcmr	= &DRCMR27,
+		drcmr (27)
 	},
 	.ep[4] = {
 		.ep = {
@@ -2174,12 +2199,13 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = 4,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS4,
 		.reg_ubcr	= &UBCR4,
 		.reg_uddr	= &UDDR4,
-		.reg_drcmr	= &DRCMR28,
+		drcmr (28)
 	},
 	.ep[5] = {
 		.ep = {
@@ -2188,6 +2214,7 @@
 			.maxpacket	= INT_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 5,
 		.bmAttributes	= USB_ENDPOINT_XFER_INT,
 		.reg_udccs	= &UDCCS5,
@@ -2202,11 +2229,12 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 6,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS6,
 		.reg_uddr	= &UDDR6,
-		.reg_drcmr	= &DRCMR30,
+		drcmr (30)
 	},
 	.ep[7] = {
 		.ep = {
@@ -2215,12 +2243,13 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = 7,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS7,
 		.reg_ubcr	= &UBCR7,
 		.reg_uddr	= &UDDR7,
-		.reg_drcmr	= &DRCMR31,
+		drcmr (31)
 	},
 	.ep[8] = {
 		.ep = {
@@ -2229,11 +2258,12 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 8,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS8,
 		.reg_uddr	= &UDDR8,
-		.reg_drcmr	= &DRCMR32,
+		drcmr (32)
 	},
 	.ep[9] = {
 		.ep = {
@@ -2242,12 +2272,13 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = 9,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS9,
 		.reg_ubcr	= &UBCR9,
 		.reg_uddr	= &UDDR9,
-		.reg_drcmr	= &DRCMR33,
+		drcmr (33)
 	},
 	.ep[10] = {
 		.ep = {
@@ -2256,6 +2287,7 @@
 			.maxpacket	= INT_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 10,
 		.bmAttributes	= USB_ENDPOINT_XFER_INT,
 		.reg_udccs	= &UDCCS10,
@@ -2270,11 +2302,12 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 11,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS11,
 		.reg_uddr	= &UDDR11,
-		.reg_drcmr	= &DRCMR35,
+		drcmr (35)
 	},
 	.ep[12] = {
 		.ep = {
@@ -2283,12 +2316,13 @@
 			.maxpacket	= BULK_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= BULK_FIFO_SIZE,
 		.bEndpointAddress = 12,
 		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
 		.reg_udccs	= &UDCCS12,
 		.reg_ubcr	= &UBCR12,
 		.reg_uddr	= &UDDR12,
-		.reg_drcmr	= &DRCMR36,
+		drcmr (36)
 	},
 	.ep[13] = {
 		.ep = {
@@ -2297,11 +2331,12 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 13,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS13,
 		.reg_uddr	= &UDDR13,
-		.reg_drcmr	= &DRCMR37,
+		drcmr (37)
 	},
 	.ep[14] = {
 		.ep = {
@@ -2310,12 +2345,13 @@
 			.maxpacket	= ISO_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= ISO_FIFO_SIZE,
 		.bEndpointAddress = 14,
 		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,
 		.reg_udccs	= &UDCCS14,
 		.reg_ubcr	= &UBCR14,
 		.reg_uddr	= &UDDR14,
-		.reg_drcmr	= &DRCMR38,
+		drcmr (38)
 	},
 	.ep[15] = {
 		.ep = {
@@ -2324,6 +2360,7 @@
 			.maxpacket	= INT_FIFO_SIZE,
 		},
 		.dev		= &memory,
+		.fifo_size	= INT_FIFO_SIZE,
 		.bEndpointAddress = USB_DIR_IN | 15,
 		.bmAttributes	= USB_ENDPOINT_XFER_INT,
 		.reg_udccs	= &UDCCS15,
@@ -2333,8 +2370,15 @@
 };
 
 #define CP15R0_VENDOR_MASK	0xffffe000
+
+#if	defined(CONFIG_ARCH_PXA)
 #define CP15R0_XSCALE_VALUE	0x69052000	/* intel/arm/xscale */
 
+#elif	defined(CONFIG_ARCH_IXP425)
+#define CP15R0_XSCALE_VALUE	0x69054000	/* intel/arm/ixp425 */
+
+#endif
+
 #define CP15R0_PROD_MASK	0x000003f0
 #define PXA25x			0x00000100	/* and PXA26x */
 #define PXA210			0x00000120
@@ -2355,6 +2399,7 @@
 #define PXA210_B2		0x00000124
 #define PXA210_B1		0x00000123
 #define PXA210_B0		0x00000122
+#define IXP425_A0		0x000001c1
 
 /*
  * 	probe - binds to the platform device
@@ -2374,6 +2419,7 @@
 
 	/* trigger chiprev-specific logic */
 	switch (chiprev & CP15R0_PRODREV_MASK) {
+#if	defined(CONFIG_ARCH_PXA)
 	case PXA255_A0:
 		dev->has_cfr = 1;
 		break;
@@ -2388,6 +2434,11 @@
 		/* fall through */
 	case PXA250_C0: case PXA210_C0:
 		break;
+#elif	defined(CONFIG_ARCH_IXP425)
+	case IXP425_A0:
+		out_dma = 0;
+		break;
+#endif
 	default:
 		out_dma = 0;
 		printk(KERN_ERR "%s: unrecognized processor: %08x\n",
@@ -2443,6 +2494,7 @@
 	}
 	dev->got_irq = 1;
 
+#ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
 		disable_irq(LUBBOCK_USB_DISC_IRQ);
 		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
@@ -2457,7 +2509,7 @@
 		}
 		dev->got_disc = 1;
 	}
-
+#endif
 	create_proc_files();
 
 	return 0;
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
--- a/drivers/usb/gadget/pxa2xx_udc.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/gadget/pxa2xx_udc.h	Sun Feb  8 20:57:49 2004
@@ -52,14 +52,15 @@
 	struct list_head			queue;
 	unsigned long				pio_irqs;
 	unsigned long				dma_irqs;
-	int					dma;
+	short					dma; 
 
+	unsigned short				fifo_size;
 	u8					bEndpointAddress;
 	u8					bmAttributes;
 
 	unsigned				stopped : 1;
 	unsigned				dma_fixup : 1;
-
+							 
 	/* UDCCS = UDC Control/Status for this EP
 	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
 	 * UDDR = UDC Endpoint Data Register (the fifo)
@@ -68,7 +69,12 @@
 	volatile u32				*reg_udccs;
 	volatile u32				*reg_ubcr;
 	volatile u32				*reg_uddr;
+#ifdef USE_DMA
 	volatile u32				*reg_drcmr;
+#define	drcmr(n)  .reg_drcmr = & DRCMR ## n ,
+#else
+#define	drcmr(n)  
+#endif
 };
 
 struct pxa2xx_request {
@@ -76,7 +82,7 @@
 	struct list_head			queue;
 };
 
-enum ep0_state {
+enum ep0_state { 
 	EP0_IDLE,
 	EP0_IN_DATA_PHASE,
 	EP0_OUT_DATA_PHASE,
@@ -181,14 +187,14 @@
 {
 	if (!the_controller->mach->udc_command)
 		return;
-	the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+	the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
 
 static inline void let_usb_appear(void)
 {
 	if (!the_controller->mach->udc_command)
 		return;
-	the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+	the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -305,7 +311,7 @@
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 
 #define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
-
+#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
 
 
 #endif /* __LINUX_USB_GADGET_PXA2XX_H */
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ehci-hcd.c	Sun Feb  8 20:57:49 2004
@@ -680,7 +680,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			status;
@@ -690,6 +690,12 @@
 
 	status = readl (&ehci->regs->status);
 
+	/* shared irq */
+	if (status == 0) {
+		spin_unlock (&ehci->lock);
+		return IRQ_NONE;
+	}
+
 	/* e.g. cardbus physical eject */
 	if (status == ~(u32) 0) {
 		ehci_dbg (ehci, "device removed\n");
@@ -743,6 +749,7 @@
 		ehci_work (ehci, regs);
 done:
 	spin_unlock (&ehci->lock);
+	return IRQ_HANDLED;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-hcd.c	Sun Feb  8 20:57:49 2004
@@ -81,6 +81,7 @@
 #endif
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -103,7 +104,7 @@
 #include <asm/byteorder.h>
 
 
-#define DRIVER_VERSION "2003 Oct 13"
+#define DRIVER_VERSION "2004 Feb 02"
 #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
 #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
 
@@ -112,8 +113,7 @@
 // #define OHCI_VERBOSE_DEBUG	/* not always helpful */
 
 /* For initializing controller (mask in an HCFS mode too) */
-#define	OHCI_CONTROL_INIT \
-	 (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+#define	OHCI_CONTROL_INIT 	OHCI_CTRL_CBSR
 
 #define OHCI_UNLINK_TIMEOUT	 (HZ / 10)
 
@@ -133,6 +133,12 @@
 #include "ohci-mem.c"
 #include "ohci-q.c"
 
+
+/* Some boards don't support per-port power switching */
+static int power_switching = 0;
+module_param (power_switching, bool, 0);
+MODULE_PARM_DESC (power_switching, "true (not default) to switch port power");
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -288,11 +294,8 @@
 		 * with HC dead, we won't respect hc queue pointers
 		 * any more ... just clean up every urb's memory.
 		 */
-		if (urb->hcpriv) {
-			spin_unlock (&ohci->lock);
+		if (urb->hcpriv)
 			finish_urb (ohci, urb, NULL);
-			spin_lock (&ohci->lock);
-		}
 	}
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return 0;
@@ -413,6 +416,14 @@
 	ohci->hc_control = readl (&ohci->regs->control);
 	ohci->hc_control &= OHCI_CTRL_RWC;	/* hcfs 0 = RESET */
 	writel (ohci->hc_control, &ohci->regs->control);
+	if (power_switching) {
+		unsigned ports = roothub_a (ohci) & RH_A_NDP; 
+
+		/* power down each port */
+		for (temp = 0; temp < ports; temp++)
+			writel (RH_PS_LSDA,
+				&ohci->regs->roothub.portstatus [temp]);
+	}
 	// flush those pci writes
 	(void) readl (&ohci->regs->control);
 	wait_ms (50);
@@ -502,15 +513,21 @@
 		/* NSC 87560 and maybe others */
 		tmp |= RH_A_NOCP;
 		tmp &= ~(RH_A_POTPGT | RH_A_NPS);
+	} else if (power_switching) {
+		/* act like most external hubs:  use per-port power
+		 * switching and overcurrent reporting.
+		 */
+		tmp &= ~(RH_A_NPS | RH_A_NOCP);
+		tmp |= RH_A_PSM | RH_A_OCPM;
 	} else {
 		/* hub power always on; required for AMD-756 and some
-		 * Mac platforms, use this mode everywhere by default
+		 * Mac platforms.  ganged overcurrent reporting, if any.
 		 */
 		tmp |= RH_A_NPS;
 	}
 	writel (tmp, &ohci->regs->roothub.a);
 	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
-	writel (0, &ohci->regs->roothub.b);
+	writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
 	// flush those pci writes
 	(void) readl (&ohci->regs->control);
 
@@ -545,7 +562,7 @@
 
 /* an interrupt happens */
 
-static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
+static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	struct ohci_regs	*regs = ohci->regs;
@@ -560,11 +577,11 @@
 	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
 		disable (ohci);
 		ohci_dbg (ohci, "device removed!\n");
-		return;
+		return IRQ_HANDLED;
 
 	/* interrupt for some other device? */
 	} else if ((ints &= readl (&regs->intrenable)) == 0) {
-		return;
+		return IRQ_NONE;
 	} 
 
 	if (ints & OHCI_INTR_UE) {
@@ -604,6 +621,8 @@
 		// flush those pci writes
 		(void) readl (&ohci->regs->control);
 	}
+
+	return IRQ_HANDLED;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-hub.c	Sun Feb  8 20:57:49 2004
@@ -128,6 +128,8 @@
 	desc->bDescLength = 7 + 2 * temp;
 
 	temp = 0;
+	if (rh & RH_A_NPS)		/* no power switching? */
+	    temp |= 0x0002;
 	if (rh & RH_A_PSM) 		/* per-port power switching? */
 	    temp |= 0x0001;
 	if (rh & RH_A_NOCP)		/* no overcurrent reporting? */
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-omap.c	Sun Feb  8 20:57:49 2004
@@ -134,7 +134,7 @@
 			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ,
 				ULPD_SOFT_REQ_REG);
 
-			outl(inl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
+			writel(readl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
 			     ULPD_STATUS_REQ_REG);
 		}
 
@@ -248,7 +248,7 @@
 	val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */
 	val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */
 
-	outl(val, USB_TRANSCEIVER_CTRL);
+	writel(val, USB_TRANSCEIVER_CTRL);
 
 	/* Set the USB0_TRX_MODE */
 	val = 0;
@@ -256,7 +256,7 @@
 	val &= ~DEV_IDLE_EN;
 	val &= ~(7 << 16);	/* Clear USB0_TRX_MODE */
 	val |= (3 << 16);	/* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
-	outl(val, OTG_SYSCON_1);
+	writel(val, OTG_SYSCON_1);
 
 	/* 
 	 * Control via OTG, see TRM p 15-163
@@ -275,10 +275,10 @@
 	val |= (4 << 16);	/* Must be 4 */
 	val |= USBX_SYNCHRO;	/* Must be set */
 	val |= SRP_VBUS;
-	outl(val, OTG_SYSCON_2);
+	writel(val, OTG_SYSCON_2);
 
 	/* Enable OTG idle */
-	//outl(inl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
+	//writel(readl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
 
 	return 0;
 }
@@ -631,7 +631,7 @@
 		.end	= OMAP_OHCI_BASE + OMAP_OHCI_SIZE,
 	},
 	.irq = {
-		INT_OHCI,
+		INT_USB_HHC_1,
 	},
 };
 
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-pci.c	Sun Feb  8 20:57:49 2004
@@ -266,6 +266,9 @@
 			if (ohci->ed_bulktail)
 				ohci->hc_control |= OHCI_CTRL_BLE;
 		}
+		if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs
+				|| hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs)
+			ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
 		hcd->state = USB_STATE_RUNNING;
 		writel (ohci->hc_control, &ohci->regs->control);
 
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-q.c	Sun Feb  8 20:57:49 2004
@@ -30,7 +30,7 @@
 /*
  * URB goes back to driver, and isn't reissued.
  * It's completely gone from HC data structures.
- * PRECONDITION:  no locks held, irqs blocked  (Giveback can call into HCD.)
+ * PRECONDITION:  ohci lock held, irqs blocked.
  */
 static void
 finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
@@ -55,7 +55,6 @@
 	}
 	spin_unlock (&urb->lock);
 
-	// what lock protects these?
 	switch (usb_pipetype (urb->pipe)) {
 	case PIPE_ISOCHRONOUS:
 		hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--;
@@ -68,7 +67,18 @@
 #ifdef OHCI_VERBOSE_DEBUG
 	urb_print (urb, "RET", usb_pipeout (urb->pipe));
 #endif
+
+	/* urb->complete() can reenter this HCD */
+	spin_unlock (&ohci->lock);
 	usb_hcd_giveback_urb (&ohci->hcd, urb, regs);
+	spin_lock (&ohci->lock);
+
+	/* stop periodic dma if it's not needed */
+	if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0
+			&& hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) {
+		ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
+		writel (ohci->hc_control, &ohci->regs->control);
+	}
 }
 
 
@@ -549,6 +559,7 @@
 	int		cnt = 0;
 	u32		info = 0;
 	int		is_out = usb_pipeout (urb->pipe);
+	int		periodic = 0;
 
 	/* OHCI handles the bulk/interrupt data toggles itself.  We just
 	 * use the device toggle bits for resetting, and rely on the fact
@@ -578,7 +589,8 @@
 	 */
 	case PIPE_INTERRUPT:
 		/* ... and periodic urbs have extra accounting */
-		hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++;
+		periodic = hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++ == 0
+			&& hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0;
 		/* FALLTHROUGH */
 	case PIPE_BULK:
 		info = is_out
@@ -646,9 +658,17 @@
 				data + urb->iso_frame_desc [cnt].offset,
 				urb->iso_frame_desc [cnt].length, urb, cnt);
 		}
-		hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++;
+		periodic = hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++ == 0
+			&& hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0;
 		break;
 	}
+
+	/* start periodic dma if needed */
+	if (periodic) {
+		ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
+		writel (ohci->hc_control, &ohci->regs->control);
+	}
+
 	// ASSERT (urb_priv->length == cnt);
 }
 
@@ -949,9 +969,7 @@
 			/* if URB is done, clean up */
 			if (urb_priv->td_cnt == urb_priv->length) {
 				modified = completed = 1;
-				spin_unlock (&ohci->lock);
 				finish_urb (ohci, urb, regs);
-				spin_lock (&ohci->lock);
 			}
 		}
 		if (completed && !list_empty (&ed->td_list))
@@ -1030,11 +1048,8 @@
   		urb_priv->td_cnt++;
 
 		/* If all this urb's TDs are done, call complete() */
-  		if (urb_priv->td_cnt == urb_priv->length) {
-     			spin_unlock (&ohci->lock);
+  		if (urb_priv->td_cnt == urb_priv->length)
   			finish_urb (ohci, urb, regs);
-  			spin_lock (&ohci->lock);
-  		}
 
 		/* clean schedule:  unlink EDs that are no longer busy */
 		if (list_empty (&ed->td_list))
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/ohci-sa1111.c	Sun Feb  8 20:57:49 2004
@@ -254,8 +254,6 @@
 	hcd_buffer_destroy (hcd);
 
 	usb_deregister_bus (&hcd->self);
-	if (atomic_read (&hcd->self.refcnt) != 1)
-		err ("%s: %s, count != 1", __FUNCTION__, hcd->self.bus_name);
 
 	base = hcd->regs;
 	hcd->driver->hcd_free (hcd);
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/uhci-hcd.c	Sun Feb  8 20:57:49 2004
@@ -1,7 +1,7 @@
 /*
  * Universal Host Controller Interface driver for USB.
  *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
+ * Maintainer: Alan Stern <stern@rowland.harvard.edu>
  *
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
@@ -668,7 +668,6 @@
 	urbp->inserttime = jiffies;
 	urbp->fsbrtime = jiffies;
 	urbp->urb = urb;
-	urbp->dev = urb->dev;
 	
 	INIT_LIST_HEAD(&urbp->td_list);
 	INIT_LIST_HEAD(&urbp->queue_list);
@@ -1909,7 +1908,7 @@
 	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
 }
 
-static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned int io_addr = uhci->io_addr;
@@ -1922,7 +1921,7 @@
 	 */
 	status = inw(io_addr + USBSTS);
 	if (!status)	/* shared interrupt, not mine */
-		return;
+		return IRQ_NONE;
 	outw(status, io_addr + USBSTS);		/* Clear it */
 
 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
@@ -1963,6 +1962,7 @@
 	spin_unlock(&uhci->urb_list_lock);
 
 	uhci_finish_completion(hcd, regs);
+	return IRQ_HANDLED;
 }
 
 static void reset_hc(struct uhci_hcd *uhci)
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/host/uhci-hcd.h	Sun Feb  8 20:57:49 2004
@@ -372,7 +372,6 @@
 	struct list_head urb_list;
 
 	struct urb *urb;
-	struct usb_device *dev;
 
 	struct uhci_qh *qh;		/* QH for this URB */
 	struct list_head td_list;	/* P: urb->lock */
diff -Nru a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
--- a/drivers/usb/image/Kconfig	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/image/Kconfig	Sun Feb  8 20:57:49 2004
@@ -17,19 +17,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mdc800.
 
-config USB_SCANNER
-	tristate "USB Scanner support (OBSOLETE)"
-	depends on USB
-	help
-	  Say Y here if you want to connect a USB scanner to your computer's
-	  USB port. Please read <file:Documentation/usb/scanner.txt> for more
-	  information.
-
-	  This driver has been obsoleted by support via libusb.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called scanner.
-
 config USB_MICROTEK
 	tristate "Microtek X6USB scanner support"
 	depends on USB && SCSI
diff -Nru a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile
--- a/drivers/usb/image/Makefile	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/image/Makefile	Sun Feb  8 20:57:49 2004
@@ -5,4 +5,3 @@
 obj-$(CONFIG_USB_MDC800)	+= mdc800.o
 obj-$(CONFIG_USB_HPUSBSCSI)	+= hpusbscsi.o
 obj-$(CONFIG_USB_MICROTEK)	+= microtek.o
-obj-$(CONFIG_USB_SCANNER)	+= scanner.o
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c	Sun Feb  8 20:57:49 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1216 +0,0 @@
-/* -*- linux-c -*- */
-
-/* 
- * Driver for USB Scanners (linux-2.6)
- *
- * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
- * Copyright (C) 2002, 2003 Henning Meier-Geinitz
- *
- * Portions may be copyright Brad Keryan and Michael Gee.
- *
- * Previously maintained by Brian Beattie
- *
- * Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de>
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
- *
- * History
- *
- *  0.1  8/31/1999
- *
- *    Developed/tested using linux-2.3.15 with minor ohci.c changes to
- *    support short packets during bulk xfer mode.  Some testing was
- *    done with ohci-hcd but the performance was low.  Very limited
- *    testing was performed with uhci but I was unable to get it to
- *    work.  Initial relase to the linux-usb development effort.
- *
- *
- *  0.2  10/16/1999
- *
- *    - Device can't be opened unless a scanner is plugged into the USB.
- *    - Finally settled on a reasonable value for the I/O buffer's.
- *    - Cleaned up write_scanner()
- *    - Disabled read/write stats
- *    - A little more code cleanup
- *
- *
- *  0.3  10/18/1999
- *
- *    - Device registration changed to reflect new device
- *      allocation/registration for linux-2.3.22+.
- *    - Adopted David Brownell's <david-b@pacbell.net> technique for 
- *      assigning bulk endpoints.
- *    - Removed unnecessary #include's
- *    - Scanner model now reported via syslog INFO after being detected 
- *      *and* configured.
- *    - Added user specified vendor:product USB ID's which can be passed 
- *      as module parameters.
- *
- *
- *  0.3.1
- *
- *    - Applied patches for linux-2.3.25.
- *    - Error number reporting changed to reflect negative return codes.
- *
- *
- *  0.3.2
- *
- *    - Applied patches for linux-2.3.26 to scanner_init().
- *    - Debug read/write stats now report values as signed decimal.
- *
- *
- *  0.3.3
- *
- *    - Updated the bulk_msg() calls to usb usb_bulk_msg().
- *    - Added a small delay in the write_scanner() method to aid in
- *      avoiding NULL data reads on HP scanners.  We'll see how this works.
- *    - Return values from usb_bulk_msg() now ignore positive values for
- *      use with the ohci driver.
- *    - Added conditional debugging instead of commenting/uncommenting
- *      all over the place.
- *    - kfree()'d the pointer after using usb_string() as documented in
- *      linux-usb-api.txt.
- *    - Added usb_set_configuration().  It got lost in version 0.3 -- ack!
- *    - Added the HP 5200C USB Vendor/Product ID's.
- *
- *
- *  0.3.4  1/23/2000
- *
- *    - Added Greg K-H's <greg@kroah.com> patch for better handling of 
- *      Product/Vendor detection.
- *    - The driver now autoconfigures its endpoints including interrupt
- *      endpoints if one is detected.  The concept was originally based
- *      upon David Brownell's method.
- *    - Added some Seiko/Epson ID's. Thanks to Karl Heinz 
- *      Kremer <khk@khk.net>.
- *    - Added some preliminary ioctl() calls for the PV8630 which is used
- *      by the HP4200. The ioctl()'s still have to be registered. Thanks 
- *      to Adrian Perez Jorge <adrianpj@easynews.com>.
- *    - Moved/migrated stuff to scanner.h
- *    - Removed the usb_set_configuration() since this is handled by
- *      the usb_new_device() routine in usb.c.
- *    - Added the HP 3300C.  Thanks to Bruce Tenison.
- *    - Changed user specified vendor/product id so that root hub doesn't
- *      get falsely attached to. Thanks to Greg K-H.
- *    - Added some Mustek ID's. Thanks to Gernot Hoyler 
- *      <Dr.Hoyler@t-online.de>.
- *    - Modified the usb_string() reporting.  See kfree() comment above.
- *    - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>.
- *    - Updated the printk()'s to use the info/warn/dbg macros.
- *    - Updated usb_bulk_msg() argument types to fix gcc warnings.
- *
- *
- *  0.4  2/4/2000
- *
- *    - Removed usb_string() from probe_scanner since the core now does a
- *      good job of reporting what was connnected.  
- *    - Finally, simultaneous multiple device attachment!
- *    - Fixed some potential memory freeing issues should memory allocation
- *      fail in probe_scanner();
- *    - Some fixes to disconnect_scanner().
- *    - Added interrupt endpoint support.
- *    - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh
- *      <jan.vandenbergh@cs.kuleuven.ac.be>.
- *    - Added Umax 1220U ID's. Thanks to Maciek Klimkowski
- *      <mac@nexus.carleton.ca>.
- *    - Fixed bug in write_scanner(). The buffer was not being properly
- *      updated for writes larger than OBUF_SIZE. Thanks to Henrik 
- *      Johansson <henrikjo@post.utfors.se> for identifying it.
- *    - Added Microtek X6 ID's. Thanks to Oliver Neukum
- *      <Oliver.Neukum@lrz.uni-muenchen.de>.
- *
- * 
- *  0.4.1  2/15/2000
- *  
- *    - Fixed 'count' bug in read_scanner(). Thanks to Henrik
- *      Johansson <henrikjo@post.utfors.se> for identifying it.  Amazing
- *      it has worked this long.
- *    - Fixed '>=' bug in both read/write_scanner methods.
- *    - Cleaned up both read/write_scanner() methods so that they are 
- *      a little more readable.
- *    - Added a lot of Microtek ID's.  Thanks to Adrian Perez Jorge.
- *    - Adopted the __initcall().
- *    - Added #include <linux/init.h> to scanner.h for __initcall().
- *    - Added one liner in irq_scanner() to keep gcc from complaining 
- *      about an unused variable (data) if debugging was disabled
- *      in scanner.c.
- *    - Increased the timeout parameter in read_scanner() to 120 Secs.
- *
- *
- *  0.4.2  3/23/2000
- *
- *    - Added Umax 1236U ID.  Thanks to Philipp Baer <ph_baer@npw.net>.
- *    - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's.
- *      Thanks to Adrian Perez Jorge <adrianpj@easynews.com>.
- *    - Fixed error number reported for non-existant devices.  Thanks to
- *      Spyridon Papadimitriou <Spyridon_Papadimitriou@gs91.sp.cs.cmu.edu>.
- *    - Added Acer Prisascan 620U ID's.  Thanks to Joao <joey@knoware.nl>.
- *    - Replaced __initcall() with module_init()/module_exit(). Updates
- *      from patch-2.3.48.
- *    - Replaced file_operations structure with new syntax.  Updates
- *      from patch-2.3.49.
- *    - Changed #include "usb.h" to #include <linux/usb.h>
- *    - Added #define SCN_IOCTL to exclude development areas 
- *      since 2.4.x is about to be released. This mainly affects the 
- *      ioctl() stuff.  See scanner.h for more details.
- *    - Changed the return value for signal_pending() from -ERESTARTSYS to
- *      -EINTR.
- *
- *
- * 0.4.3  4/30/2000
- *
- *    - Added Umax Astra 2200 ID.  Thanks to Flynn Marquardt 
- *      <flynn@isr.uni-stuttgart.de>.
- *    - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>.
- *    - Added access time update for the device file courtesy of Paul
- *      Mackerras <paulus@samba.org>.  This allows a user space daemon
- *      to turn the lamp off for a Umax 1220U scanner after a prescribed
- *      time.
- *    - Fixed HP S20 ID's.  Thanks to Ruud Linders <rlinders@xs4all.nl>.
- *    - Added Acer ScanPrisa 620U ID. Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list.
- *    - Fixed bug in read_scanner for copy_to_user() function.  The returned
- *      value should be 'partial' not 'this_read'.
- *    - Fixed bug in read_scanner. 'count' should be decremented 
- *      by 'this_read' and not by 'partial'.  This resulted in twice as many
- *      calls to read_scanner() for small amounts of data and possibly
- *      unexpected returns of '0'.  Thanks to Karl Heinz 
- *      Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu>
- *      for discovering this.
- *    - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a
- *      scanner lookup/ident table. Thanks Randy.
- *    - Documentation updates.
- *    - Added wait queues to read_scanner().
- *
- *
- * 0.4.3.1
- *
- *    - Fixed HP S20 ID's...again..sigh.  Thanks to Ruud
- *      Linders <rlinders@xs4all.nl>.
- *
- * 0.4.4
- *    - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB,
- *      and 1200 UB.  Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
- *    - Added the Vuego Scan Brisa 340U ID's.  Apparently this scanner is
- *      marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to
- *      David Gundersen <gundersd@paradise.net.nz>.
- *    - Added the Epson Expression1600 ID's. Thanks to Karl Heinz
- *      Kremer <khk@khk.net>.
- *
- * 0.4.5  2/28/2001
- *    - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F).
- *      Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
- *    - Added read_timeout module parameter to override RD_NAK_TIMEOUT
- *      when read()'ing from devices.
- *    - Stalled pipes are now checked and cleared with
- *      usb_clear_halt() for the read_scanner() function. This should
- *      address the "funky result: -32" error messages.
- *    - Removed Microtek scanner ID's.  Microtek scanners are now
- *      supported via the drivers/usb/microtek.c driver.
- *    - Added scanner specific read timeout's.
- *    - Return status errors are NEGATIVE!!!  This should address the
- *      "funky result: -110" error messages.
- *    - Replaced USB_ST_TIMEOUT with ETIMEDOUT.
- *    - rd_nak was still defined in MODULE_PARM.  It's been updated with
- *      read_timeout.  Thanks to Mark W. Webb <markwebb@adelphia.net> for
- *      reporting this bug.
- *    - Added Epson Perfection 1640SU and 1640SU Photo.  Thanks to
- *      Jean-Luc <f5ibh@db0bm.ampr.org> and Manuel
- *      Pelayo <Manuel.Pelayo@sesips.org>. Reported to work fine by Manuel.
- *
- * 0.4.6  9/27/2001
- *    - Added IOCTL's to report back scanner USB ID's.  Thanks to
- *      Karl Heinz <khk@lynx.phpwebhosting.com>
- *    - Added Umax Astra 2100U ID's.  Thanks to Ron
- *      Wellsted <ron@wellsted.org.uk>.
- *      and Manuel Pelayo <Manuel.Pelayo@sesips.org>.
- *    - Added HP 3400 ID's. Thanks to Harald Hannelius <harald@iki.fi>
- *      and Bertrik Sikken <bertrik@zonnet.nl>.  Reported to work at
- *      htpp://home.zonnet.nl/bertrik/hp3300c/hp3300c.htm.
- *    - Added Minolta Dimage Scan Dual II ID's.  Thanks to Jose Paulo
- *      Moitinho de Almeida <moitinho@civil.ist.utl.pt>
- *    - Confirmed addition for SnapScan E20.  Thanks to Steffen Hübner
- *      <hueb_s@gmx.de>.
- *    - Added Lifetec LT9385 ID's.  Thanks to Van Bruwaene Kris
- *      <krvbr@yahoo.co.uk>
- *    - Added Agfa SnapScan e26 ID's.  Reported to work with SANE
- *      1.0.5.  Thanks to Falk Sauer <falk@mgnkatze.franken.de>.
- *    - Added HP 4300 ID's.  Thanks to Stefan Schlosser
- *      <castla@grmmbl.org>.
- *    - Added Relisis Episode ID's.  Thanks to Manfred
- *      Morgner <odb-devel@gmx.net>.
- *    - Added many Acer ID's. Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de>.
- *    - Added Snapscan e40 ID's.  Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de>.
- *    - Thanks to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
- *      for helping with races.
- *    - Added Epson Perfection 1650 ID's. Thanks to Karl Heinz
- *      Kremer <khk@khk.net>.
- *    - Added Epson Perfection 2450 ID's (aka GT-9700 for the Japanese
- *      market).  Thanks to Karl Heinz Kremer <khk@khk.net>.
- *    - Added Mustek 600 USB ID's.  Thanks to Marcus
- *      Alanen <maalanen@ra.abo.fi>.
- *    - Added Acer ScanPrisa 1240UT ID's.  Thanks to Morgan
- *      Collins <sirmorcant@morcant.org>.
- *    - Incorporated devfs patches!! Thanks to Tom Rini
- *      <trini@kernel.crashing.org>, Pavel Roskin <proski@gnu.org>,
- *      Greg KH <greg@kroah.com>, Yves Duret <yduret@mandrakesoft.com>,
- *      Flavio Stanchina <flavio.stanchina@tin.it>.
- *    - Removed Minolta ScanImage II.  This scanner uses USB SCSI.  Thanks
- *      to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> for pointing
- *      this out.
- *    - Added additional SMP locking.  Thanks to David Brownell and 
- *      Oliver Neukum for their help.
- *    - Added version reporting - reports for both module load and modinfo
- *    - Started path to hopefully straighten/clean out ioctl()'s.
- *    - Users are now notified to consult the Documentation/usb/scanner.txt
- *      for common error messages rather than the maintainer.
- *
- * 0.4.7  11/28/2001
- *    - Fixed typo in Documentation/usb/scanner.txt.  Thanks to
- *      Karel <karel.vervaeke@pandora.be> for pointing it out.
- *    - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de
- *      Valenzuela" <agaspard@utsi.edu>.
- *    - Added ID's for Agfa e25.  Thanks to Heinrich 
- *      Rust <Heinrich.Rust@gmx.de>.  Also reported to work with
- *      Linux and SANE (?).
- *    - Added Canon FB620U, D646U, and 1220U ID's.  Thanks to Paul
- *      Rensing <Paul_Rensing@StanfordAlumni.org>.  For more info
- *      on Linux support for these models, contact 
- *      salvestrini@users.sourceforge.net.
- *    - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
- *      ColorPage-HR6 V2 ID's in addition to many "Unknown" models
- *      under those vendors.  Thanks to
- *      Jaeger, Gerhard" <g.jaeger@earthling.net>.  These scanner are
- *      apparently based upon the LM983x IC's.
- *    - Applied Frank's patch that addressed some locking and module
- *      referencing counts.  Thanks to both
- *      Frank Zago <fzago@greshamstorage.com> and
- *      Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
- *
- * 0.4.8  5/30/2002
- *    - Added Mustek BearPaw 2400 TA.  Thanks to Sergey
- *      Vlasov <vsu@mivlgu.murom.ru>.
- *    - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's.  These use
- *      the Grandtech GT-6801 chip. Thanks to Henning
- *      Meier-Geinitz <henning@meier-geinitz.de>.
- *    - Increased Epson timeout to 60 secs as requested from 
- *      Karl Heinz Kremer <khk@khk.net>.
- *    - Changed maintainership from David E. Nelson to Brian
- *      Beattie <beattie@beattie-home.net>.
- *
- * 0.4.9  12/19/2002
- *    - Added vendor/product ids for Nikon, Mustek, Plustek, Genius, Epson,
- *      Canon, Umax, Hewlett-Packard, Benq, Agfa, Minolta scanners.
- *      Thanks to Dieter Faulbaum <faulbaum@mail.bessy.de>, Stian Jordet
- *      <liste@jordet.nu>, "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>,
- *      "Jaeger, Gerhard" <gerhard@gjaeger.de>, Ira Childress 
- *      <ichildress@mn.rr.com>, Till Kamppeter <till.kamppeter@gmx.net>,
- *      Ed Hamrick <EdHamrick@aol.com>, Oliver Schwartz
- *      <Oliver.Schwartz@gmx.de> and everyone else who sent ids.
- *    - Some Benq, Genius and Plustek ids are identified now.
- *    - Accept scanners with only one bulk (in) endpoint (thanks to Sergey
- *      Vlasov <vsu@mivlgu.murom.ru>).
- *    - Accept devices with more than one interface. Only use interfaces that
- *      look like belonging to scanners.
- *    - Fix compilation error when debugging is enabled.
- *    - Add locking to ioctl_scanner(). Thanks to Oliver Neukum
- *      <oliver@neukum.name>.
- *
- * 0.4.10  01/07/2003
- *    - Added vendor/product ids for Artec, Canon, Compaq, Epson, HP, Microtek 
- *      and Visioneer scanners. Thanks to William Lam <wklam@triad.rr.com>,
- *      Till Kamppeter <till.kamppeter@gmx.net> and others for all the ids.
- *    - Cleaned up list of vendor/product ids.
- *    - Print information about user-supplied ids only once at startup instead
- *      of every time any USB device is plugged in.
- *    - Removed PV8630 ioctls. Use the standard ioctls instead.
- *    - Made endpoint detection more generic. Basically, only one bulk-in 
- *      endpoint is required, everything else is optional.
- *    - New maintainer: Henning Meier-Geinitz.
- *    - Print ids and device number when a device was detected.
- *    - Don't print errors when the device is busy.
- *      
- * 0.4.11  2003-02-25
- *    - Added vendor/product ids for Artec, Avision, Brother, Canon, Compaq,
- *      Fujitsu, Hewlett-Packard, Lexmark, LG Electronics, Medion, Microtek,
- *      Primax, Prolink,  Plustek, SYSCAN, Trust and UMAX scanners.
- *    - Fixed generation of devfs names if dynamic minors are disabled.
- *    - Used kobject reference counting to free the scn struct when the device
- *      is closed and disconnected. Avoids crashes when writing to a 
- *      disconnected device. (Thanks to Greg KH).
- *
- * 0.4.12  2003-04-11
- *    - Fixed endpoint detection. The endpoints were numbered from 1 to n but
- *      that assumption is not correct in all cases.
- *
- * 0.4.13  2003-05-30
- *    - Added vendor/product ids for Genius, Hewlett-Packard, Microtek, 
- *      Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners.
- *      Fixed names of some other scanners.
- *
- * 0.4.14  2003-07-15
- *    - Fixed race between open and probe (Oliver Neukum).
- *    - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys scanners.
- *    - Clean up irq urb when not enough memory is available.
- *
- * 0.4.15  2003-09-22
- *    - Use static declarations for usb_scanner_init/usb_scanner_exit 
- *      (Daniele Bellucci).
- *    - Report back return codes of usb_register and usb_usbmit_urb instead of -1 or
- *      -ENONMEM (Daniele Bellucci).
- *    - Balancing usb_register_dev/usb_deregister_dev in probe_scanner when a fail 
- *      condition occours (Daniele Bellucci).
- *    - Added vendor/product ids for Canon, HP, Microtek, Mustek, Siemens, UMAX, and
- *      Visioneer scanners.
- *    - Added test for USB_CLASS_CDC_DATA which is used by some fingerprint scanners.
- *
- * 0.4.16  2003-11-04
- *    - Added vendor/product ids for Epson, Genius, Microtek, Plustek, Reflecta, and
- *      Visioneer scanners. Removed ids for HP PSC devices as these are supported by
- *      the hpoj userspace driver.
- *
- * TODO
- *    - Performance
- *    - Select/poll methods
- *    - More testing
- *    - More general usage ioctl's
- *
- *
- *  Thanks to:
- *
- *    - All the folks on the linux-usb list who put up with me. :)  This 
- *      has been a great learning experience for me.
- *    - To Linus Torvalds for this great OS.
- *    - The GNU folks.
- *    - The folks that forwarded Vendor:Product ID's to me.
- *    - Johannes Erdfelt for the loaning of a USB analyzer for tracking an
- *      issue with HP-4100 and uhci.
- *    - Adolfo Montero for his assistance.
- *    - All the folks who chimed in with reports and suggestions.
- *    - All the developers that are working on USB SANE backends or other
- *      applications to use USB scanners.
- *    - Thanks to Greg KH <greg@kroah.com> for setting up Brian Beattie
- *      and Henning Meier-Geinitz to be the new USB Scanner maintainer.
- *
- *  Performance:
- *
- *    System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner
- *            300 dpi scan of the entire bed
- *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
- *       8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
-
-/*
- * For documentation, see Documentation/usb/scanner.txt.
- * Website: http://www.meier-geinitz.de/kernel/
- * Please contact the maintainer if your scanner is not detected by this
- * driver automatically.
- */
-
-
-#include <asm/byteorder.h>
-
-/* 
- * Scanner definitions, macros, module info, 
- * debug/ioctl/data_dump enable, and other constants.
- */ 
-#include "scanner.h"
-
-static void
-irq_scanner(struct urb *urb, struct pt_regs *regs)
-{
-
-/*
- * For the meantime, this is just a placeholder until I figure out what
- * all I want to do with it -- or somebody else for that matter.
- */
-
-	struct scn_usb_data *scn;
-	unsigned char *data;
-	int status;
-
-	scn = urb->context;
-
-	data = &scn->button;
-	data += 0;		/* Keep gcc from complaining about unused var */
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-	        return;	
-	}
-
-	dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
-
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
-}
-
-static int
-open_scanner(struct inode * inode, struct file * file)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-	struct usb_interface *intf;
-
-	int scn_minor;
-
-	int err=0;
-
-	down(&scn_mutex);
-
-	scn_minor = USB_SCN_MINOR(inode);
-
-	dbg("open_scanner: scn_minor:%d", scn_minor);
-
-	intf = usb_find_interface(&scanner_driver, scn_minor);
-	if (!intf) {
-		up(&scn_mutex);
-		err("open_scanner(%d): Unable to access minor data", scn_minor);
-		return -ENODEV;
-	}
-	scn = usb_get_intfdata(intf);
-	kobject_get(&scn->kobj);
-
-	dev = scn->scn_dev;
-
-	down(&(scn->sem));	/* Now protect the scn_usb_data structure */ 
-
-	up(&scn_mutex); /* Now handled by the above */
-
-	if (!dev) {
-		err("open_scanner(%d): Scanner device not present", scn_minor);
-		err = -ENODEV;
-		goto out_error;
-	}
-
-	if (!scn->present) {
-		err("open_scanner(%d): Scanner is not present", scn_minor);
-		err = -ENODEV;
-		goto out_error;
-	}
-
-	if (scn->isopen) {
-		dbg("open_scanner(%d): Scanner device is already open", scn_minor);
-		err = -EBUSY;
-		goto out_error;
-	}
-
-	init_waitqueue_head(&scn->rd_wait_q);
-
-	scn->isopen = 1;
-
-	file->private_data = scn; /* Used by the read and write methods */
-
-
-out_error:
-
-	up(&(scn->sem)); /* Wake up any possible contending processes */
-
-	return err;
-}
-
-static int
-close_scanner(struct inode * inode, struct file * file)
-{
-	struct scn_usb_data *scn = file->private_data;
-
-	int scn_minor;
-
-	scn_minor = USB_SCN_MINOR (inode);
-
-	dbg("close_scanner: scn_minor:%d", scn_minor);
-
-	down(&scn_mutex);
-	down(&(scn->sem));
-
-	scn->isopen = 0;
-
-	file->private_data = NULL;
-
-	up(&scn_mutex);
-	up(&(scn->sem));
-
-	kobject_put(&scn->kobj);
-
-	return 0;
-}
-
-static ssize_t
-write_scanner(struct file * file, const char * buffer,
-              size_t count, loff_t *ppos)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-
-	ssize_t bytes_written = 0; /* Overall count of bytes written */
-	ssize_t ret = 0;
-
-	int scn_minor;
-
-	int this_write;		/* Number of bytes to write */
-	int partial;		/* Number of bytes successfully written */
-	int result = 0;
-
-	char *obuf;
-
-	scn = file->private_data;
-
-	down(&(scn->sem));
-
-	if (!scn->bulk_out_ep) {
-		/* This scanner does not have a bulk-out endpoint */
-		up(&(scn->sem));
-		return -EINVAL;
-	}
-
-	scn_minor = scn->scn_minor;
-
-	obuf = scn->obuf;
-
-	dev = scn->scn_dev;
-
-	file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-
-	while (count > 0) {
-
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
-
-		if (copy_from_user(scn->obuf, buffer, this_write)) {
-			ret = -EFAULT;
-			break;
-		}
-
-		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ);
-		dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial);
-
-		if (result == -ETIMEDOUT) {	/* NAK -- shouldn't happen */
-			warn("write_scanner: NAK received.");
-			ret = result;
-			break;
-		} else if (result < 0) { /* We should not get any I/O errors */
-			warn("write_scanner(%d): funky result: %d. Consult Documentataion/usb/scanner.txt.", scn_minor, result);
-			ret = -EIO;
-			break;
-		}
-
-#ifdef WR_DATA_DUMP
-		if (partial) {
-			unsigned char cnt, cnt_max;
-			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump(%d): ", scn_minor);
-			for (cnt=0; cnt < cnt_max; cnt++) {
-				printk("%X ", obuf[cnt]);
-			}
-			printk("\n");
-		}
-#endif
-		if (partial != this_write) { /* Unable to write all contents of obuf */
-			ret = -EIO;
-			break;
-		}
-
-		if (partial) { /* Data written */
-			buffer += partial;
-			count -= partial;
-			bytes_written += partial;
-		} else { /* No data written */
-			ret = 0;
-			break;
-		}
-	}
-	up(&(scn->sem));
-	mdelay(5);		/* This seems to help with SANE queries */
-	return ret ? ret : bytes_written;
-}
-
-static ssize_t
-read_scanner(struct file * file, char * buffer,
-             size_t count, loff_t *ppos)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-
-	ssize_t bytes_read;	/* Overall count of bytes_read */
-	ssize_t ret;
-
-	int scn_minor;
-	int partial;		/* Number of bytes successfully read */
-	int this_read;		/* Max number of bytes to read */
-	int result;
-	int rd_expire = RD_EXPIRE;
-
-	char *ibuf;
-
-	scn = file->private_data;
-
-	down(&(scn->sem));
-
-	scn_minor = scn->scn_minor;
-
-	ibuf = scn->ibuf;
-
-	dev = scn->scn_dev;
-
-	bytes_read = 0;
-	ret = 0;
-
-	file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the
-                                                            atime of
-                                                            the device
-                                                            node */
-	while (count > 0) {
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-
-		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, scn->rd_nak_timeout);
-		dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", scn_minor, result, this_read, partial, count);
-
-/*
- * Scanners are sometimes inheriently slow since they are mechanical
- * in nature.  USB bulk reads tend to timeout while the scanner is
- * positioning, resetting, warming up the lamp, etc if the timeout is
- * set too low.  A very long timeout parameter for bulk reads was used
- * to overcome this limitation, but this sometimes resulted in folks
- * having to wait for the timeout to expire after pressing Ctrl-C from
- * an application. The user was sometimes left with the impression
- * that something had hung or crashed when in fact the USB read was
- * just waiting on data.  So, the below code retains the same long
- * timeout period, but splits it up into smaller parts so that
- * Ctrl-C's are acted upon in a reasonable amount of time.
- */
-
-		if (result == -ETIMEDOUT) { /* NAK */
-			if (!partial) { /* No data */
-				if (--rd_expire <= 0) {	/* Give it up */
-					warn("read_scanner(%d): excessive NAK's received", scn_minor);
-					ret = result;
-					break;
-				} else { /* Keep trying to read data */
-					interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout);
-					continue;
-				}
-			} else { /* Timeout w/ some data */
-				goto data_recvd;
-			}
-		}
-		
-		if (result == -EPIPE) { /* No hope */
-			if(usb_clear_halt(dev, scn->bulk_in_ep)) {
-				err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret);
-			}
-			ret = result;
-			break;
-		} else if ((result < 0) && (result != -EREMOTEIO)) {
-			warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_minor, (int)result);
-			ret = -EIO;
-			break;
-		}
-
-	data_recvd:
-
-#ifdef RD_DATA_DUMP
-		if (partial) {
-			unsigned char cnt, cnt_max;
-			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump(%d): ", scn_minor);
-			for (cnt=0; cnt < cnt_max; cnt++) {
-				printk("%X ", ibuf[cnt]);
-			}
-			printk("\n");
-		}
-#endif
-
-		if (partial) { /* Data returned */
-			if (copy_to_user(buffer, ibuf, partial)) {
-				ret = -EFAULT;
-				break;
-			}
-			count -= this_read; /* Compensate for short reads */
-			bytes_read += partial; /* Keep tally of what actually was read */
-			buffer += partial;
-		} else {
-			ret = 0;
-			break;
-		}
-	}
-	up(&(scn->sem));
-	return ret ? ret : bytes_read;
-}
-
-static int
-ioctl_scanner(struct inode *inode, struct file *file,
-	      unsigned int cmd, unsigned long arg)
-{
-	struct usb_device *dev;
-	struct scn_usb_data *scn = file->private_data;
-	int retval = -ENOTTY;
-	int scn_minor;
-
-	scn_minor = USB_SCN_MINOR(inode);
-	down(&(scn->sem));
-
-	dev = scn->scn_dev;
-
-	switch (cmd)
-	{
-	case SCANNER_IOCTL_VENDOR :
-		retval = (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
-		break;
-	case SCANNER_IOCTL_PRODUCT :
-		retval = (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
-		break;
- 	case SCANNER_IOCTL_CTRLMSG:
- 	{
- 		struct ctrlmsg_ioctl {
- 			struct usb_ctrlrequest	req;
- 			void			*data;
- 		} cmsg;
- 		int pipe, nb, ret;
- 		unsigned char buf[64];
-		retval = 0;
-
- 		if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) {
-			retval = -EFAULT;
-			break;
-		}
-
- 		nb = cmsg.req.wLength;
-
- 		if (nb > sizeof(buf)) {
- 			retval = -EINVAL;
-			break;
-		}
-
- 		if ((cmsg.req.bRequestType & 0x80) == 0) {
- 			pipe = usb_sndctrlpipe(dev, 0);
- 			if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) {
- 				retval = -EFAULT;
-				break;
-			}
- 		} else {
- 			pipe = usb_rcvctrlpipe(dev, 0);
-		}
-
- 		ret = usb_control_msg(dev, pipe, cmsg.req.bRequest,
- 				      cmsg.req.bRequestType,
- 				      cmsg.req.wValue,
- 				      cmsg.req.wIndex,
- 				      buf, nb, HZ);
-
- 		if (ret < 0) {
- 			err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor, ret);
- 			retval = -EIO;
-			break;
- 		}
-
- 		if (nb > 0 && (cmsg.req.bRequestType & 0x80) && copy_to_user(cmsg.data, buf, nb))
- 			retval = -EFAULT;
-
- 		break;
- 	}
-	default:
-		break;
-	}
-	up(&(scn->sem));
-	return retval;
-}
-
-static void destroy_scanner (struct kobject *kobj)
-{
-	struct scn_usb_data *scn;
-
-	dbg ("%s", __FUNCTION__);
-
-	scn = to_scanner(kobj);
-
-	down (&scn_mutex);
-	down (&(scn->sem));
-
-	usb_driver_release_interface(&scanner_driver,
-		scn->scn_dev->actconfig->interface[scn->ifnum]);
-
-	kfree(scn->ibuf);
-	kfree(scn->obuf);
-
-	usb_free_urb(scn->scn_irq);
-	usb_put_dev(scn->scn_dev);
-	up (&(scn->sem));
-	kfree (scn);
-	up (&scn_mutex);
-}
-
-static struct kobj_type scanner_kobj_type = {
-	.release = destroy_scanner,
-};
-
-static struct
-file_operations usb_scanner_fops = {
-	.owner =	THIS_MODULE,
-	.read =		read_scanner,
-	.write =	write_scanner,
-	.ioctl =	ioctl_scanner,
-	.open =		open_scanner,
-	.release =	close_scanner,
-};
-
-static struct usb_class_driver scanner_class = {
-	.name =		"usb/scanner%d",
-	.fops =		&usb_scanner_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
-	.minor_base =	SCN_BASE_MNR,
-};
-
-static int
-probe_scanner(struct usb_interface *intf,
-	      const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev (intf);
-	struct scn_usb_data *scn;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-
-	int ep_cnt;
-	int ix;
-	int retval;
-
-	char valid_device = 0;
-	char have_bulk_in, have_bulk_out, have_intr;
-	char name[14];
-
-	dbg("probe_scanner: USB dev address:%p", dev);
-
-/*
- * 1. Check Vendor/Product
- * 2. Determine/Assign Bulk Endpoints
- * 3. Determine/Assign Intr Endpoint
- */
-
-/*
- * There doesn't seem to be an imaging class defined in the USB
- * Spec. (yet).  If there is, HP isn't following it and it doesn't
- * look like anybody else is either.  Therefore, we have to test the
- * Vendor and Product ID's to see what we have.  Also, other scanners
- * may be able to use this driver by specifying both vendor and
- * product ID's as options to the scanner module in conf.modules.
- *
- * NOTE: Just because a product is supported here does not mean that
- * applications exist that support the product.  It's in the hopes
- * that this will allow developers a means to produce applications
- * that will support USB products.
- *
- * Until we detect a device which is pleasing, we silently punt.
- */
-
-	for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct usb_device_id); ix++) {
-		if ((dev->descriptor.idVendor == scanner_device_ids [ix].idVendor) &&
-		    (dev->descriptor.idProduct == scanner_device_ids [ix].idProduct)) {
-			valid_device = 1;
-			break;
-                }
-	}
-	if (dev->descriptor.idVendor == vendor &&   /* User specified */
-	    dev->descriptor.idProduct == product) { /* User specified */
-		valid_device = 1;
-	}
-
-	if (!valid_device)
-		return -ENODEV;	/* We didn't find anything pleasing */
-
-/*
- * After this point we can be a little noisy about what we are trying to
- *  configure.
- */
-
-	if (dev->descriptor.bNumConfigurations != 1) {
-		info("probe_scanner: Only one device configuration is supported.");
-		return -ENODEV;
-	}
-
-	interface = intf->altsetting;
- 
-	if (interface[0].desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC &&
-	    interface[0].desc.bInterfaceClass != USB_CLASS_PER_INTERFACE &&
-	    interface[0].desc.bInterfaceClass != USB_CLASS_CDC_DATA &&
-	    interface[0].desc.bInterfaceClass != SCN_CLASS_SCANJET) {
-		dbg("probe_scanner: This interface doesn't look like a scanner (class=0x%x).", interface[0].desc.bInterfaceClass);
-		return -ENODEV;
-	}
-
-/*
- * Start checking for bulk and interrupt endpoints. We are only using the first
- * one of each type of endpoint. If we have an interrupt endpoint go ahead and
- * setup the handler. FIXME: This is a future enhancement...
- */
-
-	dbg("probe_scanner: Number of Endpoints:%d", (int) interface->desc.bNumEndpoints);
-
-	ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0;
-
-	while (ep_cnt < interface->desc.bNumEndpoints) {
-		endpoint = &interface->endpoint[ep_cnt].desc;
-
-		if (IS_EP_BULK_IN(endpoint)) {
-			ep_cnt++;
-			if (have_bulk_in) {
-				info ("probe_scanner: ignoring additional bulk_in_ep:%d", ep_cnt);
-				continue;
-			}
-			have_bulk_in = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
-			continue;
-		}
-
-		if (IS_EP_BULK_OUT(endpoint)) {
-			ep_cnt++;
-			if (have_bulk_out) {
-				info ("probe_scanner: ignoring additional bulk_out_ep:%d", ep_cnt);
-				continue;
-			}
-			have_bulk_out = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
-			continue;
-		}
-
-		if (IS_EP_INTR(endpoint)) {
-			ep_cnt++;
-			if (have_intr) {
-				info ("probe_scanner: ignoring additional intr_ep:%d", ep_cnt);
-				continue;
-			}
-			have_intr = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			dbg("probe_scanner: intr_ep:%d", have_intr);
-			continue;
-		}
-		info("probe_scanner: Undetected endpoint -- consult Documentation/usb/scanner.txt.");
-		return -EIO;	/* Shouldn't ever get here unless we have something weird */
-	}
-
-
-/*
- * Perform a quick check to make sure that everything worked as it
- * should have.
- */
-
-	if (!have_bulk_in) {
-		err("probe_scanner: One bulk-in endpoint required.");
-		return -EIO;
-	}
-
-/*
- * Determine a minor number and initialize the structure associated
- * with it.  The problem with this is that we are counting on the fact
- * that the user will sequentially add device nodes for the scanner
- * devices.  */
-	
-	down(&scn_mutex);
-
-	retval = usb_register_dev(intf, &scanner_class);
-	if (retval) {
-		err ("Not able to get a minor for this device.");
-		up(&scn_mutex);
-		return -ENOMEM;
-	}
-
-	dbg("probe_scanner: Allocated minor:%d", intf->minor);
-
-	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
-		err("probe_scanner: Out of memory.");
-		up(&scn_mutex);
-		return -ENOMEM;
-	}
-	memset (scn, 0, sizeof(struct scn_usb_data));
-	kobject_init(&scn->kobj);
-	scn->kobj.ktype = &scanner_kobj_type;
-
-	scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!scn->scn_irq) {
-		usb_deregister_dev(intf, &scanner_class);
-		kfree(scn);
-		up(&scn_mutex);
-		return -ENOMEM;
-	}
-
-	init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
-
-	dbg ("probe_scanner(%d): Address of scn:%p", intf->minor, scn);
-
-/* Ok, if we detected an interrupt EP, setup a handler for it */
-	if (have_intr) {
-		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", intf->minor, have_intr);
-		usb_fill_int_urb(scn->scn_irq, dev,
-			     usb_rcvintpipe(dev, have_intr),
-			     &scn->button, 1, irq_scanner, scn,
-			     // endpoint[(int)have_intr].bInterval);
-			     250);
-
-		retval = usb_submit_urb(scn->scn_irq, GFP_KERNEL);
-		if (retval) {
-			err("probe_scanner(%d): Unable to allocate INT URB.", intf->minor);
-			usb_deregister_dev(intf, &scanner_class);
-                	kfree(scn);
-			up(&scn_mutex);
-                	return retval;
-        	}
-	}
-
-
-/* Ok, now initialize all the relevant values */
-	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor);
-		if (have_intr)
-			usb_unlink_urb(scn->scn_irq);
-		usb_free_urb(scn->scn_irq);
-		usb_deregister_dev(intf, &scanner_class);
-		kfree(scn);
-		up(&scn_mutex);
-		return -ENOMEM;
-	}
-	dbg("probe_scanner(%d): obuf address:%p", intf->minor, scn->obuf);
-
-	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor);
-		if (have_intr)
-			usb_unlink_urb(scn->scn_irq);
-		usb_free_urb(scn->scn_irq);
-		usb_deregister_dev(intf, &scanner_class);
-		kfree(scn->obuf);
-		kfree(scn);
-		up(&scn_mutex);
-		return -ENOMEM;
-	}
-	dbg("probe_scanner(%d): ibuf address:%p", intf->minor, scn->ibuf);
-	
-
-	switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
-	case 0x04b8:		/* Seiko/Epson */
-		scn->rd_nak_timeout = HZ * 60;
-		break;
-	case 0x055f:		/* Mustek */
-	case 0x0400:		/* Another Mustek */
-		scn->rd_nak_timeout = HZ * 1;
-	default:
-		scn->rd_nak_timeout = RD_NAK_TIMEOUT;
-	}
-
-
-	if (read_timeout > 0) {	/* User specified read timeout overrides everything */
-		info("probe_scanner: User specified USB read timeout - %d", read_timeout);
-		scn->rd_nak_timeout = read_timeout;
-	}
-
-
-	usb_get_dev(dev);
-	scn->bulk_in_ep = have_bulk_in;
-	scn->bulk_out_ep = have_bulk_out;
-	scn->intr_ep = have_intr;
-	scn->present = 1;
-	scn->scn_dev = dev;
-	scn->scn_minor = intf->minor;
-	scn->isopen = 0;
-
-	snprintf(name, sizeof(name), scanner_class.name,
-		 intf->minor - scanner_class.minor_base);
-
-	info ("USB scanner device (0x%04x/0x%04x) now attached to %s",
-	      dev->descriptor.idVendor, dev->descriptor.idProduct, name);
-
-	usb_set_intfdata(intf, scn);
-	up(&scn_mutex);
-	
-	return 0;
-}
-
-static void
-disconnect_scanner(struct usb_interface *intf)
-{
-	struct scn_usb_data *scn = usb_get_intfdata(intf);
-
-	/* disable open() */
-	dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor);
-	usb_deregister_dev(intf, &scanner_class);
-
-	usb_set_intfdata(intf, NULL);
-	if(scn->intr_ep) {
-		dbg("%s(%d): Unlinking IRQ URB", __FUNCTION__, scn->scn_minor);
-		usb_unlink_urb(scn->scn_irq);
-	}
-
-	if (scn)
-		kobject_put(&scn->kobj);
-}
-
-/* we want to look at all devices, as the vendor/product id can change
- * depending on the command line argument */
-static struct usb_device_id ids[] = {
-	{.driver_info = 42},
-	{}
-};
-
-static struct
-usb_driver scanner_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"usbscanner",
-	.probe =	probe_scanner,
-	.disconnect =	disconnect_scanner,
-	.id_table =	ids,
-};
-
-static void __exit
-usb_scanner_exit(void)
-{
-	usb_deregister(&scanner_driver);
-}
-
-static int __init
-usb_scanner_init (void)
-{
-	int retval;
-	retval = usb_register(&scanner_driver);
-	if (retval)
-		goto out;
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	if (vendor != -1 && product != -1)
-		info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product);
- out:
-	return retval;
-}
-
-module_init(usb_scanner_init);
-module_exit(usb_scanner_exit);
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- a/drivers/usb/image/scanner.h	Sun Feb  8 20:57:49 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,387 +0,0 @@
-/*
- * Driver for USB Scanners (linux-2.6)
- *
- * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
- * Previously maintained by Brian Beattie
- *
- * Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */ 
-
-/*
- * For documentation, see Documentation/usb/scanner.txt.
- * Website: http://www.meier-geinitz.de/kernel/
- * Please contact the maintainer if your scanner is not detected by this
- * driver automatically.
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-
-// #define DEBUG
-
-#define DRIVER_VERSION "0.4.16"
-#define DRIVER_DESC "USB Scanner Driver"
-
-#include <linux/usb.h>
-
-static __s32 vendor=-1, product=-1, read_timeout=0;
-
-MODULE_AUTHOR("Henning Meier-Geinitz, henning@meier-geinitz.de");
-MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-
-MODULE_PARM(read_timeout, "i");
-MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
-
-
-/* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
-// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
-// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */
-
-static struct usb_device_id scanner_device_ids [] = {
-	/* Acer (now Benq) */
-	{ USB_DEVICE(0x04a5, 0x1a20) },	/* Prisa 310U */
-	{ USB_DEVICE(0x04a5, 0x1a2a) },	/* Another 620U */
-	{ USB_DEVICE(0x04a5, 0x2022) },	/* 340U */
-	{ USB_DEVICE(0x04a5, 0x2040) },	/* 620U (!) */
-	{ USB_DEVICE(0x04a5, 0x2060) },	/* 620U & 640U (!)*/
-	{ USB_DEVICE(0x04a5, 0x207e) },	/* 640BU */
-	{ USB_DEVICE(0x04a5, 0x20b0) },	/* Benq 4300 */
-	{ USB_DEVICE(0x04a5, 0x20be) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x20c0) }, /* 1240UT, 1240U */
-	{ USB_DEVICE(0x04a5, 0x20de) },	/* S2W 3300U */
-	{ USB_DEVICE(0x04a5, 0x20fc) }, /* Benq 5000 */
-	{ USB_DEVICE(0x04a5, 0x20fe) },	/* Benq 5300 */
-	/* Agfa */
-	{ USB_DEVICE(0x06bd, 0x0001) },	/* SnapScan 1212U */
-	{ USB_DEVICE(0x06bd, 0x0002) },	/* SnapScan 1236U */
-	{ USB_DEVICE(0x06bd, 0x0100) },	/* SnapScan Touch */
-	{ USB_DEVICE(0x06bd, 0x2061) },	/* Another SnapScan 1212U (?)*/
-	{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
-	{ USB_DEVICE(0x06bd, 0x208f) }, /* SnapScan e50*/
-	{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
-	{ USB_DEVICE(0x06bd, 0x2093) }, /* SnapScan e10*/
-	{ USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
-	{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
-	{ USB_DEVICE(0x06bd, 0x20fd) }, /* SnapScan e52*/
-	{ USB_DEVICE(0x06bd, 0x20ff) }, /* SnapScan e42*/
-	/* Artec */
-	{ USB_DEVICE(0x05d8, 0x4001) },	/* Ultima 2000 */
-	{ USB_DEVICE(0x05d8, 0x4002) }, /* Ultima 2000 (GT6801 based) */
-	{ USB_DEVICE(0x05d8, 0x4003) }, /* E+ 48U */
-	{ USB_DEVICE(0x05d8, 0x4004) }, /* E+ Pro */
-	/* Avision */
-	{ USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */
-	{ USB_DEVICE(0x0638, 0x0a10) },	/* iVina FB1600 (=Umax Astra 4500) */
-	{ USB_DEVICE(0x0638, 0x0a20) }, /* iVina FB1800 (=Umax Astra 4700) */
-	/* Benq: see Acer */
-	/* Brother */
-	{ USB_DEVICE(0x04f9, 0x010f) },	/* MFC 5100C */
-	{ USB_DEVICE(0x04f9, 0x0111) },	/* MFC 6800 */
-	/* Canon */
-	{ USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */
-	{ USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */
-	{ USB_DEVICE(0x04a9, 0x2204) }, /* CanoScan FB630U/FB636U */
-	{ USB_DEVICE(0x04a9, 0x2205) }, /* CanoScan FB1210U */
-	{ USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */
-	{ USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */
-	{ USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ 
-	{ USB_DEVICE(0x04a9, 0x220a) },	/* CanoScan D2400UF */
-	{ USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */
-	{ USB_DEVICE(0x04a9, 0x220c) },	/* CanoScan D1250U2 */
-	{ USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */
-	{ USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */
-	{ USB_DEVICE(0x04a9, 0x220f) },	/* CanoScan 8000F */
-	{ USB_DEVICE(0x04a9, 0x2210) },	/* CanoScan 9900F */
-	{ USB_DEVICE(0x04a9, 0x2212) },	/* CanoScan 5000F */
-	{ USB_DEVICE(0x04a9, 0x2213) },	/* LIDE 50 */
-	{ USB_DEVICE(0x04a9, 0x2215) },	/* CanoScan 3000 */
-	{ USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */
-	/* Colorado -- See Primax/Colorado below */
-	/* Compaq */
-	{ USB_DEVICE(0x049f, 0x001a) },	/* S4 100 */
-	{ USB_DEVICE(0x049f, 0x0021) },	/* S200 */
-	/* Epson -- See Seiko/Epson below */
-	/* Fujitsu */
-	{ USB_DEVICE(0x04c5, 0x1041) }, /* fi-4220c USB/SCSI info:mza@mu-tec.de */
-	{ USB_DEVICE(0x04c5, 0x1042) }, /* fi-4120c USB/SCSI info:mza@mu-tec.de */
-	{ USB_DEVICE(0x04c5, 0x1029) }, /* fi-4010c USB AVision info:mza@mu-tec.de */
-	/* Genius */
-	{ USB_DEVICE(0x0458, 0x2001) },	/* ColorPage Vivid Pro */
-	{ USB_DEVICE(0x0458, 0x2007) },	/* ColorPage HR6 V2 */
-	{ USB_DEVICE(0x0458, 0x2008) }, /* ColorPage HR6 V2 */
-	{ USB_DEVICE(0x0458, 0x2009) }, /* ColorPage HR6A */
-	{ USB_DEVICE(0x0458, 0x2011) }, /* ColorPage Vivid3x */
-	{ USB_DEVICE(0x0458, 0x2013) }, /* ColorPage HR7 */
-	{ USB_DEVICE(0x0458, 0x2015) }, /* ColorPage HR7LE */
-	{ USB_DEVICE(0x0458, 0x2016) }, /* ColorPage HR6X */
-	{ USB_DEVICE(0x0458, 0x2018) },	/* ColorPage HR7X */
-	{ USB_DEVICE(0x0458, 0x201b) },	/* Colorpage Vivid 4x */
-	/* Hewlett Packard */
-	/* IMPORTANT: Hewlett-Packard multi-function peripherals (OfficeJet, 
-	   Printer/Scanner/Copier (PSC), LaserJet, or PhotoSmart printer)
-	   should not be added to this table because they are accessed by a
-	   userspace driver (hpoj) */
-	{ USB_DEVICE(0x03f0, 0x0101) },	/* ScanJet 4100C */
-	{ USB_DEVICE(0x03f0, 0x0102) },	/* PhotoSmart S20 */
-	{ USB_DEVICE(0x03f0, 0x0105) },	/* ScanJet 4200C */
-	{ USB_DEVICE(0x03f0, 0x0201) },	/* ScanJet 6200C */
-	{ USB_DEVICE(0x03f0, 0x0205) },	/* ScanJet 3300C */
-	{ USB_DEVICE(0x03f0, 0x0305) }, /* ScanJet 4300C */
-	{ USB_DEVICE(0x03f0, 0x0401) },	/* ScanJet 5200C */
-	{ USB_DEVICE(0x03f0, 0x0405) }, /* ScanJet 3400C */
-	{ USB_DEVICE(0x03f0, 0x0505) }, /* ScanJet 2100C */
-	{ USB_DEVICE(0x03f0, 0x0601) },	/* ScanJet 6300C */
-	{ USB_DEVICE(0x03f0, 0x0605) },	/* ScanJet 2200C */
-	//	{ USB_DEVICE(0x03f0, 0x0701) },	/* ScanJet 5300C - NOT SUPPORTED - use hpusbscsi driver */
-	{ USB_DEVICE(0x03f0, 0x0705) }, /* ScanJet 4400C */
-	//	{ USB_DEVICE(0x03f0, 0x0801) },	/* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
-	{ USB_DEVICE(0x03f0, 0x0805) },	/* ScanJet 4470c */
-	{ USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */
-	{ USB_DEVICE(0x03f0, 0x0a01) },	/* ScanJet 2400c */
-	{ USB_DEVICE(0x03F0, 0x1005) },	/* ScanJet 5400C */
-	{ USB_DEVICE(0x03F0, 0x1105) },	/* ScanJet 5470C */
-	{ USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */
-	{ USB_DEVICE(0x03f0, 0x1305) },	/* Scanjet 4570c */
-	//	{ USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 - NOT SUPPORTED - use hpoj userspace driver */
-	{ USB_DEVICE(0x03f0, 0x2005) },	/* ScanJet 3570c */
-	{ USB_DEVICE(0x03f0, 0x2205) },	/* ScanJet 3500c */
-	//	{ USB_DEVICE(0x03f0, 0x2f11) }, /* PSC 1210 - NOT SUPPORTED - use hpoj userspace driver */
-	/* Lexmark */
-	{ USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */
-	{ USB_DEVICE(0x043d, 0x003d) }, /* X83 */
-	/* LG Electronics */
-	{ USB_DEVICE(0x0461, 0x0364) },	/* Scanworks 600U (repackaged Primax?) */
-	/* Medion */
-	{ USB_DEVICE(0x0461, 0x0377) },	/* MD 5345 - repackaged Primax? */
-	/* Memorex */
-	{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
-	/* Microtek */
-	{ USB_DEVICE(0x05da, 0x20a7) },	/* ScanMaker 5600 */
-	{ USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */
-	{ USB_DEVICE(0x05da, 0x30ce) },	/* ScanMaker 3800 */
-	{ USB_DEVICE(0x05da, 0x30cf) },	/* ScanMaker 4800 */
-	{ USB_DEVICE(0x05da, 0x30d4) },	/* ScanMaker 3830 + 3840 */
-	{ USB_DEVICE(0x05da, 0x30d8) },	/* ScanMaker 5900 */
-	{ USB_DEVICE(0x04a7, 0x0224) },	/* Scanport 3000 (actually Visioneer?)*/
-	/* The following SCSI-over-USB Microtek devices are supported by the
-	   microtek driver: Enable SCSI and USB Microtek in kernel config */
-	//	{ USB_DEVICE(0x05da, 0x0099) },	/* ScanMaker X6 - X6U */
-	//	{ USB_DEVICE(0x05da, 0x0094) },	/* Phantom 336CX - C3 */
-	//	{ USB_DEVICE(0x05da, 0x00a0) },	/* Phantom 336CX - C3 #2 */
-	//	{ USB_DEVICE(0x05da, 0x009a) },	/* Phantom C6 */
-	//	{ USB_DEVICE(0x05da, 0x00a3) },	/* ScanMaker V6USL */
-	//	{ USB_DEVICE(0x05da, 0x80a3) },	/* ScanMaker V6USL #2 */
-	//	{ USB_DEVICE(0x05da, 0x80ac) },	/* ScanMaker V6UL - SpicyU */
-	/* Minolta */
-	{ USB_DEVICE(0x0686, 0x400d) }, /* Scan Dual III */
-	/* The following SCSI-over-USB Minolta devices are supported by the
-	   hpusbscsi driver: Enable SCSI and USB hpusbscsi in kernel config */
-	//	{ USB_DEVICE(0x0638, 0x026a) }, /* Minolta Dimage Scan Dual II */
-	//	{ USB_DEVICE(0x0686, 0x4004) }, /* Scan Elite II (need interrupt ep) */
-	/* Mustek */
-	{ USB_DEVICE(0x0400, 0x1000) },	/* BearPaw 1200 (National Semiconductor LM9831) */
-	{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 (National Semiconductor LM9832) */
-	{ USB_DEVICE(0x055f, 0x0001) },	/* ScanExpress 1200 CU */
-	{ USB_DEVICE(0x055f, 0x0002) },	/* ScanExpress 600 CU */
-	{ USB_DEVICE(0x055f, 0x0003) },	/* ScanExpress 1200 USB */
-	{ USB_DEVICE(0x055f, 0x0006) },	/* ScanExpress 1200 UB */
-	{ USB_DEVICE(0x055f, 0x0007) },	/* ScanExpress 1200 USB Plus */
-	{ USB_DEVICE(0x055f, 0x0008) }, /* ScanExpress 1200 CU Plus */
-	{ USB_DEVICE(0x055f, 0x0010) }, /* BearPaw 1200F */
-	{ USB_DEVICE(0x055f, 0x0210) },	/* ScanExpress A3 USB */
-	{ USB_DEVICE(0x055f, 0x0218) }, /* BearPaw 2400 TA */
-	{ USB_DEVICE(0x055f, 0x0219) }, /* BearPaw 2400 TA Plus */
-	{ USB_DEVICE(0x055f, 0x021c) }, /* BearPaw 1200 CU Plus */
-	{ USB_DEVICE(0x055f, 0x021d) }, /* Bearpaw 2400 CU Plus */
-	{ USB_DEVICE(0x055f, 0x021e) }, /* BearPaw 1200 TA/CS */
-	{ USB_DEVICE(0x055f, 0x0400) }, /* BearPaw 2400 TA PRO */
-	{ USB_DEVICE(0x055f, 0x0401) },	/* P 3600 A3 Pro */
-	{ USB_DEVICE(0x055f, 0x0409) },	/* BearPaw 2448TA Pro */
-	{ USB_DEVICE(0x055f, 0x0873) }, /* ScanExpress 600 USB */
-	{ USB_DEVICE(0x055f, 0x1000) }, /* BearPaw 4800 TA PRO */
-	//	{ USB_DEVICE(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */
-	/* Nikon */
-	{ USB_DEVICE(0x04b0, 0x4000) }, /* Coolscan LS 40 ED */
-	/* Pacific Image Electronics */
-	{ USB_DEVICE(0x05e3, 0x0120) },	/* PrimeFilm 1800u */
-	/* Plustek */
-	{ USB_DEVICE(0x07b3, 0x0001) },	/* 1212U */
-	{ USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0010) }, /* OpticPro U12 */
-	{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro U24 */
-	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0013) }, /* UT12 */
-	{ USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0015) }, /* OpticPro U24 */
-	{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12/UT16/UT24 */
-	{ USB_DEVICE(0x07b3, 0x0400) }, /* OpticPro 1248U */
-	{ USB_DEVICE(0x07b3, 0x0401) }, /* OpticPro 1248U (another one) */
-	{ USB_DEVICE(0x07b3, 0x0403) },	/* U16B */
-	{ USB_DEVICE(0x07b3, 0x0413) },	/* OpticSlim 1200 */
-	/* Primax/Colorado */
-	{ USB_DEVICE(0x0461, 0x0300) },	/* G2-300 #1 */
-	{ USB_DEVICE(0x0461, 0x0301) },	/* G2E-300 #1 */
-	{ USB_DEVICE(0x0461, 0x0302) },	/* G2-300 #2 */
-	{ USB_DEVICE(0x0461, 0x0303) },	/* G2E-300 #2 */
-	{ USB_DEVICE(0x0461, 0x0340) },	/* Colorado USB 9600 */
-	{ USB_DEVICE(0x0461, 0x0341) },	/* Colorado 600u */
-	{ USB_DEVICE(0x0461, 0x0347) },	/* Primascan Colorado 2600u */
-	{ USB_DEVICE(0x0461, 0x0360) },	/* Colorado USB 19200 */
-	{ USB_DEVICE(0x0461, 0x0361) },	/* Colorado 1200u */
-	{ USB_DEVICE(0x0461, 0x0380) },	/* G2-600 #1 */
-	{ USB_DEVICE(0x0461, 0x0381) },	/* ReadyScan 636i */
-	{ USB_DEVICE(0x0461, 0x0382) },	/* G2-600 #2 */
-	{ USB_DEVICE(0x0461, 0x0383) },	/* G2E-600 */
-	/* Prolink */
-	{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
-	/* Reflecta  */
-	{ USB_DEVICE(0x05e3, 0x0120) },	/* iScan 1800 */
-	/* Relisis */
-	// { USB_DEVICE(0x0475, 0x0103) },	/* Episode - undetected endpoint */
-	{ USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */
-	/* Seiko/Epson Corp. */
-	{ USB_DEVICE(0x04b8, 0x0101) },	/* Perfection 636U and 636Photo */
-	{ USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */
-	{ USB_DEVICE(0x04b8, 0x0103) },	/* Perfection 610 */
-	{ USB_DEVICE(0x04b8, 0x0104) },	/* Perfection 1200U and 1200Photo*/
-	{ USB_DEVICE(0x04b8, 0x0105) }, /* StylusScan 2000 */
-	{ USB_DEVICE(0x04b8, 0x0106) },	/* Stylus Scan 2500 */
-	{ USB_DEVICE(0x04b8, 0x0107) },	/* Expression 1600 */
-	{ USB_DEVICE(0x04b8, 0x0109) }, /* Expression 1640XL */
-	{ USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */
-	{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
-	{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
-	{ USB_DEVICE(0x04b8, 0x010e) }, /* Expression 1680 */
-	{ USB_DEVICE(0x04b8, 0x010f) }, /* Perfection 1250U */
-	{ USB_DEVICE(0x04b8, 0x0110) }, /* Perfection 1650 */
-	{ USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */
-	{ USB_DEVICE(0x04b8, 0x0114) }, /* Perfection 660 */
-	{ USB_DEVICE(0x04b8, 0x011b) }, /* Perfection 2400 Photo */
-	{ USB_DEVICE(0x04b8, 0x011c) }, /* Perfection 3200 */
-	{ USB_DEVICE(0x04b8, 0x011d) }, /* Perfection 1260 */
-	{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
-	{ USB_DEVICE(0x04b8, 0x011f) },	/* Perfection 1670 */
-	{ USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */
-	{ USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */
-	/* Siemens */
-	{ USB_DEVICE(0x0681, 0x0005) },	/* ID Mouse Professional */
-	{ USB_DEVICE(0x0681, 0x0010) },	/* Cherry FingerTIP ID Board - Sensor */
-	/* SYSCAN */
-	{ USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */
-	/* Trust */
-	{ USB_DEVICE(0x05cb, 0x1483) }, /* CombiScan 19200 */
-	{ USB_DEVICE(0x05d8, 0x4006) }, /* Easy Webscan 19200 (repackaged Artec?) */
-	/* Umax */
-	{ USB_DEVICE(0x05d8, 0x4009) },	/* Astraslim (actually Artec?) */
-	{ USB_DEVICE(0x1606, 0x0010) },	/* Astra 1220U */
-	{ USB_DEVICE(0x1606, 0x0030) },	/* Astra 2000U */
-	{ USB_DEVICE(0x1606, 0x0060) }, /* Astra 3400U/3450U */
-	{ USB_DEVICE(0x1606, 0x0070) },	/* Astra 4400 */
-	{ USB_DEVICE(0x1606, 0x0130) }, /* Astra 2100U */
-	{ USB_DEVICE(0x1606, 0x0160) }, /* Astra 5400U */  
-	{ USB_DEVICE(0x1606, 0x0230) },	/* Astra 2200U */
-	/* Visioneer */
-	{ USB_DEVICE(0x04a7, 0x0211) },	/* OneTouch 7600 USB */
-	{ USB_DEVICE(0x04a7, 0x0221) },	/* OneTouch 5300 USB */
-	{ USB_DEVICE(0x04a7, 0x0224) },	/* OneTouch 4800 USB */
-	{ USB_DEVICE(0x04a7, 0x0226) },	/* OneTouch 5800 USB */
-	{ USB_DEVICE(0x04a7, 0x0229) }, /* OneTouch 7100 USB */
-	{ USB_DEVICE(0x04a7, 0x022c) },	/* OneTouch 9020 USB */
-	{ USB_DEVICE(0x04a7, 0x0231) },	/* 6100 USB */
-	{ USB_DEVICE(0x04a7, 0x0311) },	/* 6200 EPP/USB */
-	{ USB_DEVICE(0x04a7, 0x0321) },	/* OneTouch 8100 EPP/USB */
-	{ USB_DEVICE(0x04a7, 0x0331) }, /* OneTouch 8600 EPP/USB */
-	{ USB_DEVICE(0x0461, 0x0345) }, /* 6200 (actually Primax?) */
-	{ USB_DEVICE(0x0461, 0x0371) }, /* Onetouch 8920 USB (actually Primax?) */
-	{ }				/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, scanner_device_ids);
-
-#define IS_EP_BULK(ep)  ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
-#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
-#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
-#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
-
-#define USB_SCN_MINOR(X) iminor(X)
-
-#ifdef DEBUG
-#define SCN_DEBUG(X) X
-#else
-#define SCN_DEBUG(X)
-#endif
-
-#define IBUF_SIZE 32768
-#define OBUF_SIZE 4096
-
-/* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ)	/* Default number of X seconds to wait */
-#define RD_EXPIRE 12		/* Number of attempts to wait X seconds */
-
-
-/* read vendor and product IDs from the scanner */
-#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
-#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
-/* send/recv a control message to the scanner */
-#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
-
-/* USB bInterfaceClass used by Hewlett-Packard ScanJet 3300c and Genius HR6
-   USB - Vivid III */
-#define SCN_CLASS_SCANJET 16
-
-#define SCN_BASE_MNR 48		/* USB Scanners start at minor 48 */
-
-static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
-
-struct scn_usb_data {
-	struct usb_device *scn_dev;
-	struct urb *scn_irq;
-	unsigned int ifnum;	/* Interface number of the USB device */
-	int scn_minor;		/* Scanner minor - used in disconnect() */
-	unsigned char button;	/* Front panel buffer */
-	char isopen;		/* Not zero if the device is open */
-	char present;		/* Not zero if device is present */
-	char *obuf, *ibuf;	/* transfer buffers */
-	char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
-	wait_queue_head_t rd_wait_q; /* read timeouts */
-	struct semaphore sem; /* lock to prevent concurrent reads or writes */
-	unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
-	struct kobject kobj;	/* Handles our reference counting */
-};
-#define to_scanner(d) container_of(d, struct scn_usb_data, kobj)
-
-static struct usb_driver scanner_driver;
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/input/hid-core.c	Sun Feb  8 20:57:49 2004
@@ -602,14 +602,16 @@
 		case 2:
 			if ((end - start) < 2) 
 				return NULL;
-			item->data.u16 = le16_to_cpu(get_unaligned(((__u16*)start)++));
+			item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start));
+			start = (__u8 *)((__u16 *)start + 1);
 			return start;
 
 		case 3:
 			item->size++;
 			if ((end - start) < 4)
 				return NULL;
-			item->data.u32 = le32_to_cpu(get_unaligned(((__u32*)start)++));
+			item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start));
+			start = (__u8 *)((__u32 *)start + 1);
 			return start;
 	}
 
diff -Nru a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
--- a/drivers/usb/media/dsbr100.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/media/dsbr100.c	Sun Feb  8 20:57:49 2004
@@ -15,7 +15,7 @@
  You might find some interesting stuff about this module at
  http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
 
- Copyright (c) 2000 Markus Demleitner <msdemlei@tucana.harvard.edu>
+ Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
 
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@
  History:
 
  Version 0.30:
- 	Markus: Updates for 2.5.x kernel and more ISO compiant source
+ 	Markus: Updates for 2.5.x kernel and more ISO compliant source
 
  Version 0.25:
         PSL and Markus: Cleanup, radio now doesn't stop on device close
@@ -75,7 +75,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.25"
+#define DRIVER_VERSION "v0.30"
 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
 
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/misc/usbtest.c	Sun Feb  8 20:57:49 2004
@@ -1,15 +1,16 @@
 #include <linux/config.h>
+#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
+#   define DEBUG
+#endif
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <asm/scatterlist.h>
 
-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
-#   define DEBUG
-#endif
 #include <linux/usb.h>
 
 
@@ -20,10 +21,10 @@
 struct usbtest_param {
 	// inputs
 	unsigned		test_num;	/* 0..(TEST_CASES-1) */
-	int			iterations;
-	int			length;
-	int			vary;
-	int			sglen;
+	unsigned		iterations;
+	unsigned		length;
+	unsigned		vary;
+	unsigned		sglen;
 
 	// outputs
 	struct timeval		duration;
@@ -48,6 +49,8 @@
 	u8			ep_in;		/* bulk/intr source */
 	u8			ep_out;		/* bulk/intr sink */
 	unsigned		autoconf : 1;
+	unsigned		ctrl_out : 1;
+	unsigned		iso : 1;	/* try iso in/out */
 	int			alt;
 };
 
@@ -60,9 +63,11 @@
 struct usbtest_dev {
 	struct usb_interface	*intf;
 	struct usbtest_info	*info;
-	char			id [32];
 	int			in_pipe;
 	int			out_pipe;
+	int			in_iso_pipe;
+	int			out_iso_pipe;
+	struct usb_endpoint_descriptor	*iso_in, *iso_out;
 	struct semaphore	sem;
 
 #define TBUF_SIZE	256
@@ -77,6 +82,31 @@
 /* set up all urbs so they can be used with either bulk or interrupt */
 #define	INTERRUPT_RATE		1	/* msec/transfer */
 
+#define xprintk(tdev,level,fmt,args...) \
+	dev_printk(level ,  &(tdev)->intf->dev ,  fmt ,  ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+	xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG DBG
+#else
+#define VDBG(dev,fmt,args...) \
+	do { } while (0)
+#endif	/* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+	xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+	xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+	xprintk(dev , KERN_INFO , fmt , ## args)
+
 /*-------------------------------------------------------------------------*/
 
 static int
@@ -85,12 +115,14 @@
 	int				tmp;
 	struct usb_host_interface	*alt;
 	struct usb_host_endpoint	*in, *out;
+	struct usb_host_endpoint	*iso_in, *iso_out;
 	struct usb_device		*udev;
 
 	for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
 		unsigned	ep;
 
 		in = out = 0;
+		iso_in = iso_out = 0;
 		alt = intf->altsetting + tmp;
 
 		/* take the first altsetting with in-bulk + out-bulk;
@@ -100,8 +132,16 @@
 			struct usb_host_endpoint	*e;
 
 			e = alt->endpoint + ep;
-			if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
+			switch (e->desc.bmAttributes) {
+			case USB_ENDPOINT_XFER_BULK:
+				break;
+			case USB_ENDPOINT_XFER_ISOC:
+				if (dev->info->iso)
+					goto try_iso;
+				// FALLTHROUGH
+			default:
 				continue;
+			}
 			if (e->desc.bEndpointAddress & USB_DIR_IN) {
 				if (!in)
 					in = e;
@@ -111,6 +151,17 @@
 			}
 			if (in && out)
 				goto found;
+			continue;
+try_iso:
+			if (e->desc.bEndpointAddress & USB_DIR_IN) {
+				if (!iso_in)
+					iso_in = e;
+			} else {
+				if (!iso_out)
+					iso_out = e;
+			}
+			if (iso_in && iso_out)
+				goto found;
 		}
 	}
 	return -EINVAL;
@@ -125,10 +176,21 @@
 			return tmp;
 	}
 
-	dev->in_pipe = usb_rcvbulkpipe (udev,
+	if (in) {
+		dev->in_pipe = usb_rcvbulkpipe (udev,
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-	dev->out_pipe = usb_sndbulkpipe (udev,
+		dev->out_pipe = usb_sndbulkpipe (udev,
 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	} else if (iso_in) {
+		dev->iso_in = &iso_in->desc;
+		dev->in_iso_pipe = usb_rcvisocpipe (udev,
+				iso_in->desc.bEndpointAddress
+					& USB_ENDPOINT_NUMBER_MASK);
+		dev->iso_out = &iso_out->desc;
+		dev->out_iso_pipe = usb_sndisocpipe (udev,
+				iso_out->desc.bEndpointAddress
+					& USB_ENDPOINT_NUMBER_MASK);
+	}
 	return 0;
 }
 
@@ -176,6 +238,63 @@
 	return urb;
 }
 
+static unsigned pattern = 0;
+module_param (pattern, uint, S_IRUGO);
+// MODULE_PARM_DESC (pattern, "i/o pattern (0 == zeroes)");
+
+static inline void simple_fill_buf (struct urb *urb)
+{
+	unsigned	i;
+	u8		*buf = urb->transfer_buffer;
+	unsigned	len = urb->transfer_buffer_length;
+
+	switch (pattern) {
+	default:
+		// FALLTHROUGH
+	case 0:
+		memset (buf, 0, len);
+		break;
+	case 1:			/* mod63 */
+		for (i = 0; i < len; i++)
+			*buf++ = (u8) (i % 63);
+		break;
+	}
+}
+
+static inline int simple_check_buf (struct urb *urb)
+{
+	unsigned	i;
+	u8		expected;
+	u8		*buf = urb->transfer_buffer;
+	unsigned	len = urb->actual_length;
+
+	for (i = 0; i < len; i++, buf++) {
+		switch (pattern) {
+		/* all-zeroes has no synchronization issues */
+		case 0:
+			expected = 0;
+			break;
+		/* mod63 stays in sync with short-terminated transfers,
+		 * or otherwise when host and gadget agree on how large
+		 * each usb transfer request should be.  resync is done
+		 * with set_interface or set_config.
+		 */
+		case 1:			/* mod63 */
+			expected = i % 63;
+			break;
+		/* always fail unsupported patterns */
+		default:
+			expected = !*buf;
+			break;
+		}
+		if (*buf == expected)
+			continue;
+		dbg ("buf[%d] = %d (not %d)", i, *buf, expected);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static void simple_free_urb (struct urb *urb)
 {
 	usb_buffer_free (urb->dev, urb->transfer_buffer_length,
@@ -186,7 +305,9 @@
 static int simple_io (
 	struct urb		*urb,
 	int			iterations,
-	int			vary
+	int			vary,
+	int			expected,
+	const char		*label
 )
 {
 	struct usb_device	*udev = urb->dev;
@@ -197,6 +318,8 @@
 	urb->context = &completion;
 	while (retval == 0 && iterations-- > 0) {
 		init_completion (&completion);
+		if (usb_pipeout (urb->pipe))
+			simple_fill_buf (urb);
 		if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0)
 			break;
 
@@ -204,6 +327,8 @@
 		wait_for_completion (&completion);
 		retval = urb->status;
 		urb->dev = udev;
+		if (retval == 0 && usb_pipein (urb->pipe))
+			retval = simple_check_buf (urb);
 
 		if (vary) {
 			int	len = urb->transfer_buffer_length;
@@ -219,14 +344,14 @@
 	}
 	urb->transfer_buffer_length = max;
 
-	// FIXME for unlink or fault handling tests, don't report
-	// failure if retval is as we expected ...
-	if (retval)
-		dbg ("simple_io failed, iterations left %d, status %d",
-				iterations, retval);
+	if (expected != retval)
+		dev_dbg (&udev->dev,
+			"%s failed, iterations left %d, status %d (not %d)\n",
+				label, iterations, retval, expected);
 	return retval;
 }
 
+
 /*-------------------------------------------------------------------------*/
 
 /* We use scatterlist primitives to test queued I/O.
@@ -360,54 +485,18 @@
 	}
 }
 
-/* this is usb_set_interface(), with no 'only one altsetting' case */
 static int set_altsetting (struct usbtest_dev *dev, int alternate)
 {
 	struct usb_interface		*iface = dev->intf;
 	struct usb_device		*udev;
-	struct usb_host_interface	*iface_as;
-	int				i, ret;
 
 	if (alternate < 0 || alternate >= iface->num_altsetting)
 		return -EINVAL;
 
 	udev = interface_to_usbdev (iface);
-	if ((ret = usb_control_msg (udev, usb_sndctrlpipe (udev, 0),
-			USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
-			alternate,
-			iface->altsetting->desc.bInterfaceNumber,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
-		return ret;
-
-	// FIXME usbcore should be more like this:
-	// - remove that special casing in usbcore.
-	// - fix usbcore signature to take interface
-
-	/* prevent requests using previous endpoint settings */
-	iface_as = iface->altsetting + iface->act_altsetting;
-	for (i = 0; i < iface_as->desc.bNumEndpoints; i++) {
-		u8	ep = iface_as->endpoint [i].desc.bEndpointAddress;
-		int	out = !(ep & USB_DIR_IN);
-
-		ep &= USB_ENDPOINT_NUMBER_MASK;
-		(out ? udev->epmaxpacketout : udev->epmaxpacketin ) [ep] = 0;
-		// FIXME want hcd hook here, "forget this endpoint"
-	}
-	iface->act_altsetting = alternate;
-
-	/* reset toggles and maxpacket for all endpoints affected */
-	iface_as = iface->altsetting + iface->act_altsetting;
-	for (i = 0; i < iface_as->desc.bNumEndpoints; i++) {
-		u8	ep = iface_as->endpoint [i].desc.bEndpointAddress;
-		int	out = !(ep & USB_DIR_IN);
-
-		ep &= USB_ENDPOINT_NUMBER_MASK;
-		usb_settoggle (udev, ep, out, 0);
-		(out ? udev->epmaxpacketout : udev->epmaxpacketin ) [ep]
-			= iface_as->endpoint [i].desc.wMaxPacketSize;
-	}
-
-	return 0;
+	return usb_set_interface (udev,
+			iface->altsetting [0].desc.bInterfaceNumber,
+			alternate);
 }
 
 static int is_good_config (char *buf, int len)
@@ -421,15 +510,19 @@
 	switch (config->bDescriptorType) {
 	case USB_DT_CONFIG:
 	case USB_DT_OTHER_SPEED_CONFIG:
-		if (config->bLength != 9)
+		if (config->bLength != 9) {
+			dbg ("bogus config descriptor length");
 			return 0;
+		}
 		/* this bit 'must be 1' but often isn't */
 		if (!realworld && !(config->bmAttributes & 0x80)) {
 			dbg ("high bit of config attributes not set");
 			return 0;
 		}
-		if (config->bmAttributes & 0x1f)	/* reserved == 0 */
+		if (config->bmAttributes & 0x1f) {	/* reserved == 0 */
+			dbg ("reserved config bits set");
 			return 0;
+		}
 		break;
 	default:
 		return 0;
@@ -438,7 +531,10 @@
 	le16_to_cpus (&config->wTotalLength);
 	if (config->wTotalLength == len)		/* read it all */
 		return 1;
-	return config->wTotalLength >= TBUF_SIZE;	/* max partial read */
+	if (config->wTotalLength >= TBUF_SIZE)		/* max partial read */
+		return 1;
+	dbg ("bogus config descriptor read size");
+	return 0;
 }
 
 /* sanity test for standard requests working with usb_control_mesg() and some
@@ -471,8 +567,9 @@
 		 * they're ordered meaningfully in this array
 		 */
 		if (iface->altsetting [i].desc.bAlternateSetting != i) {
-			dbg ("%s, invalid alt [%d].bAltSetting = %d",
-					dev->id, i, 
+			dev_dbg (&iface->dev,
+					"invalid alt [%d].bAltSetting = %d\n",
+					i, 
 					iface->altsetting [i].desc
 						.bAlternateSetting);
 			return -EDOM;
@@ -485,16 +582,16 @@
 		/* [9.4.10] set_interface */
 		retval = set_altsetting (dev, i);
 		if (retval) {
-			dbg ("%s can't set_interface = %d, %d",
-					dev->id, i, retval);
+			dev_dbg (&iface->dev, "can't set_interface = %d, %d\n",
+					i, retval);
 			return retval;
 		}
 
 		/* [9.4.4] get_interface always works */
 		retval = get_altsetting (dev);
 		if (retval != i) {
-			dbg ("%s get alt should be %d, was %d",
-					dev->id, i, retval);
+			dev_dbg (&iface->dev, "get alt should be %d, was %d\n",
+					i, retval);
 			return (retval < 0) ? retval : -EDOM;
 		}
 
@@ -513,7 +610,8 @@
 				USB_DIR_IN | USB_RECIP_DEVICE,
 				0, 0, dev->buf, 1, HZ * USB_CTRL_GET_TIMEOUT);
 		if (retval != 1 || dev->buf [0] != expected) {
-			dbg ("%s get config --> %d (%d)", dev->id, retval,
+			dev_dbg (&iface->dev,
+				"get config --> %d (%d)\n", retval,
 				expected);
 			return (retval < 0) ? retval : -EDOM;
 		}
@@ -523,7 +621,7 @@
 	retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0,
 			dev->buf, sizeof udev->descriptor);
 	if (retval != sizeof udev->descriptor) {
-		dbg ("%s dev descriptor --> %d", dev->id, retval);
+		dev_dbg (&iface->dev, "dev descriptor --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
@@ -532,8 +630,9 @@
 		retval = usb_get_descriptor (udev, USB_DT_CONFIG, i,
 				dev->buf, TBUF_SIZE);
 		if (!is_good_config (dev->buf, retval)) {
-			dbg ("%s config [%d] descriptor --> %d",
-					dev->id, i, retval);
+			dev_dbg (&iface->dev,
+					"config [%d] descriptor --> %d\n",
+					i, retval);
 			return (retval < 0) ? retval : -EDOM;
 		}
 
@@ -551,13 +650,14 @@
 				sizeof (struct usb_qualifier_descriptor));
 		if (retval == -EPIPE) {
 			if (udev->speed == USB_SPEED_HIGH) {
-				dbg ("%s hs dev qualifier --> %d",
-						dev->id, retval);
+				dev_dbg (&iface->dev,
+						"hs dev qualifier --> %d\n",
+						retval);
 				return (retval < 0) ? retval : -EDOM;
 			}
 			/* usb2.0 but not high-speed capable; fine */
 		} else if (retval != sizeof (struct usb_qualifier_descriptor)) {
-			dbg ("%s dev qualifier --> %d", dev->id, retval);
+			dev_dbg (&iface->dev, "dev qualifier --> %d\n", retval);
 			return (retval < 0) ? retval : -EDOM;
 		} else
 			d = (struct usb_qualifier_descriptor *) dev->buf;
@@ -570,8 +670,9 @@
 					USB_DT_OTHER_SPEED_CONFIG, i,
 					dev->buf, TBUF_SIZE);
 				if (!is_good_config (dev->buf, retval)) {
-					dbg ("%s other speed config --> %d",
-							dev->id, retval);
+					dev_dbg (&iface->dev,
+						"other speed config --> %d\n",
+						retval);
 					return (retval < 0) ? retval : -EDOM;
 				}
 			}
@@ -582,7 +683,7 @@
 	/* [9.4.5] get_status always works */
 	retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf);
 	if (retval != 2) {
-		dbg ("%s get dev status --> %d", dev->id, retval);
+		dev_dbg (&iface->dev, "get dev status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
@@ -592,7 +693,7 @@
 	retval = usb_get_status (udev, USB_RECIP_INTERFACE,
 			iface->altsetting [0].desc.bInterfaceNumber, dev->buf);
 	if (retval != 2) {
-		dbg ("%s get interface status --> %d", dev->id, retval);
+		dev_dbg (&iface->dev, "get interface status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 	// FIXME get status for each endpoint in the interface
@@ -606,7 +707,7 @@
  *   (a) queues work for control, keeping N subtests queued and
  *       active (auto-resubmit) for M loops through the queue.
  *   (b) protocol stalls (control-only) will autorecover.
- *       it's quite not like bulk/intr; no halt clearing.
+ *       it's not like bulk/intr; no halt clearing.
  *   (c) short control reads are reported and handled.
  *   (d) queues are always processed in-order
  */
@@ -654,6 +755,7 @@
 			dbg ("subcase %d completed out of order, last %d",
 					subcase->number, ctx->last);
 			status = -EDOM;
+			ctx->last = subcase->number;
 			goto error;
 		}
 	}
@@ -995,6 +1097,368 @@
 
 /*-------------------------------------------------------------------------*/
 
+static int verify_not_halted (int ep, struct urb *urb)
+{
+	int	retval;
+	u16	status;
+
+	/* shouldn't look or act halted */
+	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	if (retval < 0) {
+		dbg ("ep %02x couldn't get no-halt status, %d", ep, retval);
+		return retval;
+	}
+	if (status != 0) {
+		dbg ("ep %02x bogus status: %04x != 0", ep, status);
+		return -EINVAL;
+	}
+	retval = simple_io (urb, 1, 0, 0, __FUNCTION__);
+	if (retval != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int verify_halted (int ep, struct urb *urb)
+{
+	int	retval;
+	u16	status;
+
+	/* should look and act halted */
+	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	if (retval < 0) {
+		dbg ("ep %02x couldn't get halt status, %d", ep, retval);
+		return retval;
+	}
+	if (status != 1) {
+		dbg ("ep %02x bogus status: %04x != 1", ep, status);
+		return -EINVAL;
+	}
+	retval = simple_io (urb, 1, 0, -EPIPE, __FUNCTION__);
+	if (retval != -EPIPE)
+		return -EINVAL;
+	retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
+	if (retval != -EPIPE)
+		return -EINVAL;
+	return 0;
+}
+
+static int test_halt (int ep, struct urb *urb)
+{
+	int	retval;
+
+	/* shouldn't look or act halted now */
+	retval = verify_not_halted (ep, urb);
+	if (retval < 0)
+		return retval;
+
+	/* set halt (protocol test only), verify it worked */
+	retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0),
+			USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT, 0, ep,
+			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+	if (retval < 0) {
+		dbg ("ep %02x couldn't set halt, %d", ep, retval);
+		return retval;
+	}
+	retval = verify_halted (ep, urb);
+	if (retval < 0)
+		return retval;
+
+	/* clear halt (tests API + protocol), verify it worked */
+	retval = usb_clear_halt (urb->dev, urb->pipe);
+	if (retval < 0) {
+		dbg ("ep %02x couldn't clear halt, %d", ep, retval);
+		return retval;
+	}
+	retval = verify_not_halted (ep, urb);
+	if (retval < 0)
+		return retval;
+
+	/* NOTE:  could also verify SET_INTERFACE clear halts ... */
+
+	return 0;
+}
+
+static int halt_simple (struct usbtest_dev *dev)
+{
+	int		ep;
+	int		retval = 0;
+	struct urb	*urb;
+
+	urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512);
+	if (urb == 0)
+		return -ENOMEM;
+
+	if (dev->in_pipe) {
+		ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN;
+		urb->pipe = dev->in_pipe;
+		retval = test_halt (ep, urb);
+		if (retval < 0)
+			goto done;
+	}
+
+	if (dev->out_pipe) {
+		ep = usb_pipeendpoint (dev->out_pipe);
+		urb->pipe = dev->out_pipe;
+		retval = test_halt (ep, urb);
+	}
+done:
+	simple_free_urb (urb);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Control OUT tests use the vendor control requests from Intel's
+ * USB 2.0 compliance test device:  write a buffer, read it back.
+ *
+ * Intel's spec only _requires_ that it work for one packet, which
+ * is pretty weak.   Some HCDs place limits here; most devices will
+ * need to be able to handle more than one OUT data packet.  We'll
+ * try whatever we're told to try.
+ */
+static int ctrl_out (struct usbtest_dev *dev,
+		unsigned count, unsigned length, unsigned vary)
+{
+	unsigned		i, j, len, retval;
+	u8			*buf;
+	char			*what = "?";
+	struct usb_device	*udev;
+	
+	if (length > 0xffff || vary >= length)
+		return -EINVAL;
+
+	buf = kmalloc(length, SLAB_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	udev = testdev_to_usbdev (dev);
+	len = length;
+	retval = 0;
+
+	/* NOTE:  hardware might well act differently if we pushed it
+	 * with lots back-to-back queued requests.
+	 */
+	for (i = 0; i < count; i++) {
+		/* write patterned data */
+		for (j = 0; j < len; j++)
+			buf [j] = i + j;
+		retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0),
+				0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
+				0, 0, buf, len, HZ * USB_CTRL_SET_TIMEOUT);
+		if (retval != len) {
+			what = "write";
+			break;
+		}
+
+		/* read it back -- assuming nothing intervened!!  */
+		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0),
+				0x5c, USB_DIR_IN|USB_TYPE_VENDOR,
+				0, 0, buf, len, HZ * USB_CTRL_GET_TIMEOUT);
+		if (retval != len) {
+			what = "read";
+			break;
+		}
+
+		/* fail if we can't verify */
+		for (j = 0; j < len; j++) {
+			if (buf [j] != (u8) (i + j)) {
+				INFO (dev, "ctrl_out, byte %d is %d not %d\n",
+					j, buf [j], (u8) i + j);
+				retval = -EBADMSG;
+				break;
+			}
+		}
+		if (retval < 0) {
+			what = "verify";
+			break;
+		}
+
+		len += vary;
+		if (len > length)
+			len = 0;
+	}
+
+	if (retval < 0)
+		INFO (dev, "ctrl_out %s failed, code %d, count %d\n",
+			what, retval, i);
+
+	kfree (buf);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ISO tests ... mimics common usage
+ *  - buffer length is split into N packets (mostly maxpacket sized)
+ *  - multi-buffers according to sglen
+ */
+
+struct iso_context {
+	unsigned		count;
+	unsigned		pending;
+	spinlock_t		lock;
+	struct completion	done;
+	unsigned long		errors;
+	struct usbtest_dev	*dev;
+};
+
+static void iso_callback (struct urb *urb, struct pt_regs *regs)
+{
+	struct iso_context	*ctx = urb->context;
+
+	spin_lock(&ctx->lock);
+	ctx->count--;
+
+	if (urb->error_count > 0)
+		ctx->errors += urb->error_count;
+
+	if (urb->status == 0 && ctx->count > (ctx->pending - 1)) {
+		int status = usb_submit_urb (urb, GFP_ATOMIC);
+		switch (status) {
+		case 0:
+			goto done;
+		default:
+			dev_dbg (&ctx->dev->intf->dev,
+					"iso resubmit err %d\n",
+					status);
+			/* FALLTHROUGH */
+		case -ENODEV:			/* disconnected */
+			break;
+		}
+	}
+	simple_free_urb (urb);
+
+	ctx->pending--;
+	if (ctx->pending == 0) {
+		if (ctx->errors)
+			dev_dbg (&ctx->dev->intf->dev,
+				"iso test, %lu errors\n",
+				ctx->errors);
+		complete (&ctx->done);
+	} else
+done:
+	spin_unlock(&ctx->lock);
+}
+
+static struct urb *iso_alloc_urb (
+	struct usb_device	*udev,
+	int			pipe,
+	struct usb_endpoint_descriptor	*desc,
+	long			bytes
+)
+{
+	struct urb		*urb;
+	unsigned		i, maxp, packets;
+
+	if (bytes < 0 || !desc)
+		return 0;
+	maxp = 0x7ff & desc->wMaxPacketSize;
+	maxp *= 1 + (0x3 & (desc->wMaxPacketSize >> 11));
+	packets = (bytes + maxp - 1) / maxp;
+
+	urb = usb_alloc_urb (packets, SLAB_KERNEL);
+	if (!urb)
+		return urb;
+	urb->dev = udev;
+	urb->pipe = pipe;
+
+	urb->number_of_packets = packets;
+	urb->transfer_buffer_length = bytes;
+	urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL,
+			&urb->transfer_dma);
+	if (!urb->transfer_buffer) {
+		usb_free_urb (urb);
+		return 0;
+	}
+	memset (urb->transfer_buffer, 0, bytes);
+	for (i = 0; i < packets; i++) {
+		/* here, only the last packet will be short */
+		urb->iso_frame_desc[i].length = min ((unsigned) bytes, maxp);
+		bytes -= urb->iso_frame_desc[i].length;
+
+		urb->iso_frame_desc[i].offset = maxp * i;
+	}
+
+	urb->complete = iso_callback;
+	// urb->context = SET BY CALLER
+	urb->interval = 1 << (desc->bInterval - 1);
+	urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+	return urb;
+}
+
+static int
+test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+		int pipe, struct usb_endpoint_descriptor *desc)
+{
+	struct iso_context	context;
+	struct usb_device	*udev;
+	unsigned		i;
+	unsigned long		packets = 0;
+	int			status;
+	struct urb		*urbs[10];	/* FIXME no limit */
+
+	if (param->sglen > 10)
+		return -EDOM;
+
+	context.count = param->iterations * param->sglen;
+	context.pending = param->sglen;
+	context.errors = 0;
+	context.dev = dev;
+	init_completion (&context.done);
+	spin_lock_init (&context.lock);
+
+	memset (urbs, 0, sizeof urbs);
+	udev = testdev_to_usbdev (dev);
+	dev_dbg (&dev->intf->dev,
+		"... iso period %d %sframes, wMaxPacket %04x\n",
+		1 << (desc->bInterval - 1),
+		(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
+		desc->wMaxPacketSize);
+
+	for (i = 0; i < param->sglen; i++) {
+		urbs [i] = iso_alloc_urb (udev, pipe, desc,
+				param->length);
+		if (!urbs [i]) {
+			status = -ENOMEM;
+			goto fail;
+		}
+		packets += urbs[i]->number_of_packets;
+		urbs [i]->context = &context;
+	}
+	packets *= param->iterations;
+	dev_dbg (&dev->intf->dev,
+		"... total %lu msec (%lu packets)\n",
+		(packets * (1 << (desc->bInterval - 1)))
+			/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
+		packets);
+
+	spin_lock_irq (&context.lock);
+	for (i = 0; i < param->sglen; i++) {
+		status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
+		if (status < 0) {
+			ERROR (dev, "submit iso[%d], error %d\n", i, status);
+			if (i == 0)
+				goto fail;
+
+			simple_free_urb (urbs [i]);
+			context.pending--;
+		}
+	}
+	spin_unlock_irq (&context.lock);
+
+	wait_for_completion (&context.done);
+	return 0;
+
+fail:
+	for (i = 0; i < param->sglen; i++) {
+		if (urbs [i])
+			simple_free_urb (urbs [i]);
+	}
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* We only have this one interface to user space, through usbfs.
  * User mode code can scan usbfs to find N different devices (maybe on
  * different busses) to use when testing, and allocate one thread per
@@ -1047,8 +1511,9 @@
 		}
 		res = set_altsetting (dev, dev->info->alt);
 		if (res) {
-			err ("%s: set altsetting to %d failed, %d",
-					dev->id, dev->info->alt, res);
+			dev_err (&intf->dev,
+					"set altsetting to %d failed, %d\n",
+					dev->info->alt, res);
 			up (&dev->sem);
 			return res;
 		}
@@ -1067,7 +1532,7 @@
 	switch (param->test_num) {
 
 	case 0:
-		dbg ("%s TEST 0:  NOP", dev->id);
+		dev_dbg (&intf->dev, "TEST 0:  NOP\n");
 		retval = 0;
 		break;
 
@@ -1075,7 +1540,8 @@
 	case 1:
 		if (dev->out_pipe == 0)
 			break;
-		dbg ("%s TEST 1:  write %d bytes %u times", dev->id,
+		dev_dbg (&intf->dev,
+				"TEST 1:  write %d bytes %u times\n",
 				param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
 		if (!urb) {
@@ -1083,13 +1549,14 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = simple_io (urb, param->iterations, 0);
+		retval = simple_io (urb, param->iterations, 0, 0, "test1");
 		simple_free_urb (urb);
 		break;
 	case 2:
 		if (dev->in_pipe == 0)
 			break;
-		dbg ("%s TEST 2:  read %d bytes %u times", dev->id,
+		dev_dbg (&intf->dev,
+				"TEST 2:  read %d bytes %u times\n",
 				param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
 		if (!urb) {
@@ -1097,13 +1564,14 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = simple_io (urb, param->iterations, 0);
+		retval = simple_io (urb, param->iterations, 0, 0, "test2");
 		simple_free_urb (urb);
 		break;
 	case 3:
 		if (dev->out_pipe == 0 || param->vary == 0)
 			break;
-		dbg ("%s TEST 3:  write/%d 0..%d bytes %u times", dev->id,
+		dev_dbg (&intf->dev,
+				"TEST 3:  write/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
 		if (!urb) {
@@ -1111,13 +1579,15 @@
 			break;
 		}
 		// FIRMWARE:  bulk sink (maybe accepts short writes)
-		retval = simple_io (urb, param->iterations, param->vary);
+		retval = simple_io (urb, param->iterations, param->vary,
+					0, "test3");
 		simple_free_urb (urb);
 		break;
 	case 4:
 		if (dev->in_pipe == 0 || param->vary == 0)
 			break;
-		dbg ("%s TEST 4:  read/%d 0..%d bytes %u times", dev->id,
+		dev_dbg (&intf->dev,
+				"TEST 4:  read/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
 		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
 		if (!urb) {
@@ -1125,7 +1595,8 @@
 			break;
 		}
 		// FIRMWARE:  bulk source (maybe generates short writes)
-		retval = simple_io (urb, param->iterations, param->vary);
+		retval = simple_io (urb, param->iterations, param->vary,
+					0, "test4");
 		simple_free_urb (urb);
 		break;
 
@@ -1133,8 +1604,9 @@
 	case 5:
 		if (dev->out_pipe == 0 || param->sglen == 0)
 			break;
-		dbg ("%s TEST 5:  write %d sglists, %d entries of %d bytes",
-				dev->id, param->iterations,
+		dev_dbg (&intf->dev,
+			"TEST 5:  write %d sglists %d entries of %d bytes\n",
+				param->iterations,
 				param->sglen, param->length);
 		sg = alloc_sglist (param->sglen, param->length, 0);
 		if (!sg) {
@@ -1150,8 +1622,9 @@
 	case 6:
 		if (dev->in_pipe == 0 || param->sglen == 0)
 			break;
-		dbg ("%s TEST 6:  read %d sglists, %d entries of %d bytes",
-				dev->id, param->iterations,
+		dev_dbg (&intf->dev,
+			"TEST 6:  read %d sglists %d entries of %d bytes\n",
+				param->iterations,
 				param->sglen, param->length);
 		sg = alloc_sglist (param->sglen, param->length, 0);
 		if (!sg) {
@@ -1166,8 +1639,9 @@
 	case 7:
 		if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0)
 			break;
-		dbg ("%s TEST 7:  write/%d %d sglists, %d entries 0..%d bytes",
-				dev->id, param->vary, param->iterations,
+		dev_dbg (&intf->dev,
+			"TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
+				param->vary, param->iterations,
 				param->sglen, param->length);
 		sg = alloc_sglist (param->sglen, param->length, param->vary);
 		if (!sg) {
@@ -1182,8 +1656,9 @@
 	case 8:
 		if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0)
 			break;
-		dbg ("%s TEST 8:  read/%d %d sglists, %d entries 0..%d bytes",
-				dev->id, param->vary, param->iterations,
+		dev_dbg (&intf->dev,
+			"TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
+				param->vary, param->iterations,
 				param->sglen, param->length);
 		sg = alloc_sglist (param->sglen, param->length, param->vary);
 		if (!sg) {
@@ -1199,8 +1674,9 @@
 	/* non-queued sanity tests for control (chapter 9 subset) */
 	case 9:
 		retval = 0;
-		dbg ("%s TEST 9:  ch9 (subset) control tests, %d times",
-				dev->id, param->iterations);
+		dev_dbg (&intf->dev,
+			"TEST 9:  ch9 (subset) control tests, %d times\n",
+				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
 			retval = ch9_postconfig (dev);
 		if (retval)
@@ -1212,8 +1688,9 @@
 		if (param->sglen == 0)
 			break;
 		retval = 0;
-		dbg ("%s TEST 10:  queue %d control calls, %d times",
-				dev->id, param->sglen,
+		dev_dbg (&intf->dev,
+				"TEST 10:  queue %d control calls, %d times\n",
+				param->sglen,
 				param->iterations);
 		retval = test_ctrl_queue (dev, param);
 		break;
@@ -1223,10 +1700,11 @@
 		if (dev->in_pipe == 0 || !param->length)
 			break;
 		retval = 0;
-		dbg ("%s TEST 11:  unlink %d reads of %d",
-				dev->id, param->iterations, param->length);
+		dev_dbg (&intf->dev, "TEST 11:  unlink %d reads of %d\n",
+				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->in_pipe, param->length);
+			retval = unlink_simple (dev, dev->in_pipe,
+						param->length);
 		if (retval)
 			dbg ("unlink reads failed, iterations left %d", i);
 		break;
@@ -1234,14 +1712,65 @@
 		if (dev->out_pipe == 0 || !param->length)
 			break;
 		retval = 0;
-		dbg ("%s TEST 12:  unlink %d writes of %d",
-				dev->id, param->iterations, param->length);
+		dev_dbg (&intf->dev, "TEST 12:  unlink %d writes of %d\n",
+				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->out_pipe, param->length);
+			retval = unlink_simple (dev, dev->out_pipe,
+						param->length);
 		if (retval)
 			dbg ("unlink writes failed, iterations left %d", i);
 		break;
 
+	/* ep halt tests */
+	case 13:
+		if (dev->out_pipe == 0 && dev->in_pipe == 0)
+			break;
+		retval = 0;
+		dev_dbg (&intf->dev, "TEST 13:  set/clear %d halts\n",
+				param->iterations);
+		for (i = param->iterations; retval == 0 && i--; /* NOP */)
+			retval = halt_simple (dev);
+		
+		if (retval)
+			DBG (dev, "halts failed, iterations left %d\n", i);
+		break;
+
+	/* control write tests */
+	case 14:
+		if (!dev->info->ctrl_out)
+			break;
+		dev_dbg (&intf->dev, "TEST 14:  %d ep0out, 0..%d vary %d\n",
+				param->iterations, param->length, param->vary);
+		retval = ctrl_out (dev, param->iterations, 
+				param->length, param->vary);
+		break;
+
+	/* iso write tests */
+	case 15:
+		if (dev->out_iso_pipe == 0 || param->sglen == 0)
+			break;
+		dev_dbg (&intf->dev, 
+			"TEST 15:  write %d iso, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		// FIRMWARE:  iso sink
+		retval = test_iso_queue (dev, param,
+				dev->out_iso_pipe, dev->iso_out);
+		break;
+
+	/* iso read tests */
+	case 16:
+		if (dev->in_iso_pipe == 0 || param->sglen == 0)
+			break;
+		dev_dbg (&intf->dev,
+			"TEST 16:  read %d iso, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		// FIRMWARE:  iso source
+		retval = test_iso_queue (dev, param,
+				dev->in_iso_pipe, dev->iso_in);
+		break;
+
 	// FIXME unlink from queue (ring with N urbs)
 
 	// FIXME scatterlist cancel (needs helper thread)
@@ -1262,7 +1791,7 @@
 
 static int force_interrupt = 0;
 MODULE_PARM (force_interrupt, "i");
-MODULE_PARM_DESC (force_interrupt, "0 = test bulk (default), else interrupt");
+MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt");
 
 #ifdef	GENERIC
 static int vendor;
@@ -1281,6 +1810,7 @@
 	struct usbtest_dev	*dev;
 	struct usbtest_info	*info;
 	char			*rtest, *wtest;
+	char			*irtest, *iwtest;
 
 	udev = interface_to_usbdev (intf);
 
@@ -1306,10 +1836,6 @@
 	dev->info = info;
 	init_MUTEX (&dev->sem);
 
-	/* use the same kind of id the hid driver shows */
-	snprintf (dev->id, sizeof dev->id, "%s-%s:%d",
-			udev->bus->bus_name, udev->devpath,
-			intf->altsetting [0].desc.bInterfaceNumber);
 	dev->intf = intf;
 
 	/* cacheline-aligned scratch for i/o */
@@ -1323,6 +1849,7 @@
 	 * "high bandwidth" modes (up to 3 packets/uframe).
 	 */
 	rtest = wtest = "";
+	irtest = iwtest = "";
 	if (force_interrupt || udev->speed == USB_SPEED_LOW) {
 		if (info->ep_in) {
 			dev->in_pipe = usb_rcvintpipe (udev, info->ep_in);
@@ -1341,6 +1868,7 @@
 				dbg ("couldn't get endpoints, %d\n", status);
 				return status;
 			}
+			/* may find bulk or ISO pipes */
 		} else {
 			if (info->ep_in)
 				dev->in_pipe = usb_rcvbulkpipe (udev,
@@ -1353,18 +1881,26 @@
 			rtest = " bulk-in";
 		if (dev->out_pipe)
 			wtest = " bulk-out";
+		if (dev->in_iso_pipe)
+			irtest = " iso-in";
+		if (dev->out_iso_pipe)
+			iwtest = " iso-out";
 	}
 
 	usb_set_intfdata (intf, dev);
-	info ("%s at %s ... %s speed {control%s%s} tests",
-			info->name, dev->id,
+	dev_info (&intf->dev, "%s\n", info->name);
+	dev_info (&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n",
 			({ char *tmp;
 			switch (udev->speed) {
 			case USB_SPEED_LOW: tmp = "low"; break;
 			case USB_SPEED_FULL: tmp = "full"; break;
 			case USB_SPEED_HIGH: tmp = "high"; break;
 			default: tmp = "unknown"; break;
-			}; tmp; }), rtest, wtest);
+			}; tmp; }),
+			info->ctrl_out ? " in/out" : "",
+			rtest, wtest,
+			irtest, iwtest,
+			info->alt >= 0 ? " (+alt)" : "");
 	return 0;
 }
 
@@ -1375,7 +1911,7 @@
 	down (&dev->sem);
 
 	usb_set_intfdata (intf, NULL);
-	info ("unbound %s", dev->id);
+	dev_dbg (&intf->dev, "disconnect\n");
 	kfree (dev);
 }
 
@@ -1423,6 +1959,7 @@
 static struct usbtest_info gz_info = {
 	.name		= "Linux gadget zero",
 	.autoconf	= 1,
+	.ctrl_out	= 1,
 	.alt		= 0,
 };
 
@@ -1432,6 +1969,13 @@
 	.alt		= -1,
 };
 
+static struct usbtest_info um2_info = {
+	.name		= "Linux user mode ISO test driver",
+	.autoconf	= 1,
+	.iso		= 1,
+	.alt		= -1,
+};
+
 #ifdef IBOT2
 /* this is a nice source of high speed bulk data;
  * uses an FX2, with firmware provided in the device
@@ -1500,6 +2044,11 @@
 	/* so does a user-mode variant */
 	{ USB_DEVICE (0x0525, 0xa4a4),
 		.driver_info = (unsigned long) &um_info,
+		},
+
+	/* ... and a user-mode variant that talks iso */
+	{ USB_DEVICE (0x0525, 0xa4a3),
+		.driver_info = (unsigned long) &um2_info,
 		},
 
 #ifdef KEYSPAN_19Qi
diff -Nru a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
--- a/drivers/usb/misc/uss720.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/misc/uss720.c	Sun Feb  8 20:57:49 2004
@@ -333,7 +333,7 @@
 	for (; got < length; got++) {
 		if (get_1284_register(pp, 4, (char *)buf))
 			break;
-		((char*)buf)++;
+		buf++;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
 			break;
@@ -392,7 +392,7 @@
 	for (; got < length; got++) {
 		if (get_1284_register(pp, 3, (char *)buf))
 			break;
-		((char*)buf)++;
+		buf++;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
 			break;
@@ -412,7 +412,7 @@
 	for (; written < length; written++) {
 		if (set_1284_register(pp, 3, *(char *)buf))
 			break;
-		((char*)buf)++;
+		buf++;
 		if (get_1284_register(pp, 1, NULL))
 			break;
 		if (priv->reg[0] & 0x01) {
@@ -469,7 +469,7 @@
 	for (; written < len; written++) {
 		if (set_1284_register(pp, 5, *(char *)buffer))
 			break;
-		((char*)buffer)++;
+		buffer++;
 	}
 	change_mode(pp, ECR_PS2);
 	return written;
diff -Nru a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
--- a/drivers/usb/net/Kconfig	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/net/Kconfig	Sun Feb  8 20:57:49 2004
@@ -254,13 +254,14 @@
 	  10/100 Ethernet devices.
 
  	  This driver should work with at least the following devices:
+	    * Aten UC210T
 	    * ASIX AX88172
 	    * D-Link DUB-E100
 	    * Hawking UF200
 	    * Linksys USB200M
 	    * Netgear FA120
-	    * Intellinet
-	    * ST Lab USB Ethernet
+	    * Intellinet USB 2.0 Ethernet
+	    * ST Lab USB 2.0 Ethernet
 	    * TrendNet TU2-ET100
 
 	  This driver creates an interface named "ethX", where X depends on
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/net/usbnet.c	Sun Feb  8 20:57:49 2004
@@ -222,6 +222,7 @@
 #define FLAG_FRAMING_NC	0x0001		/* guard against device dropouts */ 
 #define FLAG_FRAMING_GL	0x0002		/* genelink batches packets */
 #define FLAG_FRAMING_Z	0x0004		/* zaurus adds a trailer */
+#define FLAG_FRAMING_RN	0x0008		/* RNDIS batches, plus huge header */
 
 #define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
 #define FLAG_ETHER	0x0020		/* maybe use "eth%d" names */
@@ -300,7 +301,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct ethtool_ops usbnet_ethtool_ops;
 static void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *);
 static u32 usbnet_get_link (struct net_device *);
 static u32 usbnet_get_msglevel (struct net_device *);
@@ -364,6 +364,25 @@
 	return 0;
 }
 
+static void skb_return (struct usbnet *dev, struct sk_buff *skb)
+{
+	int	status;
+
+	skb->dev = dev->net;
+	skb->protocol = eth_type_trans (skb, dev->net);
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += skb->len;
+
+#ifdef	VERBOSE
+	devdbg (dev, "< rx, len %d, type 0x%x",
+		skb->len + sizeof (struct ethhdr), skb->protocol);
+#endif
+	memset (skb->cb, 0, sizeof (struct skb_data));
+	status = netif_rx (skb);
+	if (status != NET_RX_SUCCESS)
+		devdbg (dev, "netif_rx status %d", status);
+}
+
 
 #ifdef	CONFIG_USB_AN2720
 #define	HAVE_HARDWARE
@@ -818,23 +837,30 @@
 
 
 
-#if	defined (CONFIG_USB_CDCETHER) || defined (CONFIG_USB_ZAURUS)
-
 /*-------------------------------------------------------------------------
  *
- * Communications Device Class, Ethernet Control model
- * 
- * Takes two interfaces.  The DATA interface is inactive till an altsetting
- * is selected.  Configuration data includes class descriptors.
- *
- * Zaurus uses nonstandard framing, and doesn't uniquify its Ethernet
- * addresses, but is otherwise CDC Ether.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with.
+ * Communications Device Class declarations.
+ * Used by CDC Ethernet, and some CDC variants
  *
  *-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_USB_CDCETHER
+#define NEED_GENERIC_CDC
+#endif
+
+#ifdef	CONFIG_USB_ZAURUS
+/* Ethernet variant uses funky framing, broken ethernet addressing */
+#define NEED_GENERIC_CDC
+#endif
+
+#ifdef	CONFIG_USB_RNDIS
+/* ACM variant uses even funkier framing, complex control RPC scheme */
+#define NEED_GENERIC_CDC
+#endif
+
+
+#ifdef	NEED_GENERIC_CDC
+
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct header_desc {
 	u8	bLength;
@@ -876,43 +902,21 @@
 	struct usb_interface	*data;
 };
 
-#include <linux/ctype.h>
-
-static u8 nibble (unsigned char c)
-{
-	if (likely (isdigit (c)))
-		return c - '0';
-	c = toupper (c);
-	if (likely (isxdigit (c)))
-		return 10 + c - 'A';
-	return 0;
-}
-
-static inline int get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
-{
-	int 		tmp, i;
-	unsigned char	buf [13];
-
-	tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
-	if (tmp < 0)
-		return tmp;
-	else if (tmp != 12)
-		return -EINVAL;
-	for (i = tmp = 0; i < 6; i++, tmp += 2)
-		dev->net->dev_addr [i] =
-			 (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
-	return 0;
-}
-
 static struct usb_driver usbnet_driver;
 
-static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
+/*
+ * probes control interface, claims data interface, collects the bulk
+ * endpoints, activates data interface (if needed), maybe sets MTU.
+ * all pure cdc, except for certain firmware workarounds.
+ */
+static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 {
 	u8				*buf = intf->altsetting->extra;
 	int				len = intf->altsetting->extralen;
 	struct usb_interface_descriptor	*d;
 	struct cdc_state		*info = (void *) &dev->data;
 	int				status;
+	int				rndis;
 
 	if (sizeof dev->data < sizeof *info)
 		return -EDOM;
@@ -931,14 +935,23 @@
 				"CDC descriptors on config\n");
 	}
 
+	/* this assumes that if there's a non-RNDIS vendor variant
+	 * of cdc-acm, it'll fail RNDIS requests cleanly.
+	 */
+	rndis = (intf->altsetting->desc.bInterfaceProtocol == 0xff);
+
 	memset (info, 0, sizeof *info);
 	info->control = intf;
 	while (len > 3) {
 		if (buf [1] != USB_DT_CS_INTERFACE)
 			goto next_desc;
 
-		/* bDescriptorSubType identifies three "must have" descriptors;
-		 * save them for later.
+		/* use bDescriptorSubType to identify the CDC descriptors.
+		 * We expect devices with CDC header and union descriptors.
+		 * For CDC Ethernet we need the ethernet descriptor.
+		 * For RNDIS, ignore two (pointless) CDC modem descriptors
+		 * in favor of a complicated OID-based RPC scheme doing what
+		 * CDC Ethernet achieves with a simple descriptor.
 		 */
 		switch (buf [2]) {
 		case 0x00:		/* Header, mostly useless */
@@ -1001,8 +1014,6 @@
 					d->bInterfaceClass);
 				goto bad_desc;
 			}
-			if (usb_interface_claimed (info->data))
-				return -EBUSY;
 			break;
 		case 0x0F:		/* Ethernet Networking */
 			if (info->ether) {
@@ -1015,13 +1026,20 @@
 					info->u->bLength);
 				goto bad_desc;
 			}
+			dev->net->mtu = cpu_to_le16p (
+						&info->ether->wMaxSegmentSize)
+					- ETH_HLEN;
+			/* because of Zaurus, we may be ignoring the host
+			 * side link address we were given.
+			 */
 			break;
 		}
 next_desc:
 		len -= buf [0];	/* bLength */
 		buf += buf [0];
 	}
-	if (!info->header || !info ->u || !info->ether) {
+
+	if (!info->header || !info->u || (!rndis && !info->ether)) {
 		dev_dbg (&intf->dev, "missing cdc %s%s%sdescriptor\n",
 			info->header ? "" : "header ",
 			info->u ? "" : "union ",
@@ -1029,18 +1047,6 @@
 		goto bad_desc;
 	}
 
-#ifdef CONFIG_USB_ZAURUS
-	/* Zaurus ethernet addresses aren't unique ... */
-	if ((dev->driver_info->flags & FLAG_FRAMING_Z) != 0)
-		/* ignore */ ;
-	else
-#endif
-	{
-		status = get_ethernet_addr (dev, info->ether);
-		if (status < 0)
-			return status;
-	}
-
 	/* claim data interface and set it up ... with side effects.
 	 * network traffic can't flow until an altsetting is enabled.
 	 */
@@ -1049,16 +1055,11 @@
 		return status;
 	status = get_endpoints (dev, info->data);
 	if (status < 0) {
+		/* ensure immediate exit from usbnet_disconnect */
+		usb_set_intfdata(info->data, NULL);
 		usb_driver_release_interface (&usbnet_driver, info->data);
 		return status;
 	}
-
-	/* FIXME cdc-ether has some multicast code too, though it complains
-	 * in routine cases.  info->ether describes the multicast support.
-	 */
-
-	dev->net->mtu = cpu_to_le16p (&info->ether->wMaxSegmentSize)
-		- ETH_HLEN;
 	return 0;
 
 bad_desc:
@@ -1072,24 +1073,89 @@
 
 	/* disconnect master --> disconnect slave */
 	if (intf == info->control && info->data) {
+		/* ensure immediate exit from usbnet_disconnect */
+		usb_set_intfdata(info->data, NULL);
 		usb_driver_release_interface (&usbnet_driver, info->data);
 		info->data = 0;
 	}
 
 	/* and vice versa (just in case) */
 	else if (intf == info->data && info->control) {
+		/* ensure immediate exit from usbnet_disconnect */
+		usb_set_intfdata(info->control, NULL);
 		usb_driver_release_interface (&usbnet_driver, info->control);
 		info->control = 0;
 	}
-
 }
 
-#endif	/* CONFIG_USB_ZAURUS || CONFIG_USB_CDCETHER */
-
+#endif	/* NEED_GENERIC_CDC */
 
+
 #ifdef	CONFIG_USB_CDCETHER
 #define	HAVE_HARDWARE
 
+/*-------------------------------------------------------------------------
+ *
+ * Communications Device Class, Ethernet Control model
+ * 
+ * Takes two interfaces.  The DATA interface is inactive till an altsetting
+ * is selected.  Configuration data includes class descriptors.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <linux/ctype.h>
+
+static u8 nibble (unsigned char c)
+{
+	if (likely (isdigit (c)))
+		return c - '0';
+	c = toupper (c);
+	if (likely (isxdigit (c)))
+		return 10 + c - 'A';
+	return 0;
+}
+
+static inline int
+get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
+{
+	int 		tmp, i;
+	unsigned char	buf [13];
+
+	tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf);
+	if (tmp < 0)
+		return tmp;
+	else if (tmp != 12)
+		return -EINVAL;
+	for (i = tmp = 0; i < 6; i++, tmp += 2)
+		dev->net->dev_addr [i] =
+			 (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]);
+	return 0;
+}
+
+static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
+{
+	int				status;
+	struct cdc_state		*info = (void *) &dev->data;
+
+	status = generic_cdc_bind (dev, intf);
+	if (status < 0)
+		return status;
+
+	status = get_ethernet_addr (dev, info->ether);
+	if (status < 0) {
+		usb_driver_release_interface (&usbnet_driver, info->data);
+		return status;
+	}
+
+	/* FIXME cdc-ether has some multicast code too, though it complains
+	 * in routine cases.  info->ether describes the multicast support.
+	 */
+	return 0;
+}
+
 static const struct driver_info	cdc_info = {
 	.description =	"CDC Ethernet Device",
 	.flags =	FLAG_ETHER,
@@ -1337,7 +1403,6 @@
 	struct gl_header	*header;
 	struct gl_packet	*packet;
 	struct sk_buff		*gl_skb;
-	int			status;
 	u32			size;
 
 	header = (struct gl_header *) skb->data;
@@ -1373,17 +1438,7 @@
 
 			// copy the packet data to the new skb
 			memcpy(skb_put(gl_skb, size), packet->packet_data, size);
-			gl_skb->dev = dev->net;
-
-			// determine the packet's protocol ID
-			gl_skb->protocol = eth_type_trans (gl_skb, dev->net);
-
-			// update the status
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += size;
-
-			// notify os of the received packet
-			status = netif_rx (gl_skb);
+			skb_return (dev, skb);
 		}
 
 		// advance to the next packet
@@ -2141,7 +2196,7 @@
 	.description =	"Sharp Zaurus SL-5x00",
 	.flags =	FLAG_FRAMING_Z,
 	.check_connect = always_connected,
-	.bind =		cdc_bind,
+	.bind =		generic_cdc_bind,
 	.unbind =	cdc_unbind,
 	.tx_fixup = 	zaurus_tx_fixup,
 };
@@ -2256,6 +2311,11 @@
 		size = 6 + (sizeof (struct ethhdr) + dev->net->mtu);
 	else
 #endif
+#ifdef CONFIG_USB_RNDIS
+	if (dev->driver_info->flags & FLAG_FRAMING_RN)
+		size = RNDIS_MAX_TRANSFER;
+	else
+#endif
 		size = (sizeof (struct ethhdr) + dev->net->mtu);
 
 	if ((skb = alloc_skb (size, flags)) == 0) {
@@ -2319,23 +2379,9 @@
 		goto error;
 	// else network stack removes extra byte if we forced a short packet
 
-	if (skb->len) {
-		int	status;
-
-		skb->dev = dev->net;
-		skb->protocol = eth_type_trans (skb, dev->net);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-
-#ifdef	VERBOSE
-		devdbg (dev, "< rx, len %d, type 0x%x",
-			skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
-		memset (skb->cb, 0, sizeof (struct skb_data));
-		status = netif_rx (skb);
-		if (status != NET_RX_SUCCESS)
-			devdbg (dev, "netif_rx status %d", status);
-	} else {
+	if (skb->len)
+		skb_return (dev, skb);
+	else {
 		devdbg (dev, "drop");
 error:
 		dev->stats.rx_errors++;
@@ -2544,6 +2590,8 @@
 			framing = "GeneSys";
 		else if (dev->driver_info->flags & FLAG_FRAMING_Z)
 			framing = "Zaurus";
+		else if (dev->driver_info->flags & FLAG_FRAMING_RN)
+			framing = "RNDIS";
 		else
 			framing = "simple";
 
@@ -2941,6 +2989,8 @@
 
 /*-------------------------------------------------------------------------*/
 
+static struct ethtool_ops usbnet_ethtool_ops;
+
 // precondition: never called in_interrupt
 
 int
@@ -3127,7 +3177,11 @@
 	// Hawking UF200, TrendNet TU2-ET100
 	USB_DEVICE (0x07b8, 0x420a),
 	.driver_info =  (unsigned long) &hawking_uf200_info,
-}, 
+}, {
+	// ATEN UC210T
+	USB_DEVICE (0x0557, 0x2009),
+	.driver_info =  (unsigned long) &ax8817x_info,
+},
 #endif
 
 #ifdef	CONFIG_USB_EPSON2888
@@ -3167,6 +3221,14 @@
 },
 #endif
 
+#ifdef	CONFIG_USB_RNDIS
+{
+	/* RNDIS is MSFT's un-official variant of CDC ACM */
+	USB_INTERFACE_INFO (USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+	.driver_info = (unsigned long) &rndis_info,
+},
+#endif
+
 #ifdef	CONFIG_USB_ARMLINUX
 /*
  * SA-1100 using standard ARM Linux kernels, or compatible.
@@ -3238,7 +3300,16 @@
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
-	.idProduct              = 0x9031,	/* C-750 */
+	.idProduct              = 0x9031,	/* C-750 C-760 */
+	.bInterfaceClass        = 0x02,
+	.bInterfaceSubClass     = 0x0a,
+	.bInterfaceProtocol     = 0x00,
+	.driver_info =  (unsigned long) &zaurus_pxa_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	.idProduct              = 0x9032,	/* SL-6000 */
 	.bInterfaceClass        = 0x02,
 	.bInterfaceSubClass     = 0x0a,
 	.bInterfaceProtocol     = 0x00,
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/serial/belkin_sa.c	Sun Feb  8 20:57:49 2004
@@ -232,8 +232,10 @@
 
 	port->interrupt_in_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-	if (retval)
+	if (retval) {
+		usb_unlink_urb(port->read_urb);
 		err(" usb_submit_urb(read int) failed");
+	}
 
 exit:
 	return retval;
diff -Nru a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
--- a/drivers/usb/serial/kobil_sct.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/serial/kobil_sct.c	Sun Feb  8 20:57:49 2004
@@ -409,8 +409,6 @@
 	// someone sets the dev to 0 if the close method has been called
 	port->interrupt_in_urb->dev = port->serial->dev;
 
-	// usb_dump_urb(port->interrupt_in_urb);
-
 	result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); 
 	dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
 }
@@ -496,8 +494,6 @@
 		port->interrupt_in_urb->dev = port->serial->dev;
 		
 		// start reading
-		//usb_dump_urb(port->interrupt_in_urb);
-
 		result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); 
 		dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
 	}
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/serial/visor.c	Sun Feb  8 20:57:49 2004
@@ -241,6 +241,8 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ },					/* optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -274,6 +276,7 @@
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
+	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 	{ },					/* optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
--- a/drivers/usb/serial/visor.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/serial/visor.h	Sun Feb  8 20:57:49 2004
@@ -50,6 +50,9 @@
 #define GARMIN_VENDOR_ID		0x091E
 #define GARMIN_IQUE_3600_ID		0x0004
 
+#define ACEECA_VENDOR_ID		0x4766
+#define ACEECA_MEZ1000_ID		0x0001
+
 /****************************************************************************
  * Handspring Visor Vendor specific request codes (bRequest values)
  * A big thank you to Handspring for providing the following information.
diff -Nru a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
--- a/drivers/usb/storage/datafab.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/storage/datafab.h	Sun Feb  8 20:57:49 2004
@@ -29,7 +29,7 @@
 struct datafab_info {
 	unsigned long   sectors;	// total sector count
 	unsigned long   ssize;		// sector size in bytes
-	char		lun;		// used for dual-slot readers
+	signed char	lun;		// used for dual-slot readers
 	
 	// the following aren't used yet
 	unsigned char   sense_key;
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/storage/unusual_devs.h	Sun Feb  8 20:57:49 2004
@@ -604,7 +604,14 @@
  * - They don't like the INQUIRY command. So we must handle this command
  *   of the SCSI layer ourselves.
  */
-UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
+UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
+		"Casio",
+		"QV DigitalCamera",
+		US_SC_8070, US_PR_CB, NULL,
+		US_FL_FIX_INQUIRY ),
+
+/* Later Casio cameras apparently tell the truth */
+UNUSUAL_DEV( 0x07cf, 0x1001, 0x9010, 0x9999,
 		"Casio",
 		"QV DigitalCamera",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Sun Feb  8 20:57:49 2004
+++ b/drivers/usb/storage/usb.c	Sun Feb  8 20:57:49 2004
@@ -834,7 +834,7 @@
 
 	/* Finish the SCSI host removal sequence */
 	if (us->host) {
-		(struct us_data *) us->host->hostdata[0] = NULL;
+		us->host->hostdata[0] = 0;
 		scsi_host_put(us->host);
 	}
 
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Sun Feb  8 20:57:49 2004
+++ b/include/linux/usb.h	Sun Feb  8 20:57:49 2004
@@ -1016,16 +1016,6 @@
 
 /* -------------------------------------------------------------------------- */
 
-/*
- * Debugging and troubleshooting/diagnostic helpers.
- */
-void usb_show_device_descriptor(struct usb_device_descriptor *);
-void usb_show_config_descriptor(struct usb_config_descriptor *);
-void usb_show_interface_descriptor(struct usb_interface_descriptor *);
-void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *);
-void usb_show_device(struct usb_device *);
-void usb_show_string(struct usb_device *dev, char *id, int index);
-
 #ifdef DEBUG
 #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
 #else
