Commit 71380949 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 9892c3b0 25b365ac
...@@ -1320,7 +1320,8 @@ int usb_bluetooth_init(void) ...@@ -1320,7 +1320,8 @@ int usb_bluetooth_init(void)
bluetooth_tty_driver->owner = THIS_MODULE; bluetooth_tty_driver->owner = THIS_MODULE;
bluetooth_tty_driver->driver_name = "usb-bluetooth"; bluetooth_tty_driver->driver_name = "usb-bluetooth";
bluetooth_tty_driver->name = "usb/ttub/"; bluetooth_tty_driver->name = "ttyUB";
bluetooth_tty_driver->devfs_name = "usb/ttub/";
bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR; bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
bluetooth_tty_driver->minor_start = 0; bluetooth_tty_driver->minor_start = 0;
bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
......
...@@ -765,7 +765,8 @@ static int __init acm_init(void) ...@@ -765,7 +765,8 @@ static int __init acm_init(void)
return -ENOMEM; return -ENOMEM;
acm_tty_driver->owner = THIS_MODULE, acm_tty_driver->owner = THIS_MODULE,
acm_tty_driver->driver_name = "acm", acm_tty_driver->driver_name = "acm",
acm_tty_driver->name = "usb/acm/", acm_tty_driver->name = "ttyACM",
acm_tty_driver->devfs_name = "usb/acm/",
acm_tty_driver->major = ACM_TTY_MAJOR, acm_tty_driver->major = ACM_TTY_MAJOR,
acm_tty_driver->minor_start = 0, acm_tty_driver->minor_start = 0,
acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
......
...@@ -359,7 +359,6 @@ static int usblp_open(struct inode *inode, struct file *file) ...@@ -359,7 +359,6 @@ static int usblp_open(struct inode *inode, struct file *file)
file->private_data = usblp; file->private_data = usblp;
usblp->writeurb->transfer_buffer_length = 0; usblp->writeurb->transfer_buffer_length = 0;
usblp->writeurb->status = 0;
usblp->wcomplete = 1; /* we begin writeable */ usblp->wcomplete = 1; /* we begin writeable */
usblp->rcomplete = 0; usblp->rcomplete = 0;
...@@ -833,22 +832,15 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -833,22 +832,15 @@ static int usblp_probe(struct usb_interface *intf,
init_waitqueue_head(&usblp->wait); init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; usblp->ifnum = intf->altsetting->desc.bInterfaceNumber;
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
err("Not able to get a minor for this device.");
goto abort;
}
usblp->minor = intf->minor;
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) { if (!usblp->writeurb) {
err("out of memory"); err("out of memory");
goto abort_minor; goto abort;
} }
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL); usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) { if (!usblp->readurb) {
err("out of memory"); err("out of memory");
goto abort_minor; goto abort;
} }
/* Malloc device ID string buffer to the largest expected length, /* Malloc device ID string buffer to the largest expected length,
...@@ -856,7 +848,7 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -856,7 +848,7 @@ static int usblp_probe(struct usb_interface *intf,
* could change in length. */ * could change in length. */
if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) { if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory for device_id_string"); err("out of memory for device_id_string");
goto abort_minor; goto abort;
} }
usblp->writebuf = usblp->readbuf = NULL; usblp->writebuf = usblp->readbuf = NULL;
...@@ -868,19 +860,19 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -868,19 +860,19 @@ static int usblp_probe(struct usb_interface *intf,
if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->writeurb->transfer_dma))) { GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
err("out of memory for write buf"); err("out of memory for write buf");
goto abort_minor; goto abort;
} }
if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->readurb->transfer_dma))) { GFP_KERNEL, &usblp->readurb->transfer_dma))) {
err("out of memory for read buf"); err("out of memory for read buf");
goto abort_minor; goto abort;
} }
/* Allocate buffer for printer status */ /* Allocate buffer for printer status */
usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
if (!usblp->statusbuf) { if (!usblp->statusbuf) {
err("out of memory for statusbuf"); err("out of memory for statusbuf");
goto abort_minor; goto abort;
} }
/* Lookup quirks for this printer. */ /* Lookup quirks for this printer. */
...@@ -894,12 +886,12 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -894,12 +886,12 @@ static int usblp_probe(struct usb_interface *intf,
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
dev->descriptor.idVendor, dev->descriptor.idVendor,
dev->descriptor.idProduct); dev->descriptor.idProduct);
goto abort_minor; goto abort;
} }
/* Setup the selected alternate setting and endpoints. */ /* Setup the selected alternate setting and endpoints. */
if (usblp_set_protocol(usblp, protocol) < 0) if (usblp_set_protocol(usblp, protocol) < 0)
goto abort_minor; goto abort;
/* Retrieve and store the device ID string. */ /* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp); usblp_cache_device_id_string(usblp);
...@@ -920,10 +912,17 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -920,10 +912,17 @@ static int usblp_probe(struct usb_interface *intf,
usblp->present = 1; usblp->present = 1;
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
err("Not able to get a minor for this device.");
goto abort_intfdata;
}
usblp->minor = intf->minor;
return 0; return 0;
abort_minor: abort_intfdata:
usb_deregister_dev(intf, &usblp_class); usb_set_intfdata (intf, NULL);
abort: abort:
if (usblp) { if (usblp) {
if (usblp->writebuf) if (usblp->writebuf)
......
...@@ -81,7 +81,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -81,7 +81,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
if (!dev->irq) { if (!dev->irq) {
err ("Found HC with no IRQ. Check BIOS/PCI %s setup!", err ("Found HC with no IRQ. Check BIOS/PCI %s setup!",
dev->slot_name); pci_name(dev));
return -ENODEV; return -ENODEV;
} }
...@@ -99,7 +99,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -99,7 +99,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
retval = -EFAULT; retval = -EFAULT;
clean_1: clean_1:
release_mem_region (resource, len); release_mem_region (resource, len);
err ("init %s fail, %d", dev->slot_name, retval); err ("init %s fail, %d", pci_name(dev), retval);
return retval; return retval;
} }
...@@ -136,7 +136,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -136,7 +136,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
goto clean_1; goto clean_1;
} else { } else {
release_region (resource, len); release_region (resource, len);
err ("init %s fail, %d", dev->slot_name, retval); err ("init %s fail, %d", pci_name(dev), retval);
return retval; return retval;
} }
} }
...@@ -144,7 +144,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -144,7 +144,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
hcd->driver = driver; hcd->driver = driver;
hcd->description = driver->description; hcd->description = driver->description;
hcd->pdev = dev; hcd->pdev = dev;
hcd->self.bus_name = dev->slot_name; hcd->self.bus_name = pci_name(dev);
hcd->product_desc = dev->dev.name; hcd->product_desc = dev->dev.name;
hcd->self.controller = &dev->dev; hcd->self.controller = &dev->dev;
hcd->controller = hcd->self.controller; hcd->controller = hcd->self.controller;
...@@ -279,6 +279,7 @@ EXPORT_SYMBOL (usb_hcd_pci_remove); ...@@ -279,6 +279,7 @@ EXPORT_SYMBOL (usb_hcd_pci_remove);
/** /**
* usb_hcd_pci_suspend - power management suspend of a PCI-based HCD * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
* @dev: USB Host Controller being suspended * @dev: USB Host Controller being suspended
* @state: state that the controller is going into
* *
* Store this function in the HCD's struct pci_driver as suspend(). * Store this function in the HCD's struct pci_driver as suspend().
*/ */
......
...@@ -1293,7 +1293,8 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) ...@@ -1293,7 +1293,8 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
} }
/* then kill any current requests */ /* then kill any current requests */
spin_lock_irqsave (&hcd_data_lock, flags); local_irq_save (flags);
spin_lock (&hcd_data_lock);
list_for_each_entry (urb, &dev->urb_list, urb_list) { list_for_each_entry (urb, &dev->urb_list, urb_list) {
int tmp = urb->pipe; int tmp = urb->pipe;
...@@ -1311,13 +1312,13 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) ...@@ -1311,13 +1312,13 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
if (urb->status != -EINPROGRESS) if (urb->status != -EINPROGRESS)
continue; continue;
usb_get_urb (urb); usb_get_urb (urb);
spin_unlock_irqrestore (&hcd_data_lock, flags); spin_unlock (&hcd_data_lock);
spin_lock_irqsave (&urb->lock, flags); spin_lock (&urb->lock);
tmp = urb->status; tmp = urb->status;
if (tmp == -EINPROGRESS) if (tmp == -EINPROGRESS)
urb->status = -ESHUTDOWN; urb->status = -ESHUTDOWN;
spin_unlock_irqrestore (&urb->lock, flags); spin_unlock (&urb->lock);
/* kick hcd unless it's already returning this */ /* kick hcd unless it's already returning this */
if (tmp == -EINPROGRESS) { if (tmp == -EINPROGRESS) {
...@@ -1340,7 +1341,8 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) ...@@ -1340,7 +1341,8 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
/* list contents may have changed */ /* list contents may have changed */
goto rescan; goto rescan;
} }
spin_unlock_irqrestore (&hcd_data_lock, flags); spin_unlock (&hcd_data_lock);
local_irq_restore (flags);
/* synchronize with the hardware, so old configuration state /* synchronize with the hardware, so old configuration state
* clears out immediately (and will be freed). * clears out immediately (and will be freed).
......
...@@ -80,6 +80,23 @@ static struct device_driver usb_generic_driver = { ...@@ -80,6 +80,23 @@ static struct device_driver usb_generic_driver = {
static int usb_generic_driver_data; static int usb_generic_driver_data;
/* deallocate hcd/hardware state ... and nuke all pending urbs */
static void nuke_urbs(struct usb_device *dev)
{
void (*disable)(struct usb_device *, int);
int i;
if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->disable)
return;
dbg("nuking urbs assigned to %s", dev->dev.bus_id);
disable = dev->bus->op->disable;
for (i = 0; i < 15; i++) {
disable(dev, i);
disable(dev, USB_DIR_IN | i);
}
}
/* needs to be called with BKL held */ /* needs to be called with BKL held */
int usb_device_probe(struct device *dev) int usb_device_probe(struct device *dev)
{ {
...@@ -116,6 +133,9 @@ int usb_device_remove(struct device *dev) ...@@ -116,6 +133,9 @@ int usb_device_remove(struct device *dev)
down(&driver->serialize); down(&driver->serialize);
/* release all urbs for this device */
nuke_urbs(interface_to_usbdev(intf));
if (intf->driver && intf->driver->disconnect) if (intf->driver && intf->driver->disconnect)
intf->driver->disconnect(intf); intf->driver->disconnect(intf);
...@@ -896,6 +916,9 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -896,6 +916,9 @@ void usb_disconnect(struct usb_device **pdev)
usb_disconnect(child); usb_disconnect(child);
} }
/* deallocate hcd/hardware state ... and nuke all pending urbs */
nuke_urbs(dev);
/* disconnect() drivers from interfaces (a key side effect) */ /* disconnect() drivers from interfaces (a key side effect) */
dev_dbg (&dev->dev, "unregistering interfaces\n"); dev_dbg (&dev->dev, "unregistering interfaces\n");
if (dev->actconfig) { if (dev->actconfig) {
...@@ -908,16 +931,6 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -908,16 +931,6 @@ void usb_disconnect(struct usb_device **pdev)
} }
} }
/* deallocate hcd/hardware state */
if (ops->disable) {
void (*disable)(struct usb_device *, int) = ops->disable;
for (i = 0; i < 15; i++) {
disable (dev, i);
disable (dev, USB_DIR_IN | i);
}
}
dev_dbg (&dev->dev, "unregistering device\n"); dev_dbg (&dev->dev, "unregistering device\n");
/* Free the device number and remove the /proc/bus/usb entry */ /* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) { if (dev->devnum > 0) {
......
/* /*
* ether.c -- CDC 1.1 Ethernet gadget driver * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
* *
* Copyright (C) 2003 David Brownell * Copyright (C) 2003 David Brownell
* *
...@@ -58,21 +58,23 @@ ...@@ -58,21 +58,23 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
* "Communications Device Class" (CDC) Ethernet class driver * Ethernet gadget driver -- with CDC and non-CDC options
* *
* CDC Ethernet is the standard USB solution for sending Ethernet frames * CDC Ethernet is the standard USB solution for sending Ethernet frames
* using USB. Real hardware tends to use the same framing protocol but look * using USB. Real hardware tends to use the same framing protocol but look
* different for control features. And Microsoft pushes their own approach * different for control features. And Microsoft pushes their own approach
* (RNDIS) instead of the standard. * (RNDIS) instead of the standard.
*
* There's some hardware that can't talk CDC. We make that hardware
* implement a "minimalist" vendor-agnostic CDC core: same framing, but
* link-level setup only requires activating the configuration.
*/ */
#define DRIVER_DESC "CDC Ethernet Gadget" #define DRIVER_DESC "Ethernet Gadget"
#define DRIVER_VERSION "29 April 2003" #define DRIVER_VERSION "Bastille Day 2003"
static const char shortname [] = "ether"; static const char shortname [] = "ether";
static const char driver_desc [] = DRIVER_DESC; static const char driver_desc [] = DRIVER_DESC;
static const char control_name [] = "Communications Control";
static const char data_name [] = "CDC Ethernet Data";
#define MIN_PACKET sizeof(struct ethhdr) #define MIN_PACKET sizeof(struct ethhdr)
#define MAX_PACKET ETH_DATA_LEN /* biggest packet we'll rx/tx */ #define MAX_PACKET ETH_DATA_LEN /* biggest packet we'll rx/tx */
...@@ -92,8 +94,7 @@ struct eth_dev { ...@@ -92,8 +94,7 @@ struct eth_dev {
const struct usb_endpoint_descriptor const struct usb_endpoint_descriptor
*in, *out, *status; *in, *out, *status;
struct semaphore mutex; struct net_device *net;
struct net_device net;
struct net_device_stats stats; struct net_device_stats stats;
atomic_t tx_qlen; atomic_t tx_qlen;
...@@ -112,7 +113,7 @@ struct eth_dev { ...@@ -112,7 +113,7 @@ struct eth_dev {
static unsigned qmult = 4; static unsigned qmult = 4;
#define HS_FACTOR 15 #define HS_FACTOR 5
#define qlen(gadget) \ #define qlen(gadget) \
(qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1)) (qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1))
...@@ -128,7 +129,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); ...@@ -128,7 +129,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
/* Thanks to NetChip Technologies for donating this product ID. /* Thanks to NetChip Technologies for donating this product ID.
* *
* DO NOT REUSE THESE IDs with any other driver!! Ever!! * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures. * Instead: allocate your own, using normal USB-IF procedures.
*/ */
#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
...@@ -158,6 +159,11 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); ...@@ -158,6 +159,11 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
* for some reason doesn't handle full speed bulk maxpacket of 64. * for some reason doesn't handle full speed bulk maxpacket of 64.
*/ */
#define DEV_CONFIG_VALUE 3 /* some hardware cares */
/* #undef on hardware that can't implement CDC */
#define DEV_CONFIG_CDC
/* /*
* NetChip 2280, PCI based. * NetChip 2280, PCI based.
* *
...@@ -172,7 +178,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); ...@@ -172,7 +178,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
#define DRIVER_VERSION_NUM 0x0101 #define DRIVER_VERSION_NUM 0x0101
#define EP0_MAXPACKET 64 #define EP0_MAXPACKET 64
static const char EP_OUT_NAME [] = "ep-a"; static const char EP_OUT_NAME [] = "ep-a";
#define EP_OUT_NUM 2 #define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep-b"; static const char EP_IN_NAME [] = "ep-b";
#define EP_IN_NUM 2 #define EP_IN_NUM 2
static const char EP_STATUS_NAME [] = "ep-f"; static const char EP_STATUS_NAME [] = "ep-f";
...@@ -194,22 +200,21 @@ static inline void hw_optimize (struct usb_gadget *gadget) ...@@ -194,22 +200,21 @@ static inline void hw_optimize (struct usb_gadget *gadget)
#endif #endif
/* /*
* PXA-250 UDC: widely used in second gen Linux-capable PDAs. * PXA-2xx UDC: widely used in second gen Linux-capable ARM PDAs
* and other products.
* *
* no limitations except from set_interface: docs say "no" to a third * multiple interfaces (or altsettings) aren't usable. so this hardware
* interface. and the interrupt-only endpoints don't toggle, so we'll * can't implement CDC, which needs both capabilities.
* just use a bulk-capable one instead.
*/ */
#ifdef CONFIG_USB_ETH_PXA250 #ifdef CONFIG_USB_ETH_PXA2XX
#define CHIP "pxa250" #undef DEV_CONFIG_CDC
#define CHIP "pxa2xx"
#define DRIVER_VERSION_NUM 0x0103 #define DRIVER_VERSION_NUM 0x0103
#define EP0_MAXPACKET 16 #define EP0_MAXPACKET 16
static const char EP_OUT_NAME [] = "ep12out-bulk"; static const char EP_OUT_NAME [] = "ep2out-bulk";
#define EP_OUT_NUM 12 #define EP_OUT_NUM 2
static const char EP_IN_NAME [] = "ep11in-bulk"; static const char EP_IN_NAME [] = "ep1in-bulk";
#define EP_IN_NUM 11 #define EP_IN_NUM 1
static const char EP_STATUS_NAME [] = "ep6in-bulk";
#define EP_STATUS_NUM 6
/* doesn't support bus-powered operation */ /* doesn't support bus-powered operation */
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER #define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* supports remote wakeup, but this driver doesn't */ /* supports remote wakeup, but this driver doesn't */
...@@ -247,6 +252,29 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -247,6 +252,29 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
# error Configure some USB peripheral controller driver! # error Configure some USB peripheral controller driver!
#endif #endif
/* We normally expect hardware that can talk CDC. That involves
* using multiple interfaces and altsettings, and maybe a status
* interrupt. Driver binding to be done according to USB-IF class,
* though you can use different VENDOR and PRODUCT numbers if you
* want (and they're officially assigned).
*
* For hardware that can't talk CDC, we use the same vendor ID that
* ARM Linux has used for ethernet-over-usb, both with sa1100 and
* with pxa250. We're protocol-compatible, if the host-side drivers
* use the endpoint descriptors. DRIVER_VERSION_NUM is nonzero, so
* drivers that need to hard-wire endpoint numbers have a hook.
*/
#ifdef DEV_CONFIG_CDC
#define DEV_CONFIG_CLASS USB_CLASS_COMM
#else
#define DEV_CONFIG_CLASS USB_CLASS_VENDOR_SPEC
#undef EP_STATUS_NUM
#undef DRIVER_VENDOR_NUM
#undef DRIVER_PRODUCT_NUM
#define DRIVER_VENDOR_NUM 0x049f
#define DRIVER_PRODUCT_NUM 0x505a
#endif /* CONFIG_CDC_ETHER */
/* power usage is config specific. /* power usage is config specific.
* hardware that supports remote wakeup defaults to disabling it. * hardware that supports remote wakeup defaults to disabling it.
*/ */
...@@ -274,7 +302,8 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -274,7 +302,8 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define xprintk(d,level,fmt,args...) \ #define xprintk(d,level,fmt,args...) \
dev_printk(level , &(d)->gadget->dev , fmt , ## args) printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \
## args)
#ifdef DEBUG #ifdef DEBUG
#undef DEBUG #undef DEBUG
...@@ -309,7 +338,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -309,7 +338,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
/* /*
* DESCRIPTORS ... most are static, but strings and (full) configuration * DESCRIPTORS ... most are static, but strings and (full) configuration
* descriptors are built on demand. Notice how most of the cdc descriptors * descriptors are built on demand. Notice how most of the cdc descriptors
* add no value to simple (typical) configurations. * aren't needed in the "minimalist" mode.
*/ */
#define STRING_MANUFACTURER 1 #define STRING_MANUFACTURER 1
...@@ -323,15 +352,14 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -323,15 +352,14 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
/* /*
* This device advertises one configuration. * This device advertises one configuration.
*/ */
#define CONFIG_CDC_ETHER 3
static const struct usb_device_descriptor static const struct usb_device_descriptor
device_desc = { device_desc = {
.bLength = sizeof device_desc, .bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE, .bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16 (0x0200), .bcdUSB = __constant_cpu_to_le16 (0x0200),
.bDeviceClass = USB_CLASS_COMM,
.bDeviceClass = DEV_CONFIG_CLASS,
.bDeviceSubClass = 0, .bDeviceSubClass = 0,
.bDeviceProtocol = 0, .bDeviceProtocol = 0,
.bMaxPacketSize0 = EP0_MAXPACKET, .bMaxPacketSize0 = EP0_MAXPACKET,
...@@ -350,13 +378,26 @@ eth_config = { ...@@ -350,13 +378,26 @@ eth_config = {
.bDescriptorType = USB_DT_CONFIG, .bDescriptorType = USB_DT_CONFIG,
/* compute wTotalLength on the fly */ /* compute wTotalLength on the fly */
#ifdef DEV_CONFIG_CDC
.bNumInterfaces = 2, .bNumInterfaces = 2,
.bConfigurationValue = CONFIG_CDC_ETHER, #else
.bNumInterfaces = 1,
#endif
.bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = STRING_PRODUCT, .iConfiguration = STRING_PRODUCT,
.bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
.bMaxPower = (MAX_USB_POWER + 1) / 2, .bMaxPower = (MAX_USB_POWER + 1) / 2,
}; };
#ifdef DEV_CONFIG_CDC
/*
* Compared to the "minimalist" non-CDC model, the CDC model adds
* three class descriptors, two interface descrioptors, and a status
* endpoint. Both have a "data" interface and two bulk endpoints.
* There are also differences in how control requests are handled.
*/
/* master comm interface optionally has a status notification endpoint */ /* master comm interface optionally has a status notification endpoint */
static const struct usb_interface_descriptor static const struct usb_interface_descriptor
...@@ -446,7 +487,7 @@ static const struct ether_desc ether_desc = { ...@@ -446,7 +487,7 @@ static const struct ether_desc ether_desc = {
* some drivers (like current Linux cdc-ether!) "need" it to exist even * some drivers (like current Linux cdc-ether!) "need" it to exist even
* if they ignore the connect/disconnect notifications that real aether * if they ignore the connect/disconnect notifications that real aether
* can provide. more advanced cdc configurations might want to support * can provide. more advanced cdc configurations might want to support
* encapsulated commands. * encapsulated commands (vendor-specific, using control-OUT).
*/ */
#define LOG2_STATUS_INTERVAL_MSEC 6 #define LOG2_STATUS_INTERVAL_MSEC 6
...@@ -494,6 +535,29 @@ data_intf = { ...@@ -494,6 +535,29 @@ data_intf = {
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.iInterface = STRING_DATA, .iInterface = STRING_DATA,
}; };
#else
/*
* "Minimalist" non-CDC option is a simple vendor-neutral model that most
* full speed controllers can handle: one interface, two bulk endpoints.
*/
static const struct usb_interface_descriptor
data_intf = {
.bLength = sizeof data_intf,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = STRING_DATA,
};
#endif /* DEV_CONFIG_CDC */
static const struct usb_endpoint_descriptor static const struct usb_endpoint_descriptor
fs_source_desc = { fs_source_desc = {
...@@ -563,12 +627,12 @@ dev_qualifier = { ...@@ -563,12 +627,12 @@ dev_qualifier = {
.bDescriptorType = USB_DT_DEVICE_QUALIFIER, .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = __constant_cpu_to_le16 (0x0200), .bcdUSB = __constant_cpu_to_le16 (0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC, .bDeviceClass = DEV_CONFIG_CLASS,
/* assumes ep0 uses the same value for both speeds ... */ /* assumes ep0 uses the same value for both speeds ... */
.bMaxPacketSize0 = EP0_MAXPACKET, .bMaxPacketSize0 = EP0_MAXPACKET,
.bNumConfigurations = 2, .bNumConfigurations = 1,
}; };
/* maxpacket and other transfer characteristics vary by speed. */ /* maxpacket and other transfer characteristics vary by speed. */
...@@ -581,16 +645,24 @@ dev_qualifier = { ...@@ -581,16 +645,24 @@ dev_qualifier = {
#endif /* !HIGHSPEED */ #endif /* !HIGHSPEED */
/*-------------------------------------------------------------------------*/
/* descriptors that are built on-demand */
#ifdef DEV_CONFIG_CDC
/* address that the host will use ... usually assigned at random */ /* address that the host will use ... usually assigned at random */
static char ethaddr [2 * ETH_ALEN + 1]; static char ethaddr [2 * ETH_ALEN + 1];
#endif
/* static strings, in iso 8859/1 */ /* static strings, in iso 8859/1 */
static struct usb_string strings [] = { static struct usb_string strings [] = {
{ STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE "/" CHIP, }, { STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE "/" CHIP, },
{ STRING_PRODUCT, driver_desc, }, { STRING_PRODUCT, driver_desc, },
#ifdef DEV_CONFIG_CDC
{ STRING_ETHADDR, ethaddr, }, { STRING_ETHADDR, ethaddr, },
{ STRING_CONTROL, control_name, }, { STRING_CONTROL, "CDC Communications Control", },
{ STRING_DATA, data_name, }, #endif
{ STRING_DATA, "Ethernet Data", },
{ } /* end of list */ { } /* end of list */
}; };
...@@ -607,14 +679,18 @@ static int ...@@ -607,14 +679,18 @@ static int
config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
{ {
const unsigned config_len = USB_DT_CONFIG_SIZE const unsigned config_len = USB_DT_CONFIG_SIZE
+ 3 * USB_DT_INTERFACE_SIZE #ifdef DEV_CONFIG_CDC
+ 2 * USB_DT_INTERFACE_SIZE
+ sizeof header_desc + sizeof header_desc
+ sizeof union_desc + sizeof union_desc
+ sizeof ether_desc + sizeof ether_desc
#ifdef EP_STATUS_NUM #ifdef EP_STATUS_NUM
+ USB_DT_ENDPOINT_SIZE + USB_DT_ENDPOINT_SIZE
#endif #endif
#endif /* DEV_CONFIG_CDC */
+ USB_DT_INTERFACE_SIZE
+ 2 * USB_DT_ENDPOINT_SIZE; + 2 * USB_DT_ENDPOINT_SIZE;
#ifdef HIGHSPEED #ifdef HIGHSPEED
int hs; int hs;
#endif #endif
...@@ -636,6 +712,7 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) ...@@ -636,6 +712,7 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
hs = !hs; hs = !hs;
#endif #endif
#ifdef DEV_CONFIG_CDC
/* control interface, class descriptors, optional status endpoint */ /* control interface, class descriptors, optional status endpoint */
memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE); memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
buf += USB_DT_INTERFACE_SIZE; buf += USB_DT_INTERFACE_SIZE;
...@@ -660,6 +737,7 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) ...@@ -660,6 +737,7 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
/* default data altsetting has no endpoints */ /* default data altsetting has no endpoints */
memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE); memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
buf += USB_DT_INTERFACE_SIZE; buf += USB_DT_INTERFACE_SIZE;
#endif /* DEV_CONFIG_CDC */
/* the "real" data interface has two endpoints */ /* the "real" data interface has two endpoints */
memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE); memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
...@@ -684,6 +762,8 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) ...@@ -684,6 +762,8 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void eth_start (struct eth_dev *dev, int gfp_flags);
static int static int
set_ether_config (struct eth_dev *dev, int gfp_flags) set_ether_config (struct eth_dev *dev, int gfp_flags)
{ {
...@@ -694,7 +774,8 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) ...@@ -694,7 +774,8 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
gadget_for_each_ep (ep, gadget) { gadget_for_each_ep (ep, gadget) {
const struct usb_endpoint_descriptor *d; const struct usb_endpoint_descriptor *d;
/* NOTE: the host isn't allowed to use these two data #ifdef DEV_CONFIG_CDC
/* With CDC, the host isn't allowed to use these two data
* endpoints in the default altsetting for the interface. * endpoints in the default altsetting for the interface.
* so we don't activate them yet. * so we don't activate them yet.
*/ */
...@@ -714,10 +795,11 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) ...@@ -714,10 +795,11 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
dev->out_ep = ep; dev->out_ep = ep;
dev->out = d; dev->out = d;
continue; continue;
}
#ifdef EP_STATUS_NUM #ifdef EP_STATUS_NUM
/* optional status/notification endpoint */ /* optional status/notification endpoint */
} else if (strcmp (ep->name, EP_STATUS_NAME) == 0) { else if (strcmp (ep->name, EP_STATUS_NAME) == 0) {
d = ep_desc (gadget, &hs_status_desc, &fs_status_desc); d = ep_desc (gadget, &hs_status_desc, &fs_status_desc);
result = usb_ep_enable (ep, d); result = usb_ep_enable (ep, d);
if (result == 0) { if (result == 0) {
...@@ -726,16 +808,57 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) ...@@ -726,16 +808,57 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
dev->status = d; dev->status = d;
continue; continue;
} }
}
#endif #endif
#else /* !CONFIG_CDC_ETHER */
/* non-CDC is simpler: if the device is there,
* it's live with rx and tx endpoints.
*/
/* one endpoint writes data back IN to the host */
if (strcmp (ep->name, EP_IN_NAME) == 0) {
d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
result = usb_ep_enable (ep, d);
if (result == 0) {
ep->driver_data = dev;
dev->in_ep = ep;
dev->in = d;
continue;
}
/* one endpoint just reads OUT packets */
} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
result = usb_ep_enable (ep, d);
if (result == 0) {
ep->driver_data = dev;
dev->out_ep = ep;
dev->out = d;
continue;
}
}
#endif /* !CONFIG_CDC_ETHER */
/* ignore any other endpoints */ /* ignore any other endpoints */
} else else
continue; continue;
/* stop on error */ /* stop on error */
ERROR (dev, "can't enable %s, result %d\n", ep->name, result); ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
break; break;
} }
if (!result && (!dev->in_ep || !dev->out_ep))
result = -ENODEV;
#ifndef DEV_CONFIG_CDC
if (result == 0) {
netif_carrier_on (dev->net);
if (netif_running (dev->net))
eth_start (dev, GFP_ATOMIC);
}
#endif /* !CONFIG_CDC_ETHER */
if (result == 0) if (result == 0)
DEBUG (dev, "qlen %d\n", qlen (gadget)); DEBUG (dev, "qlen %d\n", qlen (gadget));
...@@ -751,8 +874,8 @@ static void eth_reset_config (struct eth_dev *dev) ...@@ -751,8 +874,8 @@ static void eth_reset_config (struct eth_dev *dev)
DEBUG (dev, "%s\n", __FUNCTION__); DEBUG (dev, "%s\n", __FUNCTION__);
netif_stop_queue (&dev->net); netif_stop_queue (dev->net);
netif_carrier_off (&dev->net); netif_carrier_off (dev->net);
/* just disable endpoints, forcing completion of pending i/o. /* just disable endpoints, forcing completion of pending i/o.
* all our completion handlers free their requests in this case. * all our completion handlers free their requests in this case.
...@@ -797,7 +920,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) ...@@ -797,7 +920,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
hw_optimize (gadget); hw_optimize (gadget);
switch (number) { switch (number) {
case CONFIG_CDC_ETHER: case DEV_CONFIG_VALUE:
result = set_ether_config (dev, gfp_flags); result = set_ether_config (dev, gfp_flags);
break; break;
default: default:
...@@ -807,8 +930,6 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) ...@@ -807,8 +930,6 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
return result; return result;
} }
if (!result && (!dev->in_ep || !dev->out_ep))
result = -ENODEV;
if (result) if (result)
eth_reset_config (dev); eth_reset_config (dev);
else { else {
...@@ -896,6 +1017,7 @@ static void issue_start_status (struct eth_dev *dev) ...@@ -896,6 +1017,7 @@ static void issue_start_status (struct eth_dev *dev)
* FIXME ugly idiom, maybe we'd be better with just * FIXME ugly idiom, maybe we'd be better with just
* a "cancel the whole queue" primitive since any * a "cancel the whole queue" primitive since any
* unlink-one primitive has way too many error modes. * unlink-one primitive has way too many error modes.
* here, we "know" toggle is already clear...
*/ */
usb_ep_disable (dev->status_ep); usb_ep_disable (dev->status_ep);
usb_ep_enable (dev->status_ep, dev->status); usb_ep_enable (dev->status_ep, dev->status);
...@@ -953,8 +1075,6 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -953,8 +1075,6 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
*/ */
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */ #define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */
static void eth_start (struct eth_dev *dev, int gfp_flags);
/* /*
* The setup() callback implements all the ep0 functionality that's not * The setup() callback implements all the ep0 functionality that's not
* handled lower down. CDC has a number of less-common features: * handled lower down. CDC has a number of less-common features:
...@@ -1018,6 +1138,17 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1018,6 +1138,17 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC); value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
spin_unlock (&dev->lock); spin_unlock (&dev->lock);
break; break;
#ifdef CONFIG_USB_ETH_PXA2XX
/* PXA UDC prevents us from using SET_INTERFACE in normal ways.
* And it hides GET_CONFIGURATION and GET_INTERFACE too.
*/
case USB_REQ_SET_INTERFACE:
spin_lock (&dev->lock);
value = eth_set_config (dev, DEV_CONFIG_VALUE, GFP_ATOMIC);
spin_unlock (&dev->lock);
break;
#else /* hardware that that stays out of our way */
case USB_REQ_GET_CONFIGURATION: case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN) if (ctrl->bRequestType != USB_DIR_IN)
break; break;
...@@ -1056,15 +1187,15 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1056,15 +1187,15 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->wValue == 1) { if (ctrl->wValue == 1) {
usb_ep_enable (dev->in_ep, dev->in); usb_ep_enable (dev->in_ep, dev->in);
usb_ep_enable (dev->out_ep, dev->out); usb_ep_enable (dev->out_ep, dev->out);
netif_carrier_on (&dev->net); netif_carrier_on (dev->net);
#ifdef EP_STATUS_NUM #ifdef EP_STATUS_NUM
issue_start_status (dev); issue_start_status (dev);
#endif #endif
if (netif_running (&dev->net)) if (netif_running (dev->net))
eth_start (dev, GFP_ATOMIC); eth_start (dev, GFP_ATOMIC);
} else { } else {
netif_stop_queue (&dev->net); netif_stop_queue (dev->net);
netif_carrier_off (&dev->net); netif_carrier_off (dev->net);
} }
value = 0; value = 0;
break; break;
...@@ -1079,12 +1210,14 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1079,12 +1210,14 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* if carrier is on, data interface is active. */ /* if carrier is on, data interface is active. */
*(u8 *)req->buf = *(u8 *)req->buf =
((ctrl->wIndex == 1) && netif_carrier_ok (&dev->net)) ((ctrl->wIndex == 1) && netif_carrier_ok (dev->net))
? 1 ? 1
: 0, : 0,
value = min (ctrl->wLength, (u16) 1); value = min (ctrl->wLength, (u16) 1);
break; break;
#endif
#ifdef DEV_CONFIG_CDC
case CDC_SET_ETHERNET_PACKET_FILTER: case CDC_SET_ETHERNET_PACKET_FILTER:
/* see 6.2.30: no data, wIndex = interface, /* see 6.2.30: no data, wIndex = interface,
* wValue = packet filter bitmap * wValue = packet filter bitmap
...@@ -1099,6 +1232,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1099,6 +1232,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*/ */
value = 0; value = 0;
break; break;
#endif /* DEV_CONFIG_CDC */
default: default:
VDEBUG (dev, VDEBUG (dev,
...@@ -1129,8 +1263,8 @@ eth_disconnect (struct usb_gadget *gadget) ...@@ -1129,8 +1263,8 @@ eth_disconnect (struct usb_gadget *gadget)
unsigned long flags; unsigned long flags;
spin_lock_irqsave (&dev->lock, flags); spin_lock_irqsave (&dev->lock, flags);
netif_stop_queue (&dev->net); netif_stop_queue (dev->net);
netif_carrier_off (&dev->net); netif_carrier_off (dev->net);
eth_reset_config (dev); eth_reset_config (dev);
spin_unlock_irqrestore (&dev->lock, flags); spin_unlock_irqrestore (&dev->lock, flags);
...@@ -1175,10 +1309,10 @@ static int eth_ethtool_ioctl (struct net_device *net, void *useraddr) ...@@ -1175,10 +1309,10 @@ static int eth_ethtool_ioctl (struct net_device *net, void *useraddr)
memset (&info, 0, sizeof info); memset (&info, 0, sizeof info);
info.cmd = ETHTOOL_GDRVINFO; info.cmd = ETHTOOL_GDRVINFO;
strncpy (info.driver, shortname, sizeof info.driver); strlcpy (info.driver, shortname, sizeof info.driver);
strncpy (info.version, DRIVER_VERSION, sizeof info.version); strlcpy (info.version, DRIVER_VERSION, sizeof info.version);
strncpy (info.fw_version, CHIP, sizeof info.fw_version); strlcpy (info.fw_version, CHIP, sizeof info.fw_version);
strncpy (info.bus_info, dev->gadget->dev.bus_id, strlcpy (info.bus_info, dev->gadget->dev.bus_id,
sizeof info.bus_info); sizeof info.bus_info);
if (copy_to_user (useraddr, &info, sizeof (info))) if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT; return -EFAULT;
...@@ -1227,7 +1361,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags) ...@@ -1227,7 +1361,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
int retval = 0; int retval = 0;
size_t size; size_t size;
size = (sizeof (struct ethhdr) + dev->net.mtu + RX_EXTRA); size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
if ((skb = alloc_skb (size, gfp_flags)) == 0) { if ((skb = alloc_skb (size, gfp_flags)) == 0) {
DEBUG (dev, "no rx skb\n"); DEBUG (dev, "no rx skb\n");
...@@ -1241,16 +1375,9 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags) ...@@ -1241,16 +1375,9 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
req->complete = rx_complete; req->complete = rx_complete;
req->context = skb; req->context = skb;
if (netif_running (&dev->net)) { retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
retval = usb_ep_queue (dev->out_ep, req, gfp_flags); if (retval == -ENOMEM)
if (retval == -ENOMEM) defer_kevent (dev, WORK_RX_MEMORY);
defer_kevent (dev, WORK_RX_MEMORY);
if (retval)
DEBUG (dev, "%s %d\n", __FUNCTION__, retval);
} else {
DEBUG (dev, "%s stopped\n", __FUNCTION__);
retval = -ENOLINK;
}
if (retval) { if (retval) {
DEBUG (dev, "rx submit --> %d\n", retval); DEBUG (dev, "rx submit --> %d\n", retval);
dev_kfree_skb_any (skb); dev_kfree_skb_any (skb);
...@@ -1278,8 +1405,8 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -1278,8 +1405,8 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
break; break;
} }
skb->dev = &dev->net; skb->dev = dev->net;
skb->protocol = eth_type_trans (skb, &dev->net); skb->protocol = eth_type_trans (skb, dev->net);
dev->stats.rx_packets++; dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len; dev->stats.rx_bytes += skb->len;
...@@ -1294,9 +1421,7 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -1294,9 +1421,7 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
case -ECONNRESET: // unlink case -ECONNRESET: // unlink
case -ESHUTDOWN: // disconnect etc case -ESHUTDOWN: // disconnect etc
VDEBUG (dev, "rx shutdown, code %d\n", status); VDEBUG (dev, "rx shutdown, code %d\n", status);
usb_ep_free_request (dev->out_ep, req); goto clean;
req = 0;
break;
/* data overrun */ /* data overrun */
case -EOVERFLOW: case -EOVERFLOW:
...@@ -1311,7 +1436,11 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -1311,7 +1436,11 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
if (skb) if (skb)
dev_kfree_skb_any (skb); dev_kfree_skb_any (skb);
if (!netif_running (dev->net)) {
clean:
usb_ep_free_request (dev->out_ep, req);
req = 0;
}
if (req) if (req)
rx_submit (dev, req, GFP_ATOMIC); rx_submit (dev, req, GFP_ATOMIC);
} }
...@@ -1323,7 +1452,7 @@ static void eth_work (void *_dev) ...@@ -1323,7 +1452,7 @@ static void eth_work (void *_dev)
if (test_bit (WORK_RX_MEMORY, &dev->todo)) { if (test_bit (WORK_RX_MEMORY, &dev->todo)) {
struct usb_request *req = 0; struct usb_request *req = 0;
if (netif_running (&dev->net)) if (netif_running (dev->net))
req = usb_ep_alloc_request (dev->in_ep, GFP_KERNEL); req = usb_ep_alloc_request (dev->in_ep, GFP_KERNEL);
else else
clear_bit (WORK_RX_MEMORY, &dev->todo); clear_bit (WORK_RX_MEMORY, &dev->todo);
...@@ -1342,18 +1471,25 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -1342,18 +1471,25 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
struct sk_buff *skb = req->context; struct sk_buff *skb = req->context;
struct eth_dev *dev = ep->driver_data; struct eth_dev *dev = ep->driver_data;
if (req->status) switch (req->status) {
default:
dev->stats.tx_errors++; dev->stats.tx_errors++;
else VDEBUG (dev, "tx err %d\n", req->status);
/* FALLTHROUGH */
case -ECONNRESET: // unlink
case -ESHUTDOWN: // disconnect etc
break;
case 0:
dev->stats.tx_bytes += skb->len; dev->stats.tx_bytes += skb->len;
}
dev->stats.tx_packets++; dev->stats.tx_packets++;
usb_ep_free_request (ep, req); usb_ep_free_request (ep, req);
dev_kfree_skb_any (skb); dev_kfree_skb_any (skb);
atomic_inc (&dev->tx_qlen); atomic_inc (&dev->tx_qlen);
if (netif_carrier_ok (&dev->net)) if (netif_carrier_ok (dev->net))
netif_wake_queue (&dev->net); netif_wake_queue (dev->net);
} }
static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
...@@ -1437,7 +1573,7 @@ static void eth_start (struct eth_dev *dev, int gfp_flags) ...@@ -1437,7 +1573,7 @@ static void eth_start (struct eth_dev *dev, int gfp_flags)
/* and open the tx floodgates */ /* and open the tx floodgates */
atomic_set (&dev->tx_qlen, size); atomic_set (&dev->tx_qlen, size);
netif_wake_queue (&dev->net); netif_wake_queue (dev->net);
} }
static int eth_open (struct net_device *net) static int eth_open (struct net_device *net)
...@@ -1445,10 +1581,8 @@ static int eth_open (struct net_device *net) ...@@ -1445,10 +1581,8 @@ static int eth_open (struct net_device *net)
struct eth_dev *dev = (struct eth_dev *) net->priv; struct eth_dev *dev = (struct eth_dev *) net->priv;
DEBUG (dev, "%s\n", __FUNCTION__); DEBUG (dev, "%s\n", __FUNCTION__);
down (&dev->mutex); if (netif_carrier_ok (dev->net))
if (netif_carrier_ok (&dev->net))
eth_start (dev, GFP_KERNEL); eth_start (dev, GFP_KERNEL);
up (&dev->mutex);
return 0; return 0;
} }
...@@ -1457,7 +1591,6 @@ static int eth_stop (struct net_device *net) ...@@ -1457,7 +1591,6 @@ static int eth_stop (struct net_device *net)
struct eth_dev *dev = (struct eth_dev *) net->priv; struct eth_dev *dev = (struct eth_dev *) net->priv;
DEBUG (dev, "%s\n", __FUNCTION__); DEBUG (dev, "%s\n", __FUNCTION__);
down (&dev->mutex);
netif_stop_queue (net); netif_stop_queue (net);
DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
...@@ -1469,7 +1602,7 @@ static int eth_stop (struct net_device *net) ...@@ -1469,7 +1602,7 @@ static int eth_stop (struct net_device *net)
if (dev->gadget->speed != USB_SPEED_UNKNOWN) { if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
usb_ep_disable (dev->in_ep); usb_ep_disable (dev->in_ep);
usb_ep_disable (dev->out_ep); usb_ep_disable (dev->out_ep);
if (netif_carrier_ok (&dev->net)) { if (netif_carrier_ok (dev->net)) {
DEBUG (dev, "host still using in/out endpoints\n"); DEBUG (dev, "host still using in/out endpoints\n");
usb_ep_enable (dev->in_ep, dev->in); usb_ep_enable (dev->in_ep, dev->in);
usb_ep_enable (dev->out_ep, dev->out); usb_ep_enable (dev->out_ep, dev->out);
...@@ -1480,7 +1613,6 @@ static int eth_stop (struct net_device *net) ...@@ -1480,7 +1613,6 @@ static int eth_stop (struct net_device *net)
#endif #endif
} }
up (&dev->mutex);
return 0; return 0;
} }
...@@ -1492,7 +1624,6 @@ eth_unbind (struct usb_gadget *gadget) ...@@ -1492,7 +1624,6 @@ eth_unbind (struct usb_gadget *gadget)
struct eth_dev *dev = get_gadget_data (gadget); struct eth_dev *dev = get_gadget_data (gadget);
DEBUG (dev, "unbind\n"); DEBUG (dev, "unbind\n");
down (&dev->mutex);
/* we've already been disconnected ... no i/o is active */ /* we've already been disconnected ... no i/o is active */
if (dev->req) { if (dev->req) {
...@@ -1500,15 +1631,13 @@ eth_unbind (struct usb_gadget *gadget) ...@@ -1500,15 +1631,13 @@ eth_unbind (struct usb_gadget *gadget)
dev->req->buf, dev->req->dma, dev->req->buf, dev->req->dma,
USB_BUFSIZ); USB_BUFSIZ);
usb_ep_free_request (gadget->ep0, dev->req); usb_ep_free_request (gadget->ep0, dev->req);
dev->req = 0;
} }
unregister_netdev (&dev->net); unregister_netdev (dev->net);
up (&dev->mutex);
/* assuming we used keventd, it must quiesce too */ /* assuming we used keventd, it must quiesce too */
flush_scheduled_work (); flush_scheduled_work ();
kfree (dev);
set_gadget_data (gadget, 0); set_gadget_data (gadget, 0);
} }
...@@ -1517,22 +1646,24 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1517,22 +1646,24 @@ eth_bind (struct usb_gadget *gadget)
{ {
struct eth_dev *dev; struct eth_dev *dev;
struct net_device *net; struct net_device *net;
int status = -ENOMEM;
#ifdef DEV_CONFIG_CDC
u8 node_id [ETH_ALEN]; u8 node_id [ETH_ALEN];
/* just one upstream link at a time */ /* just one upstream link at a time */
if (ethaddr [0] != 0) if (ethaddr [0] != 0)
return -ENODEV; return -ENODEV;
#endif
dev = kmalloc (sizeof *dev, SLAB_KERNEL); net = alloc_etherdev (sizeof *dev);
if (!dev) if (!net)
return -ENOMEM; return status;
memset (dev, 0, sizeof *dev); dev = net->priv;
spin_lock_init (&dev->lock); spin_lock_init (&dev->lock);
init_MUTEX_LOCKED (&dev->mutex);
INIT_WORK (&dev->work, eth_work, dev); INIT_WORK (&dev->work, eth_work, dev);
/* network device setup */ /* network device setup */
net = &dev->net; dev->net = net;
SET_MODULE_OWNER (net); SET_MODULE_OWNER (net);
net->priv = dev; net->priv = dev;
strcpy (net->name, "usb%d"); strcpy (net->name, "usb%d");
...@@ -1545,6 +1676,7 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1545,6 +1676,7 @@ eth_bind (struct usb_gadget *gadget)
net->dev_addr [0] &= 0xfe; // clear multicast bit net->dev_addr [0] &= 0xfe; // clear multicast bit
net->dev_addr [0] |= 0x02; // set local assignment bit (IEEE802) net->dev_addr [0] |= 0x02; // set local assignment bit (IEEE802)
#ifdef DEV_CONFIG_CDC
/* ... another address for the host, on the other end of the /* ... another address for the host, on the other end of the
* link, gets exported through CDC (see CDC spec table 41) * link, gets exported through CDC (see CDC spec table 41)
*/ */
...@@ -1554,6 +1686,7 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1554,6 +1686,7 @@ eth_bind (struct usb_gadget *gadget)
snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
node_id [0], node_id [1], node_id [2], node_id [0], node_id [1], node_id [2],
node_id [3], node_id [4], node_id [5]); node_id [3], node_id [4], node_id [5]);
#endif
net->change_mtu = eth_change_mtu; net->change_mtu = eth_change_mtu;
net->get_stats = eth_get_stats; net->get_stats = eth_get_stats;
...@@ -1567,36 +1700,38 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1567,36 +1700,38 @@ eth_bind (struct usb_gadget *gadget)
/* preallocate control response and buffer */ /* preallocate control response and buffer */
dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
if (!dev->req) if (!dev->req)
goto enomem; goto fail;
dev->req->complete = eth_setup_complete; dev->req->complete = eth_setup_complete;
dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
&dev->req->dma, GFP_KERNEL); &dev->req->dma, GFP_KERNEL);
if (!dev->req->buf) { if (!dev->req->buf) {
usb_ep_free_request (gadget->ep0, dev->req); usb_ep_free_request (gadget->ep0, dev->req);
goto enomem; goto fail;
} }
/* finish hookup to lower layer ... */ /* finish hookup to lower layer ... */
dev->gadget = gadget; dev->gadget = gadget;
set_gadget_data (gadget, dev); set_gadget_data (gadget, dev);
gadget->ep0->driver_data = dev; gadget->ep0->driver_data = dev;
INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n", driver_desc);
#ifdef DEV_CONFIG_CDC
INFO (dev, "CDC host enet %s\n", ethaddr);
#endif
/* two kinds of host-initiated state changes: /* two kinds of host-initiated state changes:
* - iff DATA transfer is active, carrier is "on" * - iff DATA transfer is active, carrier is "on"
* - tx queueing enabled if open *and* carrier is "on" * - tx queueing enabled if open *and* carrier is "on"
*/ */
INFO (dev, "%s, host enet %s, version: " DRIVER_VERSION "\n", netif_stop_queue (dev->net);
driver_desc, ethaddr); netif_carrier_off (dev->net);
register_netdev (&dev->net);
netif_stop_queue (&dev->net); // SET_NETDEV_DEV (dev->net, &gadget->dev);
netif_carrier_off (&dev->net); status = register_netdev (dev->net);
if (status == 0)
up (&dev->mutex); return status;
return 0; fail:
enomem:
eth_unbind (gadget); eth_unbind (gadget);
return -ENOMEM; return status;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -2496,7 +2496,7 @@ static void net2280_remove (struct pci_dev *pdev) ...@@ -2496,7 +2496,7 @@ static void net2280_remove (struct pci_dev *pdev)
device_remove_file (&pdev->dev, &dev_attr_registers); device_remove_file (&pdev->dev, &dev_attr_registers);
pci_set_drvdata (pdev, 0); pci_set_drvdata (pdev, 0);
INFO (dev, "unbind from pci %s\n", pdev->slot_name); INFO (dev, "unbind from pci %s\n", pci_name(pdev));
kfree (dev); kfree (dev);
the_controller = 0; the_controller = 0;
...@@ -2518,7 +2518,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2518,7 +2518,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
* usb_gadget_driver_{register,unregister}() must change. * usb_gadget_driver_{register,unregister}() must change.
*/ */
if (the_controller) { if (the_controller) {
WARN (the_controller, "ignoring %s\n", pdev->slot_name); WARN (the_controller, "ignoring %s\n", pci_name(pdev));
return -EBUSY; return -EBUSY;
} }
...@@ -2534,7 +2534,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2534,7 +2534,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->pdev = pdev; dev->pdev = pdev;
dev->gadget.ops = &net2280_ops; dev->gadget.ops = &net2280_ops;
strcpy (dev->gadget.dev.bus_id, pdev->slot_name); strcpy (dev->gadget.dev.bus_id, pci_name(pdev));
strcpy (dev->gadget.dev.name, pdev->dev.name); strcpy (dev->gadget.dev.name, pdev->dev.name);
dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
......
...@@ -654,7 +654,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev) ...@@ -654,7 +654,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev)
#define xprintk(dev,level,fmt,args...) \ #define xprintk(dev,level,fmt,args...) \
printk(level "%s %s: " fmt , driver_name , \ printk(level "%s %s: " fmt , driver_name , \
dev->pdev->slot_name , ## args) pci_name(dev->pdev) , ## args)
#ifdef DEBUG #ifdef DEBUG
#undef DEBUG #undef DEBUG
......
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define DRIVER_VERSION "19 Feb 2003" #define DRIVER_VERSION "Bastille Day 2003"
static const char shortname [] = "zero"; static const char shortname [] = "zero";
static const char longname [] = "Gadget Zero"; static const char longname [] = "Gadget Zero";
...@@ -160,18 +160,18 @@ static inline void hw_optimize (struct usb_gadget *gadget) ...@@ -160,18 +160,18 @@ static inline void hw_optimize (struct usb_gadget *gadget)
#endif #endif
/* /*
* PXA-250 UDC: widely used in second gen Linux-capable PDAs. * PXA-2xx UDC: widely used in second gen Linux-capable PDAs.
* *
* This has fifteen fixed-function full speed endpoints, and it * This has fifteen fixed-function full speed endpoints, and it
* can support all USB transfer types. * can support all USB transfer types.
* *
* It only supports three configurations (numbered 1, 2, or 3) * These supports three or four configurations, with fixed numbers.
* with two interfaces each ... there's partial hardware support * The hardware interprets SET_INTERFACE, net effect is that you
* for set_configuration and set_interface, preventing some more * can't use altsettings or reset the interfaces independently.
* interesting config/interface/endpoint arrangements. * So stick to a single interface.
*/ */
#ifdef CONFIG_USB_ZERO_PXA250 #ifdef CONFIG_USB_ZERO_PXA2XX
#define CHIP "pxa250" #define CHIP "pxa2xx"
#define DRIVER_VERSION_NUM 0x0103 #define DRIVER_VERSION_NUM 0x0103
#define EP0_MAXPACKET 16 #define EP0_MAXPACKET 16
static const char EP_OUT_NAME [] = "ep12out-bulk"; static const char EP_OUT_NAME [] = "ep12out-bulk";
...@@ -291,9 +291,12 @@ struct zero_dev { ...@@ -291,9 +291,12 @@ struct zero_dev {
static unsigned buflen = 4096; static unsigned buflen = 4096;
static unsigned qlen = 32; static unsigned qlen = 32;
static unsigned pattern = 0;
module_param (buflen, uint, S_IRUGO|S_IWUSR); module_param (buflen, uint, S_IRUGO|S_IWUSR);
module_param (qlen, uint, S_IRUGO|S_IWUSR); module_param (qlen, uint, S_IRUGO|S_IWUSR);
module_param (pattern, uint, S_IRUGO|S_IWUSR);
/* /*
* Normally the "loopback" configuration is second (index 1) so * Normally the "loopback" configuration is second (index 1) so
...@@ -497,8 +500,8 @@ static struct usb_gadget_strings stringtab = { ...@@ -497,8 +500,8 @@ static struct usb_gadget_strings stringtab = {
/* /*
* config descriptors are also handcrafted. these must agree with code * config descriptors are also handcrafted. these must agree with code
* that sets configurations, and with code managing interface altsettings. * that sets configurations, and with code managing interfaces and their
* other complexity may come from: * altsettings. other complexity may come from:
* *
* - high speed support, including "other speed config" rules * - high speed support, including "other speed config" rules
* - multiple configurations * - multiple configurations
...@@ -506,7 +509,7 @@ static struct usb_gadget_strings stringtab = { ...@@ -506,7 +509,7 @@ static struct usb_gadget_strings stringtab = {
* - embedded class or vendor-specific descriptors * - embedded class or vendor-specific descriptors
* *
* this handles high speed, and has a second config that could as easily * this handles high speed, and has a second config that could as easily
* have been an alternate interface setting. * have been an alternate interface setting (on most hardware).
* *
* NOTE: to demonstrate (and test) more USB capabilities, this driver * NOTE: to demonstrate (and test) more USB capabilities, this driver
* should include an altsetting to test interrupt transfers, including * should include an altsetting to test interrupt transfers, including
...@@ -608,16 +611,29 @@ check_read_data ( ...@@ -608,16 +611,29 @@ check_read_data (
struct usb_request *req struct usb_request *req
) )
{ {
int i; unsigned i;
u8 *buf = req->buf;
for (i = 0; i < req->actual; i++) {
if (((u8 *)req->buf) [i] != 0) { for (i = 0; i < req->actual; i++, buf++) {
ERROR (dev, "nonzero OUT byte from host, " switch (pattern) {
"buf [%d] = %d\n", /* all-zeroes has no synchronization issues */
i, ((u8 *)req->buf) [i]); case 0:
usb_ep_set_halt (ep); if (*buf == 0)
return -EINVAL; continue;
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:
if (*buf == (u8)(i % 63))
continue;
break;
} }
ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
usb_ep_set_halt (ep);
return -EINVAL;
} }
return 0; return 0;
} }
...@@ -629,7 +645,18 @@ reinit_write_data ( ...@@ -629,7 +645,18 @@ reinit_write_data (
struct usb_request *req struct usb_request *req
) )
{ {
memset (req->buf, 0, req->length); unsigned i;
u8 *buf = req->buf;
switch (pattern) {
case 0:
memset (req->buf, 0, req->length);
break;
case 1:
for (i = 0; i < req->length; i++)
*buf++ = (u8) (i % 63);
break;
}
} }
/* if there is only one request in the queue, there'll always be an /* if there is only one request in the queue, there'll always be an
...@@ -651,10 +678,13 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -651,10 +678,13 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
break; break;
/* this endpoint is normally active while we're configured */ /* this endpoint is normally active while we're configured */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */ case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */ case -ESHUTDOWN: /* disconnect from host */
VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status, VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
req->actual, req->length); req->actual, req->length);
if (ep == dev->out_ep)
check_read_data (dev, ep, req);
free_ep_req (ep, req); free_ep_req (ep, req);
return; return;
...@@ -693,6 +723,9 @@ source_sink_start_ep (struct usb_ep *ep, int gfp_flags) ...@@ -693,6 +723,9 @@ source_sink_start_ep (struct usb_ep *ep, int gfp_flags)
memset (req->buf, 0, req->length); memset (req->buf, 0, req->length);
req->complete = source_sink_complete; req->complete = source_sink_complete;
if (strcmp (ep->name, EP_IN_NAME) == 0)
reinit_write_data (ep->driver_data, ep, req);
status = usb_ep_queue (ep, req, gfp_flags); status = usb_ep_queue (ep, req, gfp_flags);
if (status) { if (status) {
struct zero_dev *dev = ep->driver_data; struct zero_dev *dev = ep->driver_data;
...@@ -801,6 +834,8 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -801,6 +834,8 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
* rely on the hardware driver to clean up on disconnect or * rely on the hardware driver to clean up on disconnect or
* endpoint disable. * endpoint disable.
*/ */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */ case -ESHUTDOWN: /* disconnect from host */
free_ep_req (ep, req); free_ep_req (ep, req);
return; return;
...@@ -905,7 +940,7 @@ static void zero_reset_config (struct zero_dev *dev) ...@@ -905,7 +940,7 @@ static void zero_reset_config (struct zero_dev *dev)
* *
* note that some device controller hardware will constrain what this * note that some device controller hardware will constrain what this
* code can do, perhaps by disallowing more than one configuration or * code can do, perhaps by disallowing more than one configuration or
* by limiting configuration choices (like the pxa250). * by limiting configuration choices (like the pxa2xx).
*/ */
static int static int
zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
...@@ -1046,7 +1081,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1046,7 +1081,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break; break;
/* until we add altsetting support, or other interfaces, /* until we add altsetting support, or other interfaces,
* only 0/0 are possible. * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
* and already killed pending endpoint I/O.
*/ */
case USB_REQ_SET_INTERFACE: case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != USB_RECIP_INTERFACE) if (ctrl->bRequestType != USB_RECIP_INTERFACE)
......
...@@ -319,6 +319,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -319,6 +319,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
int epnum = ep & USB_ENDPOINT_NUMBER_MASK; int epnum = ep & USB_ENDPOINT_NUMBER_MASK;
unsigned long flags; unsigned long flags;
struct ed *ed; struct ed *ed;
unsigned limit = 1000;
/* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: any requests/urbs are being unlinked */
/* ASSERT: nobody can be submitting urbs for this any more */ /* ASSERT: nobody can be submitting urbs for this any more */
...@@ -337,6 +338,8 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -337,6 +338,8 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
ed->state = ED_IDLE; ed->state = ED_IDLE;
switch (ed->state) { switch (ed->state) {
case ED_UNLINK: /* wait for hw to finish? */ case ED_UNLINK: /* wait for hw to finish? */
/* major IRQ delivery trouble loses INTR_SF too... */
WARN_ON (limit-- == 0);
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock_irqrestore (&ohci->lock, flags);
set_current_state (TASK_UNINTERRUPTIBLE); set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (1); schedule_timeout (1);
......
...@@ -43,6 +43,16 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) ...@@ -43,6 +43,16 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
spin_lock (&urb->lock); spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS)) if (likely (urb->status == -EINPROGRESS))
urb->status = 0; urb->status = 0;
/* report short control reads right even though the data TD always
* has TD_R set. (much simpler, but creates the 1-td limit.)
*/
if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
&& unlikely (usb_pipecontrol (urb->pipe))
&& urb->actual_length < urb->transfer_buffer_length
&& usb_pipein (urb->pipe)
&& urb->status == 0) {
urb->status = -EREMOTEIO;
}
spin_unlock (&urb->lock); spin_unlock (&urb->lock);
// what lock protects these? // what lock protects these?
......
...@@ -2007,19 +2007,17 @@ static int suspend_allowed(struct uhci_hcd *uhci) ...@@ -2007,19 +2007,17 @@ static int suspend_allowed(struct uhci_hcd *uhci)
unsigned int io_addr = uhci->io_addr; unsigned int io_addr = uhci->io_addr;
int i; int i;
if (!uhci->hcd.pdev || if (!uhci->hcd.pdev || uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL)
uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL ||
uhci->hcd.pdev->device != PCI_DEVICE_ID_INTEL_82371AB_2)
return 1; return 1;
/* This is a 82371AB/EB/MB USB controller which has a bug that /* Some of Intel's USB controllers have a bug that causes false
* causes false resume indications if any port has an * resume indications if any port has an over current condition.
* over current condition. To prevent problems, we will not * To prevent problems, we will not allow a global suspend if
* allow a global suspend if any ports are OC. * any ports are OC.
* *
* Some motherboards using the 82371AB/EB/MB (but not the USB portion) * Some motherboards using Intel's chipsets (but not using all
* appear to hardwire the over current inputs active to disable * the USB ports) appear to hardwire the over current inputs active
* the USB ports. * to disable the USB ports.
*/ */
/* check for over current condition on any port */ /* check for over current condition on any port */
......
...@@ -306,7 +306,10 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); ...@@ -306,7 +306,10 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
if(unlikely(u->status < 0)) { if(unlikely(u->status < 0)) {
if (likely(hpusbscsi->state != HP_STATE_FREE)) if (likely(hpusbscsi->state != HP_STATE_FREE))
handle_usb_error(hpusbscsi); handle_usb_error(hpusbscsi);
return; if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN)
return;
else
goto resub;
} }
scsi_state = hpusbscsi->scsi_state_byte; scsi_state = hpusbscsi->scsi_state_byte;
...@@ -348,6 +351,8 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); ...@@ -348,6 +351,8 @@ DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
TRACE_STATE; TRACE_STATE;
break; break;
} }
resub:
usb_submit_urb(u, GFP_ATOMIC);
} }
static void simple_command_callback(struct urb *u, struct pt_regs *regs) static void simple_command_callback(struct urb *u, struct pt_regs *regs)
...@@ -427,7 +432,7 @@ static void simple_done (struct urb *u, struct pt_regs *regs) ...@@ -427,7 +432,7 @@ static void simple_done (struct urb *u, struct pt_regs *regs)
hpusbscsi->state = HP_STATE_WAIT; hpusbscsi->state = HP_STATE_WAIT;
} else { } else {
issue_request_sense(hpusbscsi); issue_request_sense(hpusbscsi);
} }
} }
} else { } else {
if (likely(hpusbscsi->scallback != NULL)) if (likely(hpusbscsi->scallback != NULL))
......
...@@ -364,6 +364,11 @@ ...@@ -364,6 +364,11 @@
* Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners. * Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners.
* Fixed names of some other 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.
*
* TODO * TODO
* - Performance * - Performance
* - Select/poll methods * - Select/poll methods
...@@ -1068,6 +1073,9 @@ probe_scanner(struct usb_interface *intf, ...@@ -1068,6 +1073,9 @@ probe_scanner(struct usb_interface *intf,
/* Ok, now initialize all the relevant values */ /* Ok, now initialize all the relevant values */
if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor); 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);
kfree(scn); kfree(scn);
up(&scn_mutex); up(&scn_mutex);
return -ENOMEM; return -ENOMEM;
...@@ -1076,6 +1084,9 @@ probe_scanner(struct usb_interface *intf, ...@@ -1076,6 +1084,9 @@ probe_scanner(struct usb_interface *intf,
if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor); 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);
kfree(scn->obuf); kfree(scn->obuf);
kfree(scn); kfree(scn);
up(&scn_mutex); up(&scn_mutex);
...@@ -1117,10 +1128,9 @@ probe_scanner(struct usb_interface *intf, ...@@ -1117,10 +1128,9 @@ probe_scanner(struct usb_interface *intf,
info ("USB scanner device (0x%04x/0x%04x) now attached to %s", info ("USB scanner device (0x%04x/0x%04x) now attached to %s",
dev->descriptor.idVendor, dev->descriptor.idProduct, name); dev->descriptor.idVendor, dev->descriptor.idProduct, name);
up(&scn_mutex);
usb_set_intfdata(intf, scn); usb_set_intfdata(intf, scn);
up(&scn_mutex);
return 0; return 0;
} }
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
// #define DEBUG // #define DEBUG
#define DRIVER_VERSION "0.4.13" #define DRIVER_VERSION "0.4.14"
#define DRIVER_DESC "USB Scanner Driver" #define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h> #include <linux/usb.h>
...@@ -103,6 +103,7 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -103,6 +103,7 @@ static struct usb_device_id scanner_device_ids [] = {
/* Avision */ /* Avision */
{ USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */ { USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */
{ USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */ { USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */
{ USB_DEVICE(0x0638, 0x0a20) }, /* iVina FB1800 (=Umax Astra 4700) */
/* Benq: see Acer */ /* Benq: see Acer */
/* Brother */ /* Brother */
{ USB_DEVICE(0x04f9, 0x010f) }, /* MFC 5100C */ { USB_DEVICE(0x04f9, 0x010f) }, /* MFC 5100C */
...@@ -115,10 +116,12 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -115,10 +116,12 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */ { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */
{ USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */ { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */
{ USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */
{ USB_DEVICE(0x04a9, 0x220a) }, /* CanoScan D2400UF */
{ USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */ { USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */
{ USB_DEVICE(0x04a9, 0x220c) }, /* CanoScan D1250U2 */ { USB_DEVICE(0x04a9, 0x220c) }, /* CanoScan D1250U2 */
{ USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */ { USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */
{ USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */ { USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */
{ USB_DEVICE(0x04a9, 0x220f) }, /* CanoScan 8000F */
{ USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */ { USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */
{ USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */ { USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */
/* Colorado -- See Primax/Colorado below */ /* Colorado -- See Primax/Colorado below */
...@@ -158,6 +161,7 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -158,6 +161,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */ { USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */
{ USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */ { USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */
{ USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */ { USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */
{ USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */
{ USB_DEVICE(0x03f0, 0x1305) }, /* Scanjet 4570c */ { USB_DEVICE(0x03f0, 0x1305) }, /* Scanjet 4570c */
{ USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */ { USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */
{ USB_DEVICE(0x03f0, 0x2005) }, /* ScanJet 3570c */ { USB_DEVICE(0x03f0, 0x2005) }, /* ScanJet 3570c */
...@@ -173,6 +177,7 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -173,6 +177,7 @@ static struct usb_device_id scanner_device_ids [] = {
/* Memorex */ /* Memorex */
{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek */ /* Microtek */
{ USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */
{ USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */ { USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */
{ USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */ { USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */
{ USB_DEVICE(0x04a7, 0x0224) }, /* Scanport 3000 (actually Visioneer?)*/ { USB_DEVICE(0x04a7, 0x0224) }, /* Scanport 3000 (actually Visioneer?)*/
...@@ -250,6 +255,7 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -250,6 +255,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */ { USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
/* Relisis */ /* Relisis */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */ // { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
{ USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */
/* Seiko/Epson Corp. */ /* Seiko/Epson Corp. */
{ USB_DEVICE(0x04b8, 0x0101) }, /* Perfection 636U and 636Photo */ { USB_DEVICE(0x04b8, 0x0101) }, /* Perfection 636U and 636Photo */
{ USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */ { USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */
......
...@@ -721,7 +721,7 @@ static struct usb_class_driver dabusb_class = { ...@@ -721,7 +721,7 @@ static struct usb_class_driver dabusb_class = {
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static int dabusb_probe (struct usb_interface *intf, static int dabusb_probe (struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *usbdev = interface_to_usbdev(intf); struct usb_device *usbdev = interface_to_usbdev(intf);
...@@ -738,9 +738,7 @@ static int dabusb_probe (struct usb_interface *intf, ...@@ -738,9 +738,7 @@ static int dabusb_probe (struct usb_interface *intf,
if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999) if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
return -ENODEV; return -ENODEV;
retval = usb_register_dev(intf, &dabusb_class);
if (retval)
return -ENOMEM;
s = &dabusb[intf->minor]; s = &dabusb[intf->minor];
...@@ -766,8 +764,15 @@ static int dabusb_probe (struct usb_interface *intf, ...@@ -766,8 +764,15 @@ static int dabusb_probe (struct usb_interface *intf,
} }
} }
dbg("bound to interface: %d", ifnum); dbg("bound to interface: %d", ifnum);
up (&s->mutex);
usb_set_intfdata (intf, s); usb_set_intfdata (intf, s);
up (&s->mutex);
retval = usb_register_dev(intf, &dabusb_class);
if (retval) {
usb_set_intfdata (intf, NULL);
return -ENOMEM;
}
return 0; return 0;
reject: reject:
......
/***************************************************************************** /*****************************************************************************
* USBLCD Kernel Driver * * USBLCD Kernel Driver *
* See http://www.usblcd.de for Hardware and Documentation. * * See http://www.usblcd.de for Hardware and Documentation. *
* Version 1.03 * * Version 1.03 *
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/usb.h> #include <linux/usb.h>
#define DRIVER_VERSION "USBLCD Driver Version 1.03" #define DRIVER_VERSION "USBLCD Driver Version 1.04"
#define USBLCD_MINOR 144 #define USBLCD_MINOR 144
...@@ -257,7 +257,7 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -257,7 +257,7 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
struct lcd_usb_data *lcd = &lcd_instance; struct lcd_usb_data *lcd = &lcd_instance;
int i; int i;
int retval; int retval;
if (dev->descriptor.idProduct != 0x0001 ) { if (dev->descriptor.idProduct != 0x0001 ) {
warn(KERN_INFO "USBLCD model not supported."); warn(KERN_INFO "USBLCD model not supported.");
return -ENODEV; return -ENODEV;
...@@ -274,30 +274,32 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -274,30 +274,32 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF), (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
dev->devnum); dev->devnum);
retval = usb_register_dev(intf, &usb_lcd_class);
if (retval) {
err("Not able to get a minor for this device.");
return -ENOMEM;
}
lcd->present = 1; lcd->present = 1;
lcd->lcd_dev = dev; lcd->lcd_dev = dev;
if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
err("probe_lcd: Not enough memory for the output buffer"); err("probe_lcd: Not enough memory for the output buffer");
usb_deregister_dev(intf, &usb_lcd_class);
return -ENOMEM; return -ENOMEM;
} }
dbg("probe_lcd: obuf address:%p", lcd->obuf); dbg("probe_lcd: obuf address:%p", lcd->obuf);
if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) { if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
err("probe_lcd: Not enough memory for the input buffer"); err("probe_lcd: Not enough memory for the input buffer");
usb_deregister_dev(intf, &usb_lcd_class);
kfree(lcd->obuf); kfree(lcd->obuf);
return -ENOMEM; return -ENOMEM;
} }
dbg("probe_lcd: ibuf address:%p", lcd->ibuf); dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
retval = usb_register_dev(intf, &usb_lcd_class);
if (retval) {
err("Not able to get a minor for this device.");
kfree(lcd->obuf);
kfree(lcd->ibuf);
return -ENOMEM;
}
usb_set_intfdata (intf, lcd); usb_set_intfdata (intf, lcd);
return 0; return 0;
} }
......
...@@ -47,6 +47,7 @@ struct usbtest_info { ...@@ -47,6 +47,7 @@ struct usbtest_info {
const char *name; const char *name;
u8 ep_in; /* bulk/intr source */ u8 ep_in; /* bulk/intr source */
u8 ep_out; /* bulk/intr sink */ u8 ep_out; /* bulk/intr sink */
unsigned autoconf : 1;
int alt; int alt;
}; };
...@@ -78,6 +79,61 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) ...@@ -78,6 +79,61 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int
get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
{
int tmp;
struct usb_host_interface *alt;
struct usb_host_endpoint *in, *out;
struct usb_device *udev;
for (tmp = 0; tmp < intf->max_altsetting; tmp++) {
unsigned ep;
in = out = 0;
alt = intf->altsetting + tmp;
/* take the first altsetting with in-bulk + out-bulk;
* ignore other endpoints and altsetttings.
*/
for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
struct usb_host_endpoint *e;
e = alt->endpoint + ep;
if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
continue;
if (e->desc.bEndpointAddress & USB_DIR_IN) {
if (!in)
in = e;
} else {
if (!out)
out = e;
}
if (in && out)
goto found;
}
}
return -EINVAL;
found:
udev = testdev_to_usbdev (dev);
if (alt->desc.bAlternateSetting != 0) {
tmp = usb_set_interface (udev,
alt->desc.bInterfaceNumber,
alt->desc.bAlternateSetting);
if (tmp < 0)
return tmp;
}
dev->in_pipe = usb_rcvbulkpipe (udev,
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
dev->out_pipe = usb_sndbulkpipe (udev,
out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
return 0;
}
/*-------------------------------------------------------------------------*/
/* Support for testing basic non-queued I/O streams. /* Support for testing basic non-queued I/O streams.
* *
* These just package urbs as requests that can be easily canceled. * These just package urbs as requests that can be easily canceled.
...@@ -1275,14 +1331,26 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) ...@@ -1275,14 +1331,26 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
wtest = " intr-out"; wtest = " intr-out";
} }
} else { } else {
if (info->ep_in) { if (info->autoconf) {
dev->in_pipe = usb_rcvbulkpipe (udev, info->ep_in); int status;
rtest = " bulk-in";
status = get_endpoints (dev, intf);
if (status < 0) {
dbg ("couldn't get endpoints, %d\n", status);
return status;
}
} else {
if (info->ep_in)
dev->in_pipe = usb_rcvbulkpipe (udev,
info->ep_in);
if (info->ep_out)
dev->out_pipe = usb_sndbulkpipe (udev,
info->ep_out);
} }
if (info->ep_out) { if (dev->in_pipe)
dev->out_pipe = usb_sndbulkpipe (udev, info->ep_out); rtest = " bulk-in";
if (dev->out_pipe)
wtest = " bulk-out"; wtest = " bulk-out";
}
} }
usb_set_intfdata (intf, dev); usb_set_intfdata (intf, dev);
...@@ -1336,11 +1404,6 @@ static struct usbtest_info ez2_info = { ...@@ -1336,11 +1404,6 @@ static struct usbtest_info ez2_info = {
}; };
/* ezusb family device with dedicated usb test firmware, /* ezusb family device with dedicated usb test firmware,
* or a peripheral running Linux and 'zero.c' test firmware.
*
* FIXME usbtest should read the descriptors, since compatible
* test firmware might run on hardware (pxa250 for one) that
* can't configure an ep2in-bulk.
*/ */
static struct usbtest_info fw_info = { static struct usbtest_info fw_info = {
.name = "usb test device", .name = "usb test device",
...@@ -1349,10 +1412,20 @@ static struct usbtest_info fw_info = { ...@@ -1349,10 +1412,20 @@ static struct usbtest_info fw_info = {
.alt = 0, .alt = 0,
}; };
/* peripheral running Linux and 'zero.c' test firmware, or
* its user-mode cousin. different versions of this use
* different hardware with the same vendor/product codes.
* host side MUST rely on the endpoint descriptors.
*/
static struct usbtest_info gz_info = {
.name = "Linux gadget zero",
.autoconf = 1,
.alt = 0,
};
static struct usbtest_info um_info = { static struct usbtest_info um_info = {
.name = "user mode test driver", .name = "Linux user mode test driver",
.ep_in = 7, .autoconf = 1,
.ep_out = 3,
.alt = -1, .alt = -1,
}; };
...@@ -1418,7 +1491,7 @@ static struct usb_device_id id_table [] = { ...@@ -1418,7 +1491,7 @@ static struct usb_device_id id_table [] = {
/* "Gadget Zero" firmware runs under Linux */ /* "Gadget Zero" firmware runs under Linux */
{ USB_DEVICE (0x0525, 0xa4a0), { USB_DEVICE (0x0525, 0xa4a0),
.driver_info = (unsigned long) &fw_info, .driver_info = (unsigned long) &gz_info,
}, },
/* so does a user-mode variant */ /* so does a user-mode variant */
......
...@@ -1208,6 +1208,7 @@ static int ax8817x_bind(struct usb_interface *intf, ...@@ -1208,6 +1208,7 @@ static int ax8817x_bind(struct usb_interface *intf,
net->init = ax8817x_net_init; net->init = ax8817x_net_init;
net->priv = ax_info; net->priv = ax_info;
SET_NETDEV_DEV(net, &intf->dev);
ret = register_netdev(net); ret = register_netdev(net);
if (ret < 0) { if (ret < 0) {
err("%s: Failed net init (%d)\n", __FUNCTION__, ret); err("%s: Failed net init (%d)\n", __FUNCTION__, ret);
......
...@@ -936,6 +936,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id ...@@ -936,6 +936,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
printk("%2.2x.\n", netdev->dev_addr[i]); printk("%2.2x.\n", netdev->dev_addr[i]);
usb_set_intfdata(intf, catc); usb_set_intfdata(intf, catc);
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) { if (register_netdev(netdev) != 0) {
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
usb_free_urb(catc->ctrl_urb); usb_free_urb(catc->ctrl_urb);
......
...@@ -1123,8 +1123,9 @@ static int kaweth_probe( ...@@ -1123,8 +1123,9 @@ static int kaweth_probe(
if (dma_supported (&intf->dev, 0xffffffffffffffffULL)) if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
kaweth->net->features |= NETIF_F_HIGHDMA; kaweth->net->features |= NETIF_F_HIGHDMA;
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) { if (register_netdev(netdev) != 0) {
kaweth_err("Error calling init_etherdev."); kaweth_err("Error registering netdev.");
goto err_intfdata; goto err_intfdata;
} }
......
...@@ -1262,7 +1262,6 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1262,7 +1262,6 @@ static int pegasus_probe(struct usb_interface *intf,
} }
set_ethernet_addr(pegasus); set_ethernet_addr(pegasus);
fill_skb_pool(pegasus); fill_skb_pool(pegasus);
printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
if (pegasus->features & PEGASUS_II) { if (pegasus->features & PEGASUS_II) {
info("setup Pegasus II specific registers"); info("setup Pegasus II specific registers");
setup_pegasus_II(pegasus); setup_pegasus_II(pegasus);
...@@ -1273,9 +1272,11 @@ static int pegasus_probe(struct usb_interface *intf, ...@@ -1273,9 +1272,11 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->phy = 1; pegasus->phy = 1;
} }
usb_set_intfdata(intf, pegasus); usb_set_intfdata(intf, pegasus);
SET_NETDEV_DEV(net, &intf->dev);
res = register_netdev(net); res = register_netdev(net);
if (res) if (res)
goto out4; goto out4;
printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
return 0; return 0;
out4: out4:
......
...@@ -830,6 +830,7 @@ static int rtl8150_probe(struct usb_interface *intf, ...@@ -830,6 +830,7 @@ static int rtl8150_probe(struct usb_interface *intf,
usb_set_intfdata(intf, dev); usb_set_intfdata(intf, dev);
SET_NETDEV_DEV(netdev, &intf->dev);
if (register_netdev(netdev) != 0) { if (register_netdev(netdev) != 0) {
err("couldn't register the device"); err("couldn't register the device");
goto out2; goto out2;
......
...@@ -2602,7 +2602,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) ...@@ -2602,7 +2602,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
SET_NETDEV_DEV(dev->net, &dev->udev->dev); SET_NETDEV_DEV(dev->net, &udev->dev);
status = register_netdev (dev->net); status = register_netdev (dev->net);
if (status) if (status)
goto out3; goto out3;
......
...@@ -257,6 +257,7 @@ static struct usb_device_id id_table_8U232AM [] = { ...@@ -257,6 +257,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) },
...@@ -321,6 +322,7 @@ static struct usb_device_id id_table_FT232BM [] = { ...@@ -321,6 +322,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
...@@ -396,6 +398,7 @@ static __devinitdata struct usb_device_id id_table_combined [] = { ...@@ -396,6 +398,7 @@ static __devinitdata struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) }, { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) },
......
...@@ -105,7 +105,13 @@ ...@@ -105,7 +105,13 @@
#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
#define FTDI_DSS20_PID 0xFC82
/* /*
* Home Electronics (www.home-electro.com) USB gadgets * Home Electronics (www.home-electro.com) USB gadgets
*/ */
......
...@@ -125,10 +125,13 @@ static struct usb_device_id ipaq_id_table [] = { ...@@ -125,10 +125,13 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) }, { USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) },
{ USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) }, { USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) },
{ USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) }, { USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) },
{ USB_DEVICE(ROVER_VENDOR_ID, ROVER_P5_ID) },
{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) }, { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) },
{ USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) }, { USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E310_ID) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) },
{ USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) }, { USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) },
{ USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) }, { USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) },
{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) }, { USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) },
......
...@@ -61,6 +61,9 @@ ...@@ -61,6 +61,9 @@
#define PORTATEC_VENDOR_ID 0x0961 #define PORTATEC_VENDOR_ID 0x0961
#define PORTATEC_PRODUCT_ID 0x0010 #define PORTATEC_PRODUCT_ID 0x0010
#define ROVER_VENDOR_ID 0x047b
#define ROVER_P5_ID 0x3000
#define SAGEM_VENDOR_ID 0x5e04 #define SAGEM_VENDOR_ID 0x5e04
#define SAGEM_WIRELESS_ID 0xce00 #define SAGEM_WIRELESS_ID 0xce00
...@@ -69,7 +72,9 @@ ...@@ -69,7 +72,9 @@
#define TOSHIBA_VENDOR_ID 0x0930 #define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_PRODUCT_ID 0x0700 #define TOSHIBA_PRODUCT_ID 0x0700
#define TOSHIBA_E310_ID 0x0705
#define TOSHIBA_E740_ID 0x0706 #define TOSHIBA_E740_ID 0x0706
#define TOSHIBA_E335_ID 0x0707
#define HTC_VENDOR_ID 0x0bb4 #define HTC_VENDOR_ID 0x0bb4
#define HTC_PRODUCT_ID 0x00ce #define HTC_PRODUCT_ID 0x00ce
......
...@@ -530,7 +530,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp) ...@@ -530,7 +530,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
/* if disconnect beat us to the punch here, there's nothing to do */ /* if disconnect beat us to the punch here, there's nothing to do */
if (tty && tty->driver_data) { if (tty && tty->driver_data) {
__serial_close(port, filp); __serial_close(port, filp);
tty->driver_data = NULL;
} }
port->tty = NULL;
} }
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
......
...@@ -509,18 +509,17 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) ...@@ -509,18 +509,17 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{ {
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
if (port_paranoia_check (port, __FUNCTION__)) if (port_paranoia_check (port, __FUNCTION__))
return; return;
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) { if (urb->status)
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); dbg("%s - nonzero write bulk status received: %d",
return; __FUNCTION__, urb->status);
}
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
schedule_work(&port->work); schedule_work(&port->work);
} }
......
...@@ -280,6 +280,7 @@ struct isd200_info { ...@@ -280,6 +280,7 @@ struct isd200_info {
/* maximum number of LUNs supported */ /* maximum number of LUNs supported */
unsigned char MaxLUNs; unsigned char MaxLUNs;
struct scsi_cmnd srb;
}; };
...@@ -404,15 +405,15 @@ static int isd200_action( struct us_data *us, int action, ...@@ -404,15 +405,15 @@ static int isd200_action( struct us_data *us, int action,
void* pointer, int value ) void* pointer, int value )
{ {
union ata_cdb ata; union ata_cdb ata;
struct scsi_cmnd srb;
struct scsi_device srb_dev; struct scsi_device srb_dev;
struct isd200_info *info = (struct isd200_info *)us->extra; struct isd200_info *info = (struct isd200_info *)us->extra;
struct scsi_cmnd *srb = &info->srb;
int status; int status;
memset(&ata, 0, sizeof(ata)); memset(&ata, 0, sizeof(ata));
memset(&srb, 0, sizeof(srb));
memset(&srb_dev, 0, sizeof(srb_dev)); memset(&srb_dev, 0, sizeof(srb_dev));
srb.device = &srb_dev; srb->device = &srb_dev;
++srb->serial_number;
ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
...@@ -425,9 +426,9 @@ static int isd200_action( struct us_data *us, int action, ...@@ -425,9 +426,9 @@ static int isd200_action( struct us_data *us, int action,
ata.generic.RegisterSelect = ata.generic.RegisterSelect =
REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
REG_STATUS | REG_ERROR; REG_STATUS | REG_ERROR;
srb.sc_data_direction = SCSI_DATA_READ; srb->sc_data_direction = SCSI_DATA_READ;
srb.request_buffer = pointer; srb->request_buffer = pointer;
srb.request_bufflen = value; srb->request_bufflen = value;
break; break;
case ACTION_ENUM: case ACTION_ENUM:
...@@ -437,7 +438,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -437,7 +438,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_5; ACTION_SELECT_5;
ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.generic.RegisterSelect = REG_DEVICE_HEAD;
ata.write.DeviceHeadByte = value; ata.write.DeviceHeadByte = value;
srb.sc_data_direction = SCSI_DATA_NONE; srb->sc_data_direction = SCSI_DATA_NONE;
break; break;
case ACTION_RESET: case ACTION_RESET:
...@@ -446,7 +447,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -446,7 +447,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_3|ACTION_SELECT_4; ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
srb.sc_data_direction = SCSI_DATA_NONE; srb->sc_data_direction = SCSI_DATA_NONE;
break; break;
case ACTION_REENABLE: case ACTION_REENABLE:
...@@ -455,7 +456,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -455,7 +456,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_3|ACTION_SELECT_4; ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
srb.sc_data_direction = SCSI_DATA_NONE; srb->sc_data_direction = SCSI_DATA_NONE;
break; break;
case ACTION_SOFT_RESET: case ACTION_SOFT_RESET:
...@@ -464,16 +465,16 @@ static int isd200_action( struct us_data *us, int action, ...@@ -464,16 +465,16 @@ static int isd200_action( struct us_data *us, int action,
ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
ata.write.DeviceHeadByte = info->DeviceHead; ata.write.DeviceHeadByte = info->DeviceHead;
ata.write.CommandByte = WIN_SRST; ata.write.CommandByte = WIN_SRST;
srb.sc_data_direction = SCSI_DATA_NONE; srb->sc_data_direction = SCSI_DATA_NONE;
break; break;
case ACTION_IDENTIFY: case ACTION_IDENTIFY:
US_DEBUGP(" isd200_action(IDENTIFY)\n"); US_DEBUGP(" isd200_action(IDENTIFY)\n");
ata.generic.RegisterSelect = REG_COMMAND; ata.generic.RegisterSelect = REG_COMMAND;
ata.write.CommandByte = WIN_IDENTIFY; ata.write.CommandByte = WIN_IDENTIFY;
srb.sc_data_direction = SCSI_DATA_READ; srb->sc_data_direction = SCSI_DATA_READ;
srb.request_buffer = (void *)&info->drive; srb->request_buffer = (void *)&info->drive;
srb.request_bufflen = sizeof(struct hd_driveid); srb->request_bufflen = sizeof(struct hd_driveid);
break; break;
default: default:
...@@ -481,9 +482,9 @@ static int isd200_action( struct us_data *us, int action, ...@@ -481,9 +482,9 @@ static int isd200_action( struct us_data *us, int action,
break; break;
} }
memcpy(srb.cmnd, &ata, sizeof(ata.generic)); memcpy(srb->cmnd, &ata, sizeof(ata.generic));
srb.cmd_len = sizeof(ata.generic); srb->cmd_len = sizeof(ata.generic);
status = usb_stor_Bulk_transport(&srb, us); status = usb_stor_Bulk_transport(srb, us);
if (status == USB_STOR_TRANSPORT_GOOD) if (status == USB_STOR_TRANSPORT_GOOD)
status = ISD200_GOOD; status = ISD200_GOOD;
else { else {
...@@ -834,7 +835,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, ...@@ -834,7 +835,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
int detect ) int detect )
{ {
int status = ISD200_GOOD; int status = ISD200_GOOD;
unsigned char regs[8]; unsigned char *regs = us->iobuf;
unsigned long endTime; unsigned long endTime;
struct isd200_info *info = (struct isd200_info *)us->extra; struct isd200_info *info = (struct isd200_info *)us->extra;
int recheckAsMaster = FALSE; int recheckAsMaster = FALSE;
...@@ -856,7 +857,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, ...@@ -856,7 +857,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
break; break;
status = isd200_action( us, ACTION_READ_STATUS, status = isd200_action( us, ACTION_READ_STATUS,
regs, sizeof(regs) ); regs, 8 );
if ( status != ISD200_GOOD ) if ( status != ISD200_GOOD )
break; break;
......
...@@ -86,7 +86,6 @@ static inline int jumpshot_bulk_write(struct us_data *us, ...@@ -86,7 +86,6 @@ static inline int jumpshot_bulk_write(struct us_data *us,
static int jumpshot_get_status(struct us_data *us) static int jumpshot_get_status(struct us_data *us)
{ {
unsigned char reply;
int rc; int rc;
if (!us) if (!us)
...@@ -94,14 +93,14 @@ static int jumpshot_get_status(struct us_data *us) ...@@ -94,14 +93,14 @@ static int jumpshot_get_status(struct us_data *us)
// send the setup // send the setup
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
0, 0xA0, 0, 7, &reply, 1); 0, 0xA0, 0, 7, us->iobuf, 1);
if (rc != USB_STOR_XFER_GOOD) if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
if (reply != 0x50) { if (us->iobuf[0] != 0x50) {
US_DEBUGP("jumpshot_get_status: 0x%2x\n", US_DEBUGP("jumpshot_get_status: 0x%2x\n",
(unsigned short) (reply)); us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -115,7 +114,7 @@ static int jumpshot_read_data(struct us_data *us, ...@@ -115,7 +114,7 @@ static int jumpshot_read_data(struct us_data *us,
unsigned char *dest, unsigned char *dest,
int use_sg) int use_sg)
{ {
unsigned char command[] = { 0, 0, 0, 0, 0, 0xe0, 0x20 }; unsigned char *command = us->iobuf;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
unsigned char *ptr; unsigned char *ptr;
unsigned char thistime; unsigned char thistime;
...@@ -154,7 +153,8 @@ static int jumpshot_read_data(struct us_data *us, ...@@ -154,7 +153,8 @@ static int jumpshot_read_data(struct us_data *us,
command[3] = (sector >> 8) & 0xFF; command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF; command[4] = (sector >> 16) & 0xFF;
command[5] |= (sector >> 24) & 0x0F; command[5] = 0xE0 | ((sector >> 24) & 0x0F);
command[6] = 0x20;
// send the setup + command // send the setup + command
result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
...@@ -199,7 +199,7 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -199,7 +199,7 @@ static int jumpshot_write_data(struct us_data *us,
unsigned char *src, unsigned char *src,
int use_sg) int use_sg)
{ {
unsigned char command[7] = { 0, 0, 0, 0, 0, 0xE0, 0x30 }; unsigned char *command = us->iobuf;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
unsigned char *ptr; unsigned char *ptr;
unsigned char thistime; unsigned char thistime;
...@@ -240,7 +240,8 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -240,7 +240,8 @@ static int jumpshot_write_data(struct us_data *us,
command[3] = (sector >> 8) & 0xFF; command[3] = (sector >> 8) & 0xFF;
command[4] = (sector >> 16) & 0xFF; command[4] = (sector >> 16) & 0xFF;
command[5] |= (sector >> 24) & 0x0F; command[5] = 0xE0 | ((sector >> 24) & 0x0F);
command[6] = 0x30;
// send the setup + command // send the setup + command
result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
...@@ -291,13 +292,19 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -291,13 +292,19 @@ static int jumpshot_write_data(struct us_data *us,
static int jumpshot_id_device(struct us_data *us, static int jumpshot_id_device(struct us_data *us,
struct jumpshot_info *info) struct jumpshot_info *info)
{ {
unsigned char command[2] = { 0xe0, 0xec }; unsigned char *command = us->iobuf;
unsigned char reply[512]; unsigned char *reply;
int rc; int rc;
if (!us || !info) if (!us || !info)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
command[0] = 0xE0;
command[1] = 0xEC;
reply = kmalloc(512, GFP_NOIO);
if (!reply)
return USB_STOR_TRANSPORT_ERROR;
// send the setup // send the setup
rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
0, 0x20, 0, 6, command, 2); 0, 0x20, 0, 6, command, 2);
...@@ -305,20 +312,27 @@ static int jumpshot_id_device(struct us_data *us, ...@@ -305,20 +312,27 @@ static int jumpshot_id_device(struct us_data *us,
if (rc != USB_STOR_XFER_GOOD) { if (rc != USB_STOR_XFER_GOOD) {
US_DEBUGP("jumpshot_id_device: Gah! " US_DEBUGP("jumpshot_id_device: Gah! "
"send_control for read_capacity failed\n"); "send_control for read_capacity failed\n");
return rc; rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
} }
// read the reply // read the reply
rc = jumpshot_bulk_read(us, reply, sizeof(reply)); rc = jumpshot_bulk_read(us, reply, sizeof(reply));
if (rc != USB_STOR_XFER_GOOD) if (rc != USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR; rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
info->sectors = ((u32)(reply[117]) << 24) | info->sectors = ((u32)(reply[117]) << 24) |
((u32)(reply[116]) << 16) | ((u32)(reply[116]) << 16) |
((u32)(reply[115]) << 8) | ((u32)(reply[115]) << 8) |
((u32)(reply[114]) ); ((u32)(reply[114]) );
return USB_STOR_TRANSPORT_GOOD; rc = USB_STOR_TRANSPORT_GOOD;
leave:
kfree(reply);
return rc;
} }
static int jumpshot_handle_mode_sense(struct us_data *us, static int jumpshot_handle_mode_sense(struct us_data *us,
......
...@@ -130,8 +130,9 @@ static void fix_read_capacity(Scsi_Cmnd *srb) ...@@ -130,8 +130,9 @@ static void fix_read_capacity(Scsi_Cmnd *srb)
void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
{ {
/* Pad the ATAPI command with zeros /* Pad the ATAPI command with zeros
*
* NOTE: This only works because a Scsi_Cmnd struct field contains * NOTE: This only works because a Scsi_Cmnd struct field contains
* a unsigned char cmnd[12], so we know we have storage available * a unsigned char cmnd[16], so we know we have storage available
*/ */
for (; srb->cmd_len<12; srb->cmd_len++) for (; srb->cmd_len<12; srb->cmd_len++)
srb->cmnd[srb->cmd_len] = 0; srb->cmnd[srb->cmd_len] = 0;
...@@ -149,13 +150,10 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -149,13 +150,10 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
{ {
int old_cmnd = 0; /* Pad the ATAPI command with zeros
/* Fix some commands -- this is a form of mode translation
* ATAPI devices only accept 12 byte long commands
* *
* NOTE: This only works because a Scsi_Cmnd struct field contains * NOTE: This only works because a Scsi_Cmnd struct field contains
* a unsigned char cmnd[12], so we know we have storage available * a unsigned char cmnd[16], so we know we have storage available
*/ */
/* Pad the ATAPI command with zeros */ /* Pad the ATAPI command with zeros */
...@@ -165,60 +163,10 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -165,60 +163,10 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
/* set command length to 12 bytes */ /* set command length to 12 bytes */
srb->cmd_len = 12; srb->cmd_len = 12;
/* determine the correct (or minimum) data length for these commands */
switch (srb->cmnd[0]) {
/* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
case MODE_SENSE:
case MODE_SELECT:
/* save the command so we can tell what it was */
old_cmnd = srb->cmnd[0];
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = 0;
srb->cmnd[4] = 0;
srb->cmnd[3] = 0;
srb->cmnd[2] = srb->cmnd[2];
srb->cmnd[1] = srb->cmnd[1];
srb->cmnd[0] = srb->cmnd[0] | 0x40;
break;
/* change READ_6/WRITE_6 to READ_10/WRITE_10, which
* are ATAPI commands */
case WRITE_6:
case READ_6:
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = srb->cmnd[3];
srb->cmnd[4] = srb->cmnd[2];
srb->cmnd[3] = srb->cmnd[1] & 0x1F;
srb->cmnd[2] = 0;
srb->cmnd[1] = srb->cmnd[1] & 0xE0;
srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
} /* end switch on cmnd[0] */
/* convert MODE_SELECT data here */
if (old_cmnd == MODE_SELECT)
usb_stor_scsiSense6to10(srb);
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE)
usb_stor_scsiSense10to6(srb);
if (srb->result == SAM_STAT_GOOD) {
/* fix the INQUIRY data if necessary */ /* fix the INQUIRY data if necessary */
fix_inquiry_data(srb); fix_inquiry_data(srb);
} }
...@@ -227,19 +175,23 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -227,19 +175,23 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
{ {
int old_cmnd = 0;
/* fix some commands -- this is a form of mode translation /* fix some commands -- this is a form of mode translation
* UFI devices only accept 12 byte long commands * UFI devices only accept 12 byte long commands
* *
* NOTE: This only works because a Scsi_Cmnd struct field contains * NOTE: This only works because a Scsi_Cmnd struct field contains
* a unsigned char cmnd[12], so we know we have storage available * a unsigned char cmnd[16], so we know we have storage available
*/ */
/* Pad the ATAPI command with zeros */
for (; srb->cmd_len<12; srb->cmd_len++)
srb->cmnd[srb->cmd_len] = 0;
/* set command length to 12 bytes (this affects the transport layer) */ /* set command length to 12 bytes (this affects the transport layer) */
srb->cmd_len = 12; srb->cmd_len = 12;
/* determine the correct (or minimum) data length for these commands */ /* XXX We should be constantly re-evaluating the need for these */
/* determine the correct data length for these commands */
switch (srb->cmnd[0]) { switch (srb->cmnd[0]) {
/* for INQUIRY, UFI devices only ever return 36 bytes */ /* for INQUIRY, UFI devices only ever return 36 bytes */
...@@ -247,33 +199,6 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -247,33 +199,6 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[4] = 36; srb->cmnd[4] = 36;
break; break;
/* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
case MODE_SENSE:
case MODE_SELECT:
/* save the command so we can tell what it was */
old_cmnd = srb->cmnd[0];
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
/* if we're sending data, we send all. If getting data,
* get the minimum */
if (srb->cmnd[0] == MODE_SELECT)
srb->cmnd[8] = srb->cmnd[4];
else
srb->cmnd[8] = 8;
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = 0;
srb->cmnd[4] = 0;
srb->cmnd[3] = 0;
srb->cmnd[2] = srb->cmnd[2];
srb->cmnd[1] = srb->cmnd[1];
srb->cmnd[0] = srb->cmnd[0] | 0x40;
break;
/* again, for MODE_SENSE_10, we get the minimum (8) */ /* again, for MODE_SENSE_10, we get the minimum (8) */
case MODE_SENSE_10: case MODE_SENSE_10:
srb->cmnd[7] = 0; srb->cmnd[7] = 0;
...@@ -284,38 +209,12 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -284,38 +209,12 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
case REQUEST_SENSE: case REQUEST_SENSE:
srb->cmnd[4] = 18; srb->cmnd[4] = 18;
break; break;
/* change READ_6/WRITE_6 to READ_10/WRITE_10, which
* are UFI commands */
case WRITE_6:
case READ_6:
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = srb->cmnd[3];
srb->cmnd[4] = srb->cmnd[2];
srb->cmnd[3] = srb->cmnd[1] & 0x1F;
srb->cmnd[2] = 0;
srb->cmnd[1] = srb->cmnd[1] & 0xE0;
srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
} /* end switch on cmnd[0] */ } /* end switch on cmnd[0] */
/* convert MODE_SELECT data here */
if (old_cmnd == MODE_SELECT)
usb_stor_scsiSense6to10(srb);
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE)
usb_stor_scsiSense10to6(srb);
if (srb->result == SAM_STAT_GOOD) {
/* Fix the data for an INQUIRY, if necessary */ /* Fix the data for an INQUIRY, if necessary */
fix_inquiry_data(srb); fix_inquiry_data(srb);
} }
...@@ -323,68 +222,10 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -323,68 +222,10 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
{ {
int old_cmnd = 0;
/* This code supports devices which do not support {READ|WRITE}_6
* Apparently, neither Windows or MacOS will use these commands,
* so some devices do not support them
*/
if (us->flags & US_FL_MODE_XLATE) {
US_DEBUGP("Invoking Mode Translation\n");
/* save the old command for later */
old_cmnd = srb->cmnd[0];
switch (srb->cmnd[0]) {
/* change READ_6/WRITE_6 to READ_10/WRITE_10 */
case WRITE_6:
case READ_6:
srb->cmd_len = 12;
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = srb->cmnd[3];
srb->cmnd[4] = srb->cmnd[2];
srb->cmnd[3] = srb->cmnd[1] & 0x1F;
srb->cmnd[2] = 0;
srb->cmnd[1] = srb->cmnd[1] & 0xE0;
srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
/* convert MODE_SELECT data here */
case MODE_SENSE:
case MODE_SELECT:
srb->cmd_len = 12;
srb->cmnd[11] = 0;
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[6] = 0;
srb->cmnd[5] = 0;
srb->cmnd[4] = 0;
srb->cmnd[3] = 0;
srb->cmnd[2] = srb->cmnd[2];
srb->cmnd[1] = srb->cmnd[1];
srb->cmnd[0] = srb->cmnd[0] | 0x40;
break;
} /* switch (srb->cmnd[0]) */
} /* if (us->flags & US_FL_MODE_XLATE) */
/* convert MODE_SELECT data here */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SELECT))
usb_stor_scsiSense6to10(srb);
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
usb_stor_scsiSense10to6(srb);
if (srb->result == SAM_STAT_GOOD) {
/* Fix the INQUIRY data if necessary */ /* Fix the INQUIRY data if necessary */
fix_inquiry_data(srb); fix_inquiry_data(srb);
......
...@@ -263,7 +263,6 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off ...@@ -263,7 +263,6 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off
#define DO_FLAG(a) if (f & US_FL_##a) pos += sprintf(pos, " " #a) #define DO_FLAG(a) if (f & US_FL_##a) pos += sprintf(pos, " " #a)
DO_FLAG(SINGLE_LUN); DO_FLAG(SINGLE_LUN);
DO_FLAG(MODE_XLATE);
DO_FLAG(SCM_MULT_TARG); DO_FLAG(SCM_MULT_TARG);
DO_FLAG(FIX_INQUIRY); DO_FLAG(FIX_INQUIRY);
DO_FLAG(FIX_CAPACITY); DO_FLAG(FIX_CAPACITY);
...@@ -346,499 +345,3 @@ unsigned char usb_stor_sense_invalidCDB[18] = { ...@@ -346,499 +345,3 @@ unsigned char usb_stor_sense_invalidCDB[18] = {
[12] = 0x24 /* Invalid Field in CDB */ [12] = 0x24 /* Invalid Field in CDB */
}; };
#define USB_STOR_SCSI_SENSE_HDRSZ 4
#define USB_STOR_SCSI_SENSE_10_HDRSZ 8
struct usb_stor_scsi_sense_hdr
{
__u8* dataLength;
__u8* mediumType;
__u8* devSpecParms;
__u8* blkDescLength;
};
typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
union usb_stor_scsi_sense_hdr_u
{
Usb_Stor_Scsi_Sense_Hdr hdr;
__u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
};
typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
struct usb_stor_scsi_sense_hdr_10
{
__u8* dataLengthMSB;
__u8* dataLengthLSB;
__u8* mediumType;
__u8* devSpecParms;
__u8* reserved1;
__u8* reserved2;
__u8* blkDescLengthMSB;
__u8* blkDescLengthLSB;
};
typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
union usb_stor_scsi_sense_hdr_10_u
{
Usb_Stor_Scsi_Sense_Hdr_10 hdr;
__u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
};
typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
{
__u8 *buffer=0;
int outputBufferSize = 0;
int length=0;
struct scatterlist *sg = 0;
int i=0, j=0, element=0;
Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
int sb=0,si=0,db=0,di=0;
int sgLength=0;
US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
the10->cmnd[0] = the10->cmnd[0] & 0xBF;
/* Determine buffer locations */
usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
&length );
/* Work out minimum buffer to output */
outputBufferSize = *the10Locations.hdr.dataLengthLSB;
outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
/* Check to see if we need to trucate the output */
if ( outputBufferSize > length )
{
printk( KERN_WARNING USB_STORAGE
"Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
printk( KERN_WARNING USB_STORAGE
"outputBufferSize is %d and length is %d.\n",
outputBufferSize, length );
}
outputBufferSize = length;
/* Data length */
if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
{
printk( KERN_WARNING USB_STORAGE
"Command will be truncated to fit in SENSE6 buffer.\n" );
*the6Locations.hdr.dataLength = 0xff;
}
else
{
*the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
}
/* Medium type and DevSpecific parms */
*the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
*the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
/* Block descriptor length */
if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
{
printk( KERN_WARNING USB_STORAGE
"Command will be truncated to fit in SENSE6 buffer.\n" );
*the6Locations.hdr.blkDescLength = 0xff;
}
else
{
*the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
}
if ( the10->use_sg == 0 )
{
buffer = the10->request_buffer;
/* Copy the rest of the data */
memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
&(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
/* initialise last bytes left in buffer due to smaller header */
memset( &(buffer[outputBufferSize
-(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
0,
USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
}
else
{
sg = (struct scatterlist *) the10->request_buffer;
/* scan through this scatterlist and figure out starting positions */
for ( i=0; i < the10->use_sg; i++)
{
sgLength = sg[i].length;
for ( j=0; j<sgLength; j++ )
{
/* get to end of header */
if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
{
db=i;
di=j;
}
if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
{
sb=i;
si=j;
/* we've found both sets now, exit loops */
j=sgLength;
i=the10->use_sg;
}
element++;
}
}
/* Now we know where to start the copy from */
element = USB_STOR_SCSI_SENSE_HDRSZ;
while ( element < outputBufferSize
-(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
{
/* check limits */
if ( sb >= the10->use_sg ||
si >= sg[sb].length ||
db >= the10->use_sg ||
di >= sg[db].length )
{
printk( KERN_ERR USB_STORAGE
"Buffer overrun averted, this shouldn't happen!\n" );
break;
}
/* copy one byte */
{
char *src = sg_address(sg[sb]) + si;
char *dst = sg_address(sg[db]) + di;
*dst = *src;
}
/* get next destination */
if ( sg[db].length-1 == di )
{
db++;
di=0;
}
else
{
di++;
}
/* get next source */
if ( sg[sb].length-1 == si )
{
sb++;
si=0;
}
else
{
si++;
}
element++;
}
/* zero the remaining bytes */
while ( element < outputBufferSize )
{
/* check limits */
if ( db >= the10->use_sg ||
di >= sg[db].length )
{
printk( KERN_ERR USB_STORAGE
"Buffer overrun averted, this shouldn't happen!\n" );
break;
}
*(char*)(sg_address(sg[db])) = 0;
/* get next destination */
if ( sg[db].length-1 == di )
{
db++;
di=0;
}
else
{
di++;
}
element++;
}
}
/* All done any everything was fine */
return 0;
}
int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
{
/* will be used to store part of buffer */
__u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
*buffer=0;
int outputBufferSize = 0;
int length=0;
struct scatterlist *sg = 0;
int i=0, j=0, element=0;
Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
int sb=0,si=0,db=0,di=0;
int lsb=0,lsi=0,ldb=0,ldi=0;
US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
the6->cmnd[0] = the6->cmnd[0] | 0x40;
/* Determine buffer locations */
usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
&length );
/* Work out minimum buffer to output */
outputBufferSize = *the6Locations.hdr.dataLength;
outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
/* Check to see if we need to trucate the output */
if ( outputBufferSize > length )
{
printk( KERN_WARNING USB_STORAGE
"Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
printk( KERN_WARNING USB_STORAGE
"outputBufferSize is %d and length is %d.\n",
outputBufferSize, length );
}
outputBufferSize = length;
/* Block descriptor length - save these before overwriting */
tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
*the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
*the10Locations.hdr.blkDescLengthMSB = 0;
/* reserved - save these before overwriting */
tempBuffer[0] = *the10Locations.hdr.reserved1;
tempBuffer[1] = *the10Locations.hdr.reserved2;
*the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
/* Medium type and DevSpecific parms */
*the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
*the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
/* Data length */
*the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
*the10Locations.hdr.dataLengthMSB = 0;
if ( !the6->use_sg )
{
buffer = the6->request_buffer;
/* Copy the rest of the data */
memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
&(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
/* Put the first four bytes (after header) in place */
memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
tempBuffer,
USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
}
else
{
sg = (struct scatterlist *) the6->request_buffer;
/* scan through this scatterlist and figure out ending positions */
for ( i=0; i < the6->use_sg; i++)
{
for ( j=0; j<sg[i].length; j++ )
{
/* get to end of header */
if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
{
ldb=i;
ldi=j;
}
if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
{
lsb=i;
lsi=j;
/* we've found both sets now, exit loops */
j=sg[i].length;
i=the6->use_sg;
break;
}
element++;
}
}
/* scan through this scatterlist and figure out starting positions */
element = length-1;
/* destination is the last element */
db=the6->use_sg-1;
di=sg[db].length-1;
for ( i=the6->use_sg-1; i >= 0; i--)
{
for ( j=sg[i].length-1; j>=0; j-- )
{
/* get to end of header and find source for copy */
if ( element == length - 1
- (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
{
sb=i;
si=j;
/* we've found both sets now, exit loops */
j=-1;
i=-1;
}
element--;
}
}
/* Now we know where to start the copy from */
element = length-1
- (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
{
/* check limits */
if ( ( sb <= lsb && si < lsi ) ||
( db <= ldb && di < ldi ) )
{
printk( KERN_ERR USB_STORAGE
"Buffer overrun averted, this shouldn't happen!\n" );
break;
}
/* copy one byte */
{
char *src = sg_address(sg[sb]) + si;
char *dst = sg_address(sg[db]) + di;
*dst = *src;
}
/* get next destination */
if ( di == 0 )
{
db--;
di=sg[db].length-1;
}
else
{
di--;
}
/* get next source */
if ( si == 0 )
{
sb--;
si=sg[sb].length-1;
}
else
{
si--;
}
element--;
}
/* copy the remaining four bytes */
while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
{
/* check limits */
if ( db <= ldb && di < ldi )
{
printk( KERN_ERR USB_STORAGE
"Buffer overrun averted, this shouldn't happen!\n" );
break;
}
{
char *dst = sg_address(sg[db]) + di;
*dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
}
/* get next destination */
if ( di == 0 )
{
db--;
di=sg[db].length-1;
}
else
{
di--;
}
element--;
}
}
/* All done and everything was fine */
return 0;
}
void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
int* length_p )
{
int i = 0, j=0, element=0;
struct scatterlist *sg = 0;
int length = 0;
__u8* buffer=0;
/* are we scatter-gathering? */
if ( srb->use_sg != 0 )
{
/* loop over all the scatter gather structures and
* get pointer to the data members in the headers
* (also work out the length while we're here)
*/
sg = (struct scatterlist *) srb->request_buffer;
for (i = 0; i < srb->use_sg; i++)
{
length += sg[i].length;
/* We only do the inner loop for the headers */
if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
{
/* scan through this scatterlist */
for ( j=0; j<sg[i].length; j++ )
{
if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
{
/* fill in the pointers for both header types */
the6->array[element] = sg_address(sg[i]) + j;
the10->array[element] = sg_address(sg[i]) + j;
}
else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
{
/* only the longer headers still cares now */
the10->array[element] = sg_address(sg[i]) + j;
}
/* increase element counter */
element++;
}
}
}
}
else
{
length = srb->request_bufflen;
buffer = srb->request_buffer;
if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
printk( KERN_ERR USB_STORAGE
"Buffer length smaller than header!!" );
for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
{
if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
{
the6->array[i] = &(buffer[i]);
the10->array[i] = &(buffer[i]);
}
else
{
the10->array[i] = &(buffer[i]);
}
}
}
/* Set value of length passed in */
*length_p = length;
}
...@@ -261,12 +261,13 @@ sddr09_send_scsi_command(struct us_data *us, ...@@ -261,12 +261,13 @@ sddr09_send_scsi_command(struct us_data *us,
*/ */
static int static int
sddr09_test_unit_ready(struct us_data *us) { sddr09_test_unit_ready(struct us_data *us) {
unsigned char command[6] = { unsigned char *command = us->iobuf;
0, LUNBITS, 0, 0, 0, 0
};
int result; int result;
result = sddr09_send_scsi_command(us, command, sizeof(command)); memset(command, 0, 6);
command[1] = LUNBITS;
result = sddr09_send_scsi_command(us, command, 6);
US_DEBUGP("sddr09_test_unit_ready returns %d\n", result); US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);
...@@ -281,12 +282,15 @@ sddr09_test_unit_ready(struct us_data *us) { ...@@ -281,12 +282,15 @@ sddr09_test_unit_ready(struct us_data *us) {
*/ */
static int static int
sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) { sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0x03, LUNBITS, 0, 0, buflen, 0, 0, 0, 0, 0, 0, 0
};
int result; int result;
result = sddr09_send_scsi_command(us, command, sizeof(command)); memset(command, 0, 12);
command[0] = 0x03;
command[1] = LUNBITS;
command[4] = buflen;
result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
US_DEBUGP("request sense failed\n"); US_DEBUGP("request sense failed\n");
return result; return result;
...@@ -331,20 +335,23 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress, ...@@ -331,20 +335,23 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
int nr_of_pages, int bulklen, unsigned char *buf, int nr_of_pages, int bulklen, unsigned char *buf,
int use_sg) { int use_sg) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xe8, LUNBITS | x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int result; int result;
command[0] = 0xE8;
command[1] = LUNBITS | x;
command[2] = MSB_of(fromaddress>>16); command[2] = MSB_of(fromaddress>>16);
command[3] = LSB_of(fromaddress>>16); command[3] = LSB_of(fromaddress>>16);
command[4] = MSB_of(fromaddress & 0xFFFF); command[4] = MSB_of(fromaddress & 0xFFFF);
command[5] = LSB_of(fromaddress & 0xFFFF); command[5] = LSB_of(fromaddress & 0xFFFF);
command[6] = 0;
command[7] = 0;
command[8] = 0;
command[9] = 0;
command[10] = MSB_of(nr_of_pages); command[10] = MSB_of(nr_of_pages);
command[11] = LSB_of(nr_of_pages); command[11] = LSB_of(nr_of_pages);
result = sddr09_send_scsi_command(us, command, sizeof(command)); result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
...@@ -458,17 +465,18 @@ sddr09_read23(struct us_data *us, unsigned long fromaddress, ...@@ -458,17 +465,18 @@ sddr09_read23(struct us_data *us, unsigned long fromaddress,
*/ */
static int static int
sddr09_erase(struct us_data *us, unsigned long Eaddress) { sddr09_erase(struct us_data *us, unsigned long Eaddress) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xea, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int result; int result;
memset(command, 0, 12);
command[0] = 0xEA;
command[1] = LUNBITS;
command[6] = MSB_of(Eaddress>>16); command[6] = MSB_of(Eaddress>>16);
command[7] = LSB_of(Eaddress>>16); command[7] = LSB_of(Eaddress>>16);
command[8] = MSB_of(Eaddress & 0xFFFF); command[8] = MSB_of(Eaddress & 0xFFFF);
command[9] = LSB_of(Eaddress & 0xFFFF); command[9] = LSB_of(Eaddress & 0xFFFF);
result = sddr09_send_scsi_command(us, command, sizeof(command)); result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
US_DEBUGP("Result for send_control in sddr09_erase %d\n", US_DEBUGP("Result for send_control in sddr09_erase %d\n",
...@@ -493,11 +501,12 @@ sddr09_writeX(struct us_data *us, ...@@ -493,11 +501,12 @@ sddr09_writeX(struct us_data *us,
unsigned long Waddress, unsigned long Eaddress, unsigned long Waddress, unsigned long Eaddress,
int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) { int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xe9, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int result; int result;
command[0] = 0xE9;
command[1] = LUNBITS;
command[2] = MSB_of(Waddress>>16); command[2] = MSB_of(Waddress>>16);
command[3] = LSB_of(Waddress>>16); command[3] = LSB_of(Waddress>>16);
command[4] = MSB_of(Waddress & 0xFFFF); command[4] = MSB_of(Waddress & 0xFFFF);
...@@ -511,7 +520,7 @@ sddr09_writeX(struct us_data *us, ...@@ -511,7 +520,7 @@ sddr09_writeX(struct us_data *us,
command[10] = MSB_of(nr_of_pages); command[10] = MSB_of(nr_of_pages);
command[11] = LSB_of(nr_of_pages); command[11] = LSB_of(nr_of_pages);
result = sddr09_send_scsi_command(us, command, sizeof(command)); result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
US_DEBUGP("Result for send_control in sddr09_writeX %d\n", US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
...@@ -554,15 +563,15 @@ sddr09_write_inplace(struct us_data *us, unsigned long address, ...@@ -554,15 +563,15 @@ sddr09_write_inplace(struct us_data *us, unsigned long address,
*/ */
static int static int
sddr09_read_sg_test_only(struct us_data *us) { sddr09_read_sg_test_only(struct us_data *us) {
unsigned char command[15] = { unsigned char *command = us->iobuf;
0xe7, LUNBITS, 0
};
int result, bulklen, nsg, ct; int result, bulklen, nsg, ct;
unsigned char *buf; unsigned char *buf;
unsigned long address; unsigned long address;
nsg = bulklen = 0; nsg = bulklen = 0;
command[0] = 0xE7;
command[1] = LUNBITS;
command[2] = 0;
address = 040000; ct = 1; address = 040000; ct = 1;
nsg++; nsg++;
bulklen += (ct << 9); bulklen += (ct << 9);
...@@ -628,20 +637,22 @@ sddr09_read_sg_test_only(struct us_data *us) { ...@@ -628,20 +637,22 @@ sddr09_read_sg_test_only(struct us_data *us) {
static int static int
sddr09_read_status(struct us_data *us, unsigned char *status) { sddr09_read_status(struct us_data *us, unsigned char *status) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xec, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 unsigned char *data = us->iobuf;
};
unsigned char data[64];
int result; int result;
US_DEBUGP("Reading status...\n"); US_DEBUGP("Reading status...\n");
result = sddr09_send_scsi_command(us, command, sizeof(command)); memset(command, 0, 12);
command[0] = 0xEC;
command[1] = LUNBITS;
result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
return result; return result;
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, sizeof(data), NULL); data, 64, NULL);
*status = data[0]; *status = data[0];
return (result == USB_STOR_XFER_GOOD ? return (result == USB_STOR_XFER_GOOD ?
USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
...@@ -953,13 +964,15 @@ sddr09_read_control(struct us_data *us, ...@@ -953,13 +964,15 @@ sddr09_read_control(struct us_data *us,
*/ */
static int static int
sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xed, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 unsigned char *content = us->iobuf;
};
unsigned char content[64];
int result, i; int result, i;
result = sddr09_send_scsi_command(us, command, sizeof(command)); memset(command, 0, 12);
command[0] = 0xED;
command[1] = LUNBITS;
result = sddr09_send_scsi_command(us, command, 12);
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
return result; return result;
...@@ -1006,11 +1019,13 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) { ...@@ -1006,11 +1019,13 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
static int static int
sddr09_reset(struct us_data *us) { sddr09_reset(struct us_data *us) {
unsigned char command[12] = { unsigned char *command = us->iobuf;
0xeb, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; memset(command, 0, 12);
command[0] = 0xEB;
command[1] = LUNBITS;
return sddr09_send_scsi_command(us, command, sizeof(command)); return sddr09_send_scsi_command(us, command, 12);
} }
#endif #endif
...@@ -1313,7 +1328,7 @@ sddr09_init_card_info(struct us_data *us) { ...@@ -1313,7 +1328,7 @@ sddr09_init_card_info(struct us_data *us) {
int int
sddr09_init(struct us_data *us) { sddr09_init(struct us_data *us) {
int result; int result;
unsigned char data[18]; unsigned char *data = us->iobuf;
result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
...@@ -1333,10 +1348,10 @@ sddr09_init(struct us_data *us) { ...@@ -1333,10 +1348,10 @@ sddr09_init(struct us_data *us) {
US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
// get 07 00 // get 07 00
result = sddr09_request_sense(us, data, sizeof(data)); result = sddr09_request_sense(us, data, 18);
if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) { if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {
int j; int j;
for (j=0; j<sizeof(data); j++) for (j=0; j<18; j++)
printk(" %02X", data[j]); printk(" %02X", data[j]);
printk("\n"); printk("\n");
// get 70 00 00 00 00 00 00 * 00 00 00 00 00 00 // get 70 00 00 00 00 00 00 * 00 00 00 00 00 00
......
...@@ -91,13 +91,14 @@ sddr55_bulk_transport(struct us_data *us, int direction, ...@@ -91,13 +91,14 @@ sddr55_bulk_transport(struct us_data *us, int direction,
static int sddr55_status(struct us_data *us) static int sddr55_status(struct us_data *us)
{ {
int result; int result;
unsigned char command[8] = { unsigned char *command = us->iobuf;
0, 0, 0, 0, 0, 0xb0, 0, 0x80 unsigned char *status = us->iobuf;
};
unsigned char status[8];
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
/* send command */ /* send command */
memset(command, 0, 8);
command[5] = 0xB0;
command[7] = 0x80;
result = sddr55_bulk_transport(us, result = sddr55_bulk_transport(us,
SCSI_DATA_WRITE, command, 8); SCSI_DATA_WRITE, command, 8);
...@@ -158,10 +159,8 @@ static int sddr55_read_data(struct us_data *us, ...@@ -158,10 +159,8 @@ static int sddr55_read_data(struct us_data *us,
int use_sg) { int use_sg) {
int result = USB_STOR_TRANSPORT_GOOD; int result = USB_STOR_TRANSPORT_GOOD;
unsigned char command[8] = { unsigned char *command = us->iobuf;
0, 0, 0, 0, 0, 0xb0, 0, 0x85 unsigned char *status = us->iobuf;
};
unsigned char status[8];
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
unsigned int pba; unsigned int pba;
...@@ -205,11 +204,15 @@ static int sddr55_read_data(struct us_data *us, ...@@ -205,11 +204,15 @@ static int sddr55_read_data(struct us_data *us,
address = (pba << info->blockshift) + page; address = (pba << info->blockshift) + page;
command[0] = 0;
command[1] = LSB_of(address>>16); command[1] = LSB_of(address>>16);
command[2] = LSB_of(address>>8); command[2] = LSB_of(address>>8);
command[3] = LSB_of(address); command[3] = LSB_of(address);
command[4] = 0;
command[5] = 0xB0;
command[6] = LSB_of(pages << (1 - info->smallpageshift)); command[6] = LSB_of(pages << (1 - info->smallpageshift));
command[7] = 0x85;
/* send command */ /* send command */
result = sddr55_bulk_transport(us, result = sddr55_bulk_transport(us,
...@@ -274,10 +277,8 @@ static int sddr55_write_data(struct us_data *us, ...@@ -274,10 +277,8 @@ static int sddr55_write_data(struct us_data *us,
int use_sg) { int use_sg) {
int result = USB_STOR_TRANSPORT_GOOD; int result = USB_STOR_TRANSPORT_GOOD;
unsigned char command[8] = { unsigned char *command = us->iobuf;
0, 0, 0, 0, 0, 0xb0, 0, 0x86 unsigned char *status = us->iobuf;
};
unsigned char status[8];
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
unsigned int pba; unsigned int pba;
...@@ -380,6 +381,8 @@ static int sddr55_write_data(struct us_data *us, ...@@ -380,6 +381,8 @@ static int sddr55_write_data(struct us_data *us,
command[6] = MSB_of(lba % 1000); command[6] = MSB_of(lba % 1000);
command[4] |= LSB_of(pages >> info->smallpageshift); command[4] |= LSB_of(pages >> info->smallpageshift);
command[5] = 0xB0;
command[7] = 0x86;
/* send command */ /* send command */
result = sddr55_bulk_transport(us, result = sddr55_bulk_transport(us,
...@@ -473,11 +476,12 @@ static int sddr55_read_deviceID(struct us_data *us, ...@@ -473,11 +476,12 @@ static int sddr55_read_deviceID(struct us_data *us,
unsigned char *deviceID) { unsigned char *deviceID) {
int result; int result;
unsigned char command[8] = { unsigned char *command = us->iobuf;
0, 0, 0, 0, 0, 0xb0, 0, 0x84 unsigned char *content = us->iobuf;
};
unsigned char content[64];
memset(command, 0, 8);
command[5] = 0xB0;
command[7] = 0x84;
result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
US_DEBUGP("Result of send_control for device ID is %d\n", US_DEBUGP("Result of send_control for device ID is %d\n",
...@@ -598,7 +602,7 @@ static int sddr55_read_map(struct us_data *us) { ...@@ -598,7 +602,7 @@ static int sddr55_read_map(struct us_data *us) {
struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra);
int numblocks; int numblocks;
unsigned char *buffer; unsigned char *buffer;
unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x8a}; unsigned char *command = us->iobuf;
int i; int i;
unsigned short lba; unsigned short lba;
unsigned short max_lba; unsigned short max_lba;
...@@ -614,7 +618,10 @@ static int sddr55_read_map(struct us_data *us) { ...@@ -614,7 +618,10 @@ static int sddr55_read_map(struct us_data *us) {
if (!buffer) if (!buffer)
return -1; return -1;
memset(command, 0, 8);
command[5] = 0xB0;
command[6] = numblocks * 2 / 256; command[6] = numblocks * 2 / 256;
command[7] = 0x8A;
result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
......
...@@ -119,7 +119,7 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, ...@@ -119,7 +119,7 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110,
UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210,
"Fujifilm", "Fujifilm",
"FinePix 1400Zoom", "FinePix 1400Zoom",
US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY), US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de> /* Reported by Peter Wchtler <pwaechtler@loewe-komp.de>
* The device needs the flags only. * The device needs the flags only.
...@@ -236,7 +236,7 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, ...@@ -236,7 +236,7 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony", "Sony",
"DSC-S30/S70/S75/505V/F505/F707/F717/P8", "DSC-S30/S70/S75/505V/F505/F707/F717/P8",
US_SC_SCSI, US_PR_CB, NULL, US_SC_SCSI, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
/* Reported by wim@geeks.nl */ /* Reported by wim@geeks.nl */
...@@ -555,7 +555,7 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, ...@@ -555,7 +555,7 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999, UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
"AIPTEK", "AIPTEK",
"PocketCAM 3Mega", "PocketCAM 3Mega",
US_SC_SCSI, US_PR_BULK, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MODE_XLATE ), US_FL_MODE_XLATE ),
/* aeb */ /* aeb */
......
...@@ -69,11 +69,10 @@ struct us_unusual_dev { ...@@ -69,11 +69,10 @@ struct us_unusual_dev {
/* Flag definitions: these entries are static */ /* Flag definitions: these entries are static */
#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for #define US_FL_MODE_XLATE 0 /* [no longer used] */
Win/MacOS compatibility */
#define US_FL_IGNORE_SER 0 /* [no longer used] */ #define US_FL_IGNORE_SER 0 /* [no longer used] */
#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
/* Dynamic flag definitions: used in set_bit() etc. */ /* Dynamic flag definitions: used in set_bit() etc. */
......
...@@ -507,7 +507,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -507,7 +507,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
size_t buffer_size; size_t buffer_size;
int i; int i;
int retval; int retval = -ENOMEM;
/* See if the device offered us matches what we can accept */ /* See if the device offered us matches what we can accept */
if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) || if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
...@@ -515,18 +515,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -515,18 +515,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
return -ENODEV; return -ENODEV;
} }
retval = usb_register_dev (interface, &skel_class);
if (retval) {
/* something prevented us from registering this driver */
err ("Not able to get a minor for this device.");
goto exit;
}
/* allocate memory for our device state and initialize it */ /* allocate memory for our device state and initialize it */
dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL); dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
if (dev == NULL) { if (dev == NULL) {
err ("Out of memory"); err ("Out of memory");
goto exit_minor; goto error;
} }
memset (dev, 0x00, sizeof (*dev)); memset (dev, 0x00, sizeof (*dev));
...@@ -603,24 +596,24 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -603,24 +596,24 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
/* allow device read, write and ioctl */ /* allow device read, write and ioctl */
dev->present = 1; dev->present = 1;
/* we can register the device now, as it is ready */
usb_set_intfdata (interface, dev);
retval = usb_register_dev (interface, &skel_class);
if (retval) {
/* something prevented us from registering this driver */
err ("Not able to get a minor for this device.");
usb_set_intfdata (interface, NULL);
goto error;
}
/* let the user know what node this device is now attached to */ /* let the user know what node this device is now attached to */
info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
return 0;
goto exit;
error: error:
skel_delete (dev); skel_delete (dev);
dev = NULL; return retval;
exit_minor:
usb_deregister_dev (interface, &skel_class);
exit:
if (dev) {
usb_set_intfdata (interface, dev);
return 0;
}
return -ENODEV;
} }
......
...@@ -80,7 +80,8 @@ struct usb_host_interface { ...@@ -80,7 +80,8 @@ struct usb_host_interface {
* @act_altsetting: index of current altsetting. this number is always * @act_altsetting: index of current altsetting. this number is always
* less than num_altsetting. after the device is configured, each * less than num_altsetting. after the device is configured, each
* interface uses its default setting of zero. * interface uses its default setting of zero.
* @max_altsetting: * @max_altsetting: the max number of altsettings for this interface.
* @driver: the USB driver that is bound to this interface.
* @minor: the minor number assigned to this interface, if this * @minor: the minor number assigned to this interface, if this
* interface is bound to a driver that uses the USB major number. * interface is bound to a driver that uses the USB major number.
* If this interface does not use the USB major, this field should * If this interface does not use the USB major, this field should
...@@ -409,7 +410,11 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) ...@@ -409,7 +410,11 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
* do (or don't) show up otherwise in the filesystem. * do (or don't) show up otherwise in the filesystem.
* @id_table: USB drivers use ID table to support hotplugging. * @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
* or your driver's probe function will never get called. * or your driver's probe function will never get called.
* @driver: the driver model core driver structure.
* @serialize: a semaphore used to serialize access to this driver. Used
* in the probe and disconnect functions. Only the USB core should use
* this lock.
* *
* USB drivers must provide a name, probe() and disconnect() methods, * USB drivers must provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional. * and an id_table. Other driver fields are optional.
...@@ -575,6 +580,8 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); ...@@ -575,6 +580,8 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
* it likes with the URB, including resubmitting or freeing it. * it likes with the URB, including resubmitting or freeing it.
* @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
* collect the transfer status for each buffer. * collect the transfer status for each buffer.
* @timeout: If set to zero, the urb will never timeout. Otherwise this is
* the time in jiffies that this urb will timeout in.
* *
* This structure identifies USB transfer requests. URBs must be allocated by * This structure identifies USB transfer requests. URBs must be allocated by
* calling usb_alloc_urb() and freed with a call to usb_free_urb(). * calling usb_alloc_urb() and freed with a call to usb_free_urb().
...@@ -677,10 +684,14 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); ...@@ -677,10 +684,14 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
*/ */
struct urb struct urb
{ {
/* private, usb core and host controller only fields in the urb */
spinlock_t lock; /* lock for the URB */ spinlock_t lock; /* lock for the URB */
atomic_t count; /* reference count of the URB */ atomic_t count; /* reference count of the URB */
void *hcpriv; /* private data for host controller */ void *hcpriv; /* private data for host controller */
struct list_head urb_list; /* list pointer to all active urbs */ struct list_head urb_list; /* list pointer to all active urbs */
int bandwidth; /* bandwidth for INT/ISO request */
/* public, documented fields in the urb that can be used by drivers */
struct usb_device *dev; /* (in) pointer to associated device */ struct usb_device *dev; /* (in) pointer to associated device */
unsigned int pipe; /* (in) pipe information */ unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */ int status; /* (return) non-ISO status */
...@@ -689,7 +700,6 @@ struct urb ...@@ -689,7 +700,6 @@ struct urb
dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
int transfer_buffer_length; /* (in) data buffer length */ int transfer_buffer_length; /* (in) data buffer length */
int actual_length; /* (return) actual transfer length */ int actual_length; /* (return) actual transfer length */
int bandwidth; /* bandwidth for INT/ISO request */
unsigned char *setup_packet; /* (in) setup packet (control only) */ unsigned char *setup_packet; /* (in) setup packet (control only) */
dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */
int start_frame; /* (modify) start frame (INT/ISO) */ int start_frame; /* (modify) start frame (INT/ISO) */
...@@ -891,8 +901,10 @@ struct usb_sg_request { ...@@ -891,8 +901,10 @@ struct usb_sg_request {
int status; int status;
size_t bytes; size_t bytes;
// members not documented above are private to usbcore, /*
// and are not provided for driver access! * members below are private to usbcore,
* and are not provided for driver access!
*/
spinlock_t lock; spinlock_t lock;
struct usb_device *dev; struct usb_device *dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment