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 #include #include /* for UTS_SYSNAME */ -#include /* for hcd->pdev and dma addressing */ +#include +#include +#include +#include #include #include @@ -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 -#include -#include -#include -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif -#include - -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 @@ -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 -#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 +#include #include #include #include @@ -103,7 +104,7 @@ #include -#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 (®s->intrstatus)) == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); - return; + return IRQ_HANDLED; /* interrupt for some other device? */ } else if ((ints &= readl (®s->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 + * Maintainer: Alan Stern * * (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 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 - * - * 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 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 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 . - * - 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 . - * - 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 - * . - * - Modified the usb_string() reporting. See kfree() comment above. - * - Added Umax Astra 2000U. Thanks to Doug Alcorn . - * - 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 - * . - * - Added Umax 1220U ID's. Thanks to Maciek Klimkowski - * . - * - Fixed bug in write_scanner(). The buffer was not being properly - * updated for writes larger than OBUF_SIZE. Thanks to Henrik - * Johansson for identifying it. - * - Added Microtek X6 ID's. Thanks to Oliver Neukum - * . - * - * - * 0.4.1 2/15/2000 - * - * - Fixed 'count' bug in read_scanner(). Thanks to Henrik - * Johansson 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 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 . - * - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's. - * Thanks to Adrian Perez Jorge . - * - Fixed error number reported for non-existant devices. Thanks to - * Spyridon Papadimitriou . - * - Added Acer Prisascan 620U ID's. Thanks to Joao . - * - 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 - * - 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 - * . - * - Added iVina 1200U ID. Thanks to Dyson Lin . - * - Added access time update for the device file courtesy of Paul - * Mackerras . 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 . - * - Added Acer ScanPrisa 620U ID. Thanks to Oliver - * Schwartz 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 and Alain Knaff - * for discovering this. - * - Integrated Randy Dunlap's 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 . - * - * 0.4.4 - * - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB, - * and 1200 UB. Thanks to Henning Meier-Geinitz . - * - 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 . - * - Added the Epson Expression1600 ID's. Thanks to Karl Heinz - * Kremer . - * - * 0.4.5 2/28/2001 - * - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F). - * Thanks to Henning Meier-Geinitz . - * - 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 for - * reporting this bug. - * - Added Epson Perfection 1640SU and 1640SU Photo. Thanks to - * Jean-Luc and Manuel - * Pelayo . 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 - * - Added Umax Astra 2100U ID's. Thanks to Ron - * Wellsted . - * and Manuel Pelayo . - * - Added HP 3400 ID's. Thanks to Harald Hannelius - * and Bertrik Sikken . 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 - * - Confirmed addition for SnapScan E20. Thanks to Steffen Hübner - * . - * - Added Lifetec LT9385 ID's. Thanks to Van Bruwaene Kris - * - * - Added Agfa SnapScan e26 ID's. Reported to work with SANE - * 1.0.5. Thanks to Falk Sauer . - * - Added HP 4300 ID's. Thanks to Stefan Schlosser - * . - * - Added Relisis Episode ID's. Thanks to Manfred - * Morgner . - * - Added many Acer ID's. Thanks to Oliver - * Schwartz . - * - Added Snapscan e40 ID's. Thanks to Oliver - * Schwartz . - * - Thanks to Oliver Neukum - * for helping with races. - * - Added Epson Perfection 1650 ID's. Thanks to Karl Heinz - * Kremer . - * - Added Epson Perfection 2450 ID's (aka GT-9700 for the Japanese - * market). Thanks to Karl Heinz Kremer . - * - Added Mustek 600 USB ID's. Thanks to Marcus - * Alanen . - * - Added Acer ScanPrisa 1240UT ID's. Thanks to Morgan - * Collins . - * - Incorporated devfs patches!! Thanks to Tom Rini - * , Pavel Roskin , - * Greg KH , Yves Duret , - * Flavio Stanchina . - * - Removed Minolta ScanImage II. This scanner uses USB SCSI. Thanks - * to Oliver Neukum 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 for pointing it out. - * - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de - * Valenzuela" . - * - Added ID's for Agfa e25. Thanks to Heinrich - * Rust . Also reported to work with - * Linux and SANE (?). - * - Added Canon FB620U, D646U, and 1220U ID's. Thanks to Paul - * Rensing . 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" . 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 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 . - * - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use - * the Grandtech GT-6801 chip. Thanks to Henning - * Meier-Geinitz . - * - Increased Epson timeout to 60 secs as requested from - * Karl Heinz Kremer . - * - Changed maintainership from David E. Nelson to Brian - * Beattie . - * - * 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 , Stian Jordet - * , "Yann E. MORIN" , - * "Jaeger, Gerhard" , Ira Childress - * , Till Kamppeter , - * Ed Hamrick , Oliver Schwartz - * 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 ). - * - 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 - * . - * - * 0.4.10 01/07/2003 - * - Added vendor/product ids for Artec, Canon, Compaq, Epson, HP, Microtek - * and Visioneer scanners. Thanks to William Lam , - * Till Kamppeter 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 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 - -/* - * 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 - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// #define DEBUG - -#define DRIVER_VERSION "0.4.16" -#define DRIVER_DESC "USB Scanner Driver" - -#include - -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 + Copyright (c) 2000 Markus Demleitner 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 " #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 +#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) +# define DEBUG +#endif #include #include #include #include #include #include +#include #include -#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) -# define DEBUG -#endif #include @@ -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 - -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 + +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