summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2002-10-13 02:00:40 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2002-10-13 02:00:40 -0700
commit31c96625109bb9deb166cfd3fbe08d0a92ad98fa (patch)
treee92290f60c8e083ec83b9968b54f2a4762c66c47
parente0970dce2a44f75f560b1a9a48a33c7828e191cc (diff)
parent321d6a826727fac90daa8cf21c4c9d973400750d (diff)
Merge kroah.com:/home/linux/linux/BK/bleeding-2.5
into kroah.com:/home/linux/linux/BK/gregkh-2.5
-rw-r--r--MAINTAINERS5
-rw-r--r--drivers/char/Config.help21
-rw-r--r--drivers/char/Config.in1
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/tipar.c541
-rw-r--r--drivers/usb/core/hcd-pci.c3
-rw-r--r--drivers/usb/core/hub.c12
-rw-r--r--drivers/usb/core/inode.c33
-rw-r--r--drivers/usb/core/message.c30
-rw-r--r--drivers/usb/core/urb.c2
-rw-r--r--drivers/usb/core/usb.c37
-rw-r--r--drivers/usb/host/ehci-hcd.c3
-rw-r--r--drivers/usb/host/hc_sl811.c3
-rw-r--r--drivers/usb/host/ohci-pci.c3
-rw-r--r--drivers/usb/host/ohci-sa1111.c5
-rw-r--r--drivers/usb/host/uhci-hcd.c3
-rw-r--r--drivers/usb/input/wacom.c1
-rw-r--r--drivers/usb/media/Makefile2
-rw-r--r--drivers/usb/media/vicam.c1894
-rw-r--r--drivers/usb/media/vicam.h81
-rw-r--r--drivers/usb/media/vicamurbs.h332
-rw-r--r--drivers/usb/net/usbnet.c2
-rw-r--r--drivers/usb/serial/io_ti.c76
-rw-r--r--drivers/usb/serial/usb-serial.c26
-rw-r--r--drivers/usb/serial/visor.c2
-rw-r--r--drivers/usb/serial/whiteheat.c18
-rw-r--r--drivers/usb/storage/datafab.c11
-rw-r--r--drivers/usb/storage/freecom.c90
-rw-r--r--drivers/usb/storage/initializers.c2
-rw-r--r--drivers/usb/storage/isd200.c42
-rw-r--r--drivers/usb/storage/jumpshot.c34
-rw-r--r--drivers/usb/storage/raw_bulk.c213
-rw-r--r--drivers/usb/storage/raw_bulk.h15
-rw-r--r--drivers/usb/storage/sddr09.c50
-rw-r--r--drivers/usb/storage/sddr55.c10
-rw-r--r--drivers/usb/storage/shuttle_usbat.c254
-rw-r--r--drivers/usb/storage/transport.c280
-rw-r--r--drivers/usb/storage/transport.h24
-rw-r--r--drivers/usb/storage/usb.c6
-rw-r--r--drivers/usb/storage/usb.h4
-rw-r--r--include/linux/usb.h37
-rw-r--r--include/linux/videodev.h1
42 files changed, 2363 insertions, 1847 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 23c9f7b02d97..a9b191413d74 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1592,6 +1592,11 @@ P: Julien Blache
M: jb@technologeek.org
S: Maintained
+TI PARALLEL LINK CABLE DRIVER
+P: Romain Lievin
+M: roms@lpg.ticalc.org
+S: Maintained
+
TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
P: Stephane Dalton
M: sdalton@videotron.ca
diff --git a/drivers/char/Config.help b/drivers/char/Config.help
index acc31b2a2416..b03cd9da93b0 100644
--- a/drivers/char/Config.help
+++ b/drivers/char/Config.help
@@ -1033,3 +1033,24 @@ CONFIG_SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.o.
+Texas Instruments parallel link cable support
+CONFIG_TIPAR
+ If you own a Texas Instruments graphing calculator and use a
+ parallel link cable, then you might be interested in this driver.
+
+ If you enable this driver, you will be able to communicate with
+ your calculator through a set of device nodes under /dev. The
+ main advantage of this driver is that you don't have to be root
+ to use this precise link cable (depending on the permissions on
+ the device nodes, though).
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tipar.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
+ If you don't know what a parallel link cable is or what a Texas
+ Instruments graphing calculator is, then you probably don't need this
+ driver.
+
+ If unsure, say N. \ No newline at end of file
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index 680bafe4ca4a..84eec6579e76 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -80,6 +80,7 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
bool ' Support for console on line printer' CONFIG_LP_CONSOLE
fi
dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
+ dep_tristate 'Texas Instruments parallel link cable support' CONFIG_TIPAR $CONFIG_PARPORT
fi
if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 80a28ced908c..d0be4dd0e8cb 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_PRINTER) += lp.o
+obj-$(CONFIG_TIPAR) += tipar.o
obj-$(CONFIG_BUSMOUSE) += busmouse.o
obj-$(CONFIG_DTLK) += dtlk.o
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
new file mode 100644
index 000000000000..16adba7c4148
--- /dev/null
+++ b/drivers/char/tipar.c
@@ -0,0 +1,541 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar - low level driver for handling a parallel link cable designed
+ * for Texas Instruments graphing calculators (http://lpg.ticalc.org).
+ * A part of the TiLP project.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ *
+ * Various fixes & clean-up from the Linux Kernel Mailing List
+ * (Alan Cox, Richard B. Johnson, Christoph Hellwig).
+ */
+
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.
+ *
+ * If this driver is built into the kernel, you can configure it using the
+ * kernel command-line. For example:
+ *
+ * tipar=timeout,delay (set timeout and delay)
+ *
+ * If the driver is loaded as a module, similar functionality is available
+ * using module parameters. The equivalent of the above commands would be:
+ *
+ * # insmod tipar timeout=15 delay=10
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Usually, parallel cables were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ * tipar0 0x378
+ * tipar1 0x278
+ * tipar2 0x3bc
+ *
+ *
+ * This driver, by default, binds tipar devices according to parport and
+ * the minor number.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <linux/devfs_fs_kernel.h> /* DevFs support */
+#include <linux/parport.h> /* Our code depend on parport */
+
+/*
+ * TI definitions
+ */
+#include <linux/ticable.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.17"
+#define DRIVER_AUTHOR "Romain Lievin <roms@lpg.ticalc.org>"
+#define DRIVER_DESC "Device driver for TI/PC parallel link cables"
+#define DRIVER_LICENSE "GPL"
+
+#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
+#if LINUX_VERSION_CODE < VERSION(2,5,0)
+# define minor(x) MINOR(x)
+# define need_resched() (current->need_resched)
+#endif
+
+/* ----- global variables --------------------------------------------- */
+
+struct tipar_struct {
+ struct pardevice *dev; /* Parport device entry */
+};
+
+#define PP_NO 3
+static struct tipar_struct table[PP_NO];
+
+static int delay = IO_DELAY; /* inter-bit delay in microseconds */
+static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
+
+static devfs_handle_t devfs_handle;
+static unsigned int tp_count; /* tipar count */
+static unsigned long opened; /* opened devices */
+
+/* --- macros for parport access -------------------------------------- */
+
+#define r_dtr(x) (parport_read_data(table[(x)].dev->port))
+#define r_str(x) (parport_read_status(table[(x)].dev->port))
+#define w_ctr(x,y) (parport_write_control(table[(x)].dev->port, (y)))
+#define w_dtr(x,y) (parport_write_data(table[(x)].dev->port, (y)))
+
+/* --- setting states on the D-bus with the right timing: ------------- */
+
+static inline void
+outbyte(int value, int minor)
+{
+ w_dtr(minor, value);
+}
+
+static inline int
+inbyte(int minor)
+{
+ return (r_str(minor));
+}
+
+static inline void
+init_ti_parallel(int minor)
+{
+ outbyte(3, minor);
+}
+
+/* ----- global defines ----------------------------------------------- */
+
+#define START(x) { x=jiffies+HZ/(timeout/10); }
+#define WAIT(x) { \
+ if (time_before((x), jiffies)) return -1; \
+ if (need_resched()) schedule(); }
+
+/* ----- D-bus bit-banging functions ---------------------------------- */
+
+/* D-bus protocol (45kbit/s max):
+ 1 0 0
+ _______ ______|______ __________|________ __________
+Red : ________ | ____ | ____
+ _ ____________|________ ______|__________ _____
+White: ________ | ______ | _______
+*/
+
+/* Try to transmit a byte on the specified port (-1 if error). */
+static int
+put_ti_parallel(int minor, unsigned char data)
+{
+ int bit;
+ unsigned long max;
+
+ for (bit = 0; bit < 8; bit++) {
+ if (data & 1) {
+ outbyte(2, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (inbyte(minor) & 0x10);
+
+ outbyte(3, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (!(inbyte(minor) & 0x10));
+ } else {
+ outbyte(1, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (inbyte(minor) & 0x20);
+
+ outbyte(3, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (!(inbyte(minor) & 0x20));
+ }
+
+ data >>= 1;
+ udelay(delay);
+
+ if (need_resched())
+ schedule();
+ }
+
+ return 0;
+}
+
+/* Receive a byte on the specified port or -1 if error. */
+static int
+get_ti_parallel(int minor)
+{
+ int bit;
+ unsigned char v, data = 0;
+ unsigned long max;
+
+ for (bit = 0; bit < 8; bit++) {
+ START(max);
+ do {
+ WAIT(max);
+ } while ((v = inbyte(minor) & 0x30) == 0x30);
+
+ if (v == 0x10) {
+ data = (data >> 1) | 0x80;
+ outbyte(1, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (!(inbyte(minor) & 0x20));
+ outbyte(3, minor);
+ } else {
+ data = data >> 1;
+ outbyte(2, minor);
+ START(max);
+ do {
+ WAIT(max);
+ } while (!(inbyte(minor) & 0x10));
+ outbyte(3, minor);
+ }
+
+ udelay(delay);
+ if (need_resched())
+ schedule();
+ }
+
+ return (int) data;
+}
+
+/* Try to detect a parallel link cable on the specified port */
+static int
+probe_ti_parallel(int minor)
+{
+ int i;
+ int seq[] = { 0x00, 0x20, 0x10, 0x30 };
+
+ for (i = 3; i >= 0; i--) {
+ outbyte(3, minor);
+ outbyte(i, minor);
+ udelay(delay);
+ /*printk(KERN_DEBUG "Probing -> %i: 0x%02x 0x%02x\n", i, data & 0x30, seq[i]); */
+ if ((inbyte(minor) & 0x30) != seq[i]) {
+ outbyte(3, minor);
+ return -1;
+ }
+ }
+
+ outbyte(3, minor);
+ return 0;
+}
+
+/* ----- kernel module functions--------------------------------------- */
+
+static int
+tipar_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR;
+
+ if (minor > tp_count - 1)
+ return -ENXIO;
+
+ if (test_and_set_bit(minor, &opened))
+ return -EBUSY;
+
+ parport_claim_or_block(table[minor].dev);
+ init_ti_parallel(minor);
+ parport_release(table[minor].dev);
+
+ return 0;
+}
+
+static int
+tipar_close(struct inode *inode, struct file *file)
+{
+ unsigned int minor = minor(inode->i_rdev) - TIPAR_MINOR;
+
+ if (minor > tp_count - 1)
+ return -ENXIO;
+
+ clear_bit(minor, &opened);
+
+ return 0;
+}
+
+static ssize_t
+tipar_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+{
+ unsigned int minor =
+ minor(file->f_dentry->d_inode->i_rdev) - TIPAR_MINOR;
+ ssize_t n;
+
+ printk("_write\n");
+ parport_claim_or_block(table[minor].dev);
+
+ for (n = 0; n < count; n++) {
+ unsigned char b;
+
+ if (get_user(b, buf + n)) {
+ n = -EFAULT;
+ goto out;
+ }
+
+ if (put_ti_parallel(minor, b) == -1) {
+ init_ti_parallel(minor);
+ n = -ETIMEDOUT;
+ goto out;
+ }
+ }
+ out:
+ parport_release(table[minor].dev);
+ return n;
+}
+
+static ssize_t
+tipar_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+ int b = 0;
+ unsigned int minor =
+ minor(file->f_dentry->d_inode->i_rdev) - TIPAR_MINOR;
+ ssize_t retval = 0;
+ ssize_t n = 0;
+
+ if (count == 0)
+ return 0;
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ printk("_read\n");
+ parport_claim_or_block(table[minor].dev);
+
+ while (n < count) {
+ b = get_ti_parallel(minor);
+ if (b == -1) {
+ init_ti_parallel(minor);
+ retval = -ETIMEDOUT;
+ goto out;
+ } else {
+ if (put_user(b, ((unsigned char *) buf) + n)) {
+ retval = -EFAULT;
+ break;
+ } else
+ retval = ++n;
+ }
+
+ /* Non-blocking mode : try again ! */
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto out;
+ }
+
+ /* Signal pending, try again ! */
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ goto out;
+ }
+
+ if (need_resched())
+ schedule();
+ }
+
+ out:
+ parport_release(table[minor].dev);
+ return retval;
+}
+
+static int
+tipar_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ switch (cmd) {
+ case IOCTL_TIPAR_DELAY:
+ delay = (int)arg; //get_user(delay, &arg);
+ break;
+ case IOCTL_TIPAR_TIMEOUT:
+ timeout = (int)arg; //get_user(timeout, &arg);
+ break;
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+
+ return retval;
+}
+
+/* ----- kernel module registering ------------------------------------ */
+
+static struct file_operations tipar_fops = {
+ owner:THIS_MODULE,
+ llseek:no_llseek,
+ read:tipar_read,
+ write:tipar_write,
+ ioctl:tipar_ioctl,
+ open:tipar_open,
+ release:tipar_close,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/* You must set these - there is no sane way to probe for this cable.
+ * You can use 'tipar=timeout,delay' to set these now. */
+static int __init
+tipar_setup(char *str)
+{
+ int ints[2];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
+ if (ints[0] > 0) {
+ timeout = ints[1];
+ if (ints[0] > 1) {
+ delay = ints[2];
+ }
+ }
+
+ return 1;
+}
+#endif
+
+/*
+ * Register our module into parport.
+ * Pass also 2 callbacks functions to parport: a pre-emptive function and an
+ * interrupt handler function (unused).
+ * Display a message such "tipar0: using parport0 (polling)".
+ */
+static int
+tipar_register(int nr, struct parport *port)
+{
+ char name[8];
+
+ /* Register our module into parport */
+ table[nr].dev = parport_register_device(port, "tipar",
+ NULL, NULL, NULL, 0,
+ (void *) &table[nr]);
+
+ if (table[nr].dev == NULL)
+ return 1;
+
+ /* Use devfs, tree: /dev/ticables/par/[0..2] */
+ sprintf(name, "%d", nr);
+ printk
+ ("tipar: registering to devfs : major = %d, minor = %d, node = %s\n",
+ TISER_MAJOR, (TIPAR_MINOR + nr), name);
+ devfs_register(devfs_handle, name, DEVFS_FL_DEFAULT, TIPAR_MAJOR,
+ TIPAR_MINOR + nr, S_IFCHR | S_IRUGO | S_IWUGO,
+ &tipar_fops, NULL);
+
+ /* Display informations */
+ printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
+ (port->irq ==
+ PARPORT_IRQ_NONE) ? "polling" : "interrupt-driven");
+
+ if (probe_ti_parallel(nr) != -1)
+ printk("tipar%d: link cable found !\n", nr);
+ else
+ printk("tipar%d: link cable not found.\n", nr);
+
+ return 0;
+}
+
+static void
+tipar_attach(struct parport *port)
+{
+ if (tp_count == PP_NO) {
+ printk("tipar: ignoring parallel port (max. %d)\n", PP_NO);
+ return;
+ }
+
+ if (!tipar_register(tp_count, port))
+ tp_count++;
+}
+
+static void
+tipar_detach(struct parport *port)
+{
+ /* Nothing to do */
+}
+
+static struct parport_driver tipar_driver = {
+ "tipar",
+ tipar_attach,
+ tipar_detach,
+ NULL
+};
+
+int __init
+tipar_init_module(void)
+{
+ printk("tipar: parallel link cable driver, version %s\n",
+ DRIVER_VERSION);
+
+ if (register_chrdev(TIPAR_MAJOR, "tipar", &tipar_fops)) {
+ printk("tipar: unable to get major %d\n", TIPAR_MAJOR);
+ return -EIO;
+ }
+
+ /* Use devfs with tree: /dev/ticables/par/[0..2] */
+ devfs_handle = devfs_mk_dir(NULL, "ticables/par", NULL);
+
+ if (parport_register_driver(&tipar_driver)) {
+ printk("tipar: unable to register with parport\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+void __exit
+tipar_cleanup_module(void)
+{
+ unsigned int i;
+
+ /* Unregistering module */
+ parport_unregister_driver(&tipar_driver);
+
+ devfs_unregister(devfs_handle);
+ unregister_chrdev(TIPAR_MAJOR, "tipar");
+
+ for (i = 0; i < PP_NO; i++) {
+ if (table[i].dev == NULL)
+ continue;
+ parport_unregister_device(table[i].dev);
+ }
+
+ printk("tipar: module unloaded !\n");
+}
+
+/* --------------------------------------------------------------------- */
+
+__setup("tipar=", tipar_setup);
+module_init(tipar_init_module);
+module_exit(tipar_cleanup_module);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)");
+MODULE_PARM(delay, "i");
+MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)");
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 5ef04cef469e..142115d509b1 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -62,6 +62,9 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
int retval, region;
char buf [8], *bufp = buf;
+ if (usb_disabled())
+ return -ENODEV;
+
if (!id || !(driver = (struct hc_driver *) id->driver_data))
return -EINVAL;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 204cf874c8e6..e12b720f0145 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -943,7 +943,9 @@ static void usb_hub_events(void)
list_del_init(tmp);
- down(&hub->khubd_sem); /* never blocks, we were on list */
+ if (unlikely(down_trylock(&hub->khubd_sem)))
+ BUG(); /* never blocks, we were on list */
+
spin_unlock_irqrestore(&hub_event_lock, flags);
if (hub->error) {
@@ -1067,10 +1069,10 @@ static int usb_hub_thread(void *__hub)
}
static struct usb_device_id hub_id_table [] = {
- { match_flags: USB_DEVICE_ID_MATCH_DEV_CLASS,
- bDeviceClass: USB_CLASS_HUB},
- { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
- bInterfaceClass: USB_CLASS_HUB},
+ { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
+ .bDeviceClass = USB_CLASS_HUB},
+ { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
+ .bInterfaceClass = USB_CLASS_HUB},
{ } /* Terminating entry */
};
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 96575bb2b465..9c35f4a3698f 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -45,7 +45,8 @@ static struct inode_operations usbfs_dir_inode_operations;
static struct vfsmount *usbdevfs_mount;
static struct vfsmount *usbfs_mount;
static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
-static int mount_count; /* = 0 */
+static int usbdevfs_mount_count; /* = 0 */
+static int usbfs_mount_count; /* = 0 */
static struct dentry *devices_usbdevfs_dentry;
static struct dentry *devices_usbfs_dentry;
@@ -507,14 +508,14 @@ static struct file_system_type usb_fs_type = {
};
/* --------------------------------------------------------------------- */
-static int get_mount (struct file_system_type *fs_type, struct vfsmount **mount)
+static int get_mount (struct file_system_type *fs_type, struct vfsmount **mount, int *mount_count)
{
struct vfsmount *mnt;
spin_lock (&mount_lock);
if (*mount) {
mntget(*mount);
- ++mount_count;
+ ++(*mount_count);
spin_unlock (&mount_lock);
goto go_ahead;
}
@@ -528,33 +529,33 @@ static int get_mount (struct file_system_type *fs_type, struct vfsmount **mount)
spin_lock (&mount_lock);
if (!*mount) {
*mount = mnt;
- ++mount_count;
+ ++(*mount_count);
spin_unlock (&mount_lock);
goto go_ahead;
}
mntget(*mount);
- ++mount_count;
+ ++(*mount_count);
spin_unlock (&mount_lock);
mntput(mnt);
go_ahead:
- dbg("mount_count = %d", mount_count);
+ dbg("mount_count = %d", *mount_count);
return 0;
}
-static void put_mount (struct vfsmount **mount)
+static void put_mount (struct vfsmount **mount, int *mount_count)
{
struct vfsmount *mnt;
spin_lock (&mount_lock);
mnt = *mount;
- --mount_count;
- if (!mount_count)
+ --(*mount_count);
+ if (!(*mount_count))
*mount = NULL;
spin_unlock (&mount_lock);
mntput(mnt);
- dbg("mount_count = %d", mount_count);
+ dbg("mount_count = %d", *mount_count);
}
static int create_special_files (void)
@@ -563,13 +564,13 @@ static int create_special_files (void)
int retval = 0;
/* create the devices special file */
- retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount);
+ retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount, &usbdevfs_mount_count);
if (retval) {
err ("Unable to get usbdevfs mount");
goto exit;
}
- retval = get_mount (&usb_fs_type, &usbfs_mount);
+ retval = get_mount (&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
if (retval) {
err ("Unable to get usbfs mount");
goto error_clean_usbdevfs_mount;
@@ -604,10 +605,10 @@ error_remove_file:
devices_usbfs_dentry = NULL;
error_clean_mounts:
- put_mount (&usbfs_mount);
+ put_mount (&usbfs_mount, &usbfs_mount_count);
error_clean_usbdevfs_mount:
- put_mount (&usbdevfs_mount);
+ put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
exit:
return retval;
@@ -621,8 +622,8 @@ static void remove_special_files (void)
fs_remove_file (devices_usbfs_dentry);
devices_usbdevfs_dentry = NULL;
devices_usbfs_dentry = NULL;
- put_mount (&usbdevfs_mount);
- put_mount (&usbfs_mount);
+ put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
+ put_mount (&usbfs_mount, &usbfs_mount_count);
}
void usbfs_update_special (void)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 17ab912a3f4b..0d1dad8253fc 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -756,6 +756,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
*
* This is used to enable data transfers on interfaces that may not
* be enabled by default. Not all devices support such configurability.
+ * Only the driver bound to an interface may change its setting.
*
* Within any given configuration, each interface may have several
* alternative settings. These are often used to control levels of
@@ -808,6 +809,22 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
interface, NULL, 0, HZ * 5)) < 0)
return ret;
+ /* FIXME drivers shouldn't need to replicate/bugfix the logic here
+ * when they implement async or easily-killable versions of this or
+ * other "should-be-internal" functions (like clear_halt).
+ * should hcd+usbcore postprocess control requests?
+ */
+
+ /* prevent submissions using previous endpoint settings */
+ iface_as = iface->altsetting + iface->act_altsetting;
+ for (i = 0; i < iface_as->bNumEndpoints; i++) {
+ u8 ep = iface_as->endpoint [i].bEndpointAddress;
+ int out = !(ep & USB_DIR_IN);
+
+ ep &= USB_ENDPOINT_NUMBER_MASK;
+ (out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0;
+ // FIXME want hcd hook here, "no such endpoint"
+ }
iface->act_altsetting = alternate;
/* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
@@ -819,21 +836,20 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* any SetInterface request and hence assume toggles need to be reset.
* However, EP0 toggles are re-synced for every individual transfer
* during the SETUP stage - hence EP0 toggles are "don't care" here.
+ * (Likewise, EP0 never "halts" on well designed devices.)
*/
iface_as = &iface->altsetting[alternate];
for (i = 0; i < iface_as->bNumEndpoints; i++) {
u8 ep = iface_as->endpoint[i].bEndpointAddress;
+ int out = !(ep & USB_DIR_IN);
- usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
+ ep &= USB_ENDPOINT_NUMBER_MASK;
+ usb_settoggle (dev, ep, out, 0);
+ (out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep]
+ = iface_as->endpoint [ep].wMaxPacketSize;
}
- /* usb_set_maxpacket() sets the maxpacket size for all EP in all
- * interfaces but it shouldn't do any harm here: we have changed
- * the AS for the requested interface only, hence for unaffected
- * interfaces it's just re-application of still-valid values.
- */
- usb_set_maxpacket(dev);
return 0;
}
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 30a2ba8585b1..aaf31af0a45b 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -272,9 +272,9 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
/* enforce simple/standard policy */
allowed = USB_ASYNC_UNLINK; // affects later unlinks
allowed |= URB_NO_DMA_MAP;
+ allowed |= URB_NO_INTERRUPT;
switch (temp) {
case PIPE_BULK:
- allowed |= URB_NO_INTERRUPT;
if (is_out)
allowed |= USB_ZERO_PACKET;
/* FALLTHROUGH */
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 5b3ec48092ad..556dbacb7c23 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -50,6 +50,9 @@ extern int usb_major_init(void);
extern void usb_major_cleanup(void);
+int nousb; /* Disable USB when built into kernel image */
+ /* Not honored on modular build */
+
static int generic_probe (struct device *dev)
{
@@ -167,6 +170,9 @@ int usb_register(struct usb_driver *new_driver)
{
int retval = 0;
+ if (nousb)
+ return -ENODEV;
+
new_driver->driver.name = (char *)new_driver->name;
new_driver->driver.bus = &usb_bus_type;
new_driver->driver.probe = usb_device_probe;
@@ -1338,11 +1344,37 @@ struct bus_type usb_bus_type = {
.hotplug = usb_hotplug,
};
+#ifndef MODULE
+
+static int __init usb_setup_disable(char *str)
+{
+ nousb = 1;
+ return 1;
+}
+
+/* format to disable USB on kernel command line is: nousb */
+__setup("nousb", usb_setup_disable);
+
+#endif
+
+/*
+ * for external read access to <nousb>
+ */
+int usb_disabled(void)
+{
+ return nousb;
+}
+
/*
* Init
*/
static int __init usb_init(void)
{
+ if (nousb) {
+ info("USB support disabled\n");
+ return 0;
+ }
+
bus_register(&usb_bus_type);
usb_major_init();
usbfs_init();
@@ -1358,6 +1390,10 @@ static int __init usb_init(void)
*/
static void __exit usb_exit(void)
{
+ /* This will matter if shutdown/reboot does exitcalls. */
+ if (nousb)
+ return;
+
remove_driver(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
@@ -1377,6 +1413,7 @@ EXPORT_SYMBOL(usb_epnum_to_ep_desc);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL(usb_disabled);
EXPORT_SYMBOL(usb_device_probe);
EXPORT_SYMBOL(usb_device_remove);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ed92a80f66d0..0398d58d7f3a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -985,6 +985,9 @@ MODULE_LICENSE ("GPL");
static int __init init (void)
{
dbg (DRIVER_INFO);
+ if (usb_disabled())
+ return -ENODEV;
+
dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd",
sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
diff --git a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
index 334d30ba13a4..a83f7e83ac33 100644
--- a/drivers/usb/host/hc_sl811.c
+++ b/drivers/usb/host/hc_sl811.c
@@ -1321,6 +1321,9 @@ static int __init hci_hcd_init (void)
int ret;
DBGFUNC ("Enter hci_hcd_init\n");
+ if (usb_disabled())
+ return -ENODEV;
+
ret = hc_found_hci (base_addr, data_reg_addr, irq);
return ret;
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index a1979e532787..29b767ec52b7 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -365,6 +365,9 @@ static struct pci_driver ohci_pci_driver = {
static int __init ohci_hcd_pci_init (void)
{
dbg (DRIVER_INFO " (PCI)");
+ if (usb_disabled())
+ return -ENODEV;
+
dbg ("block sizes: ed %d td %d",
sizeof (struct ed), sizeof (struct td));
return pci_module_init (&ohci_pci_driver);
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index a6a34619d4fd..98996cd62d6e 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -23,6 +23,8 @@
#error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined."
#endif
+extern int usb_disabled(void);
+
/*-------------------------------------------------------------------------*/
static void sa1111_start_hc(struct sa1111_dev *dev)
@@ -355,6 +357,9 @@ static int ohci_hcd_sa1111_drv_probe(struct device *_dev)
struct usb_hcd *hcd = NULL;
int ret;
+ if (usb_disabled())
+ return -ENODEV;
+
ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
if (ret == 0)
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 8d8a5cd42fa5..1e4038ac97ca 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -2484,6 +2484,9 @@ static int __init uhci_hcd_init(void)
info(DRIVER_DESC " " DRIVER_VERSION);
+ if (usb_disabled())
+ return -ENODEV;
+
if (debug) {
errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
if (!errbuf)
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index ac7bdcace180..d5016e83ba62 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -402,7 +402,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
- char rep_data[2] = {0x02, 0x02};
char path[64];
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL)))
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index b3aa1f558bbe..d30da815bf8f 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -14,6 +14,6 @@ obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_PWC) += pwc.o
obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_STV680) += stv680.o
-obj-$(CONFIG_USB_VICAM) += vicam.o
+obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
include $(TOPDIR)/Rules.make
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 5b673019b7e1..709cdf93afa3 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1,102 +1,356 @@
-/* -*- linux-c -*-
- * USB ViCAM driver
- *
- * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
- * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
+/*
+ * USB ViCam WebCam driver
+ * Copyright (c) 2002 Joe Burks (jburks@wavicle.org)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
+ * Supports 3COM HomeConnect PC Digital WebCam
*
- * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * TODO:
- * - find out the ids for the Vista Imaging ViCAM
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * History:
+ * This source code is based heavily on the CPiA webcam driver which was
+ * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
*
- * 2001_07_07 - 0.1 - christopher: first version
- * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try
- while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
- yep, moving pictures.
- * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
- get gqcam-0.9, compile it and run. Better than dd ;-).
- * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
- kill update_params if it does not seem to work for you.
- * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
-
+ * Portions of this code were also copied from usbvideo.c
*
- * FIXME: It crashes on rmmod with camera plugged.
- */
-#define DEBUG 1
+ * Special thanks to the the whole team at Sourceforge for help making
+ * this driver become a reality. Notably:
+ * Andy Armstrong who reverse engineered the color encoding and
+ * Pavel Machek and Chris Cheney who worked on reverse engineering the
+ * camera controls and wrote the first generation driver.
+ * */
-#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
+#include <linux/wrapper.h>
#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/init.h>
+#include <linux/videodev.h>
#include <linux/usb.h>
-
-#include <asm/io.h>
-#include <linux/wrapper.h>
#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include "usbvideo.h"
-#include <linux/videodev.h>
+// #define VICAM_DEBUG
-#include "vicam.h"
-#include "vicamurbs.h"
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(a)
+#endif
+
+#ifndef bool
+#define bool int
+#endif
+
+#ifdef VICAM_DEBUG
+#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
+#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
+#else
+#define DBG(fmn,args...) do {} while(0)
+#endif
/* Version Information */
-#define DRIVER_VERSION "v0"
-#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
-#define DRIVER_DESC "USB ViCAM Driver"
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
+#define DRIVER_DESC "ViCam WebCam Driver"
/* Define these values to match your device */
-#define USB_VICAM_VENDOR_ID 0x04C1
-#define USB_VICAM_PRODUCT_ID 0x009D
+#define USB_VICAM_VENDOR_ID 0x04c1
+#define USB_VICAM_PRODUCT_ID 0x009d
-/* table of devices that work with this driver */
-static struct usb_device_id vicam_table [] = {
- { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
- { } /* Terminating entry */
-};
+#define VICAM_BYTES_PER_PIXEL 3
+#define VICAM_MAX_READ_SIZE (512*242+128)
+#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
+#define VICAM_FRAMES 2
-MODULE_DEVICE_TABLE (usb, vicam_table);
+/* Not sure what all the bytes in these char
+ * arrays do, but they're necessary to make
+ * the camera work.
+ */
-static int video_nr = -1; /* next avail video device */
-static struct usb_driver vicam_driver;
+static unsigned char setup1[] = {
+ 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67,
+ 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00,
+ 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17,
+ 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00,
+ 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
+};
-static char *buf, *buf2;
-static volatile int change_pending = 0;
+static unsigned char setup2[] = {
+ 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
+ 0x00, 0x00
+};
-static int vicam_parameters(struct usb_vicam *vicam);
+static unsigned char setup3[] = {
+ 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
+};
-/******************************************************************************
- *
- * Memory management functions
- *
- * Taken from bttv-drivers.c 2.4.7-pre3
- *
- ******************************************************************************/
+static unsigned char setup4[] = {
+ 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07,
+ 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00,
+ 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00,
+ 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07,
+ 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00,
+ 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00,
+ 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07,
+ 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF,
+ 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0,
+ 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07,
+ 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00,
+ 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0,
+ 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1,
+ 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09,
+ 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00,
+ 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF,
+ 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02,
+ 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00,
+ 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF,
+ 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00,
+ 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00,
+ 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05,
+ 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA,
+ 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06,
+ 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF,
+ 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05,
+ 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01,
+ 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09,
+ 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06,
+ 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05,
+ 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA,
+ 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05,
+ 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
+ 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00,
+ 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF,
+ 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00,
+ 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0,
+ 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06,
+ 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00,
+ 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07,
+ 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF,
+ 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00,
+ 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
+ 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57,
+ 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57,
+ 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00,
+ 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0,
+ 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B,
+ 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06,
+ 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06,
+ 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E,
+ 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00,
+ 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05,
+ 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00,
+ 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
+ 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF,
+ 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0,
+ 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+ 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05,
+ 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF,
+ 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0,
+ 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07,
+ 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07,
+ 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF,
+ 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF,
+ 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
+ 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
+ 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1,
+ 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
+ 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00,
+ 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07,
+ 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07,
+ 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07,
+ 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00,
+ 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06,
+ 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67,
+ 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8,
+ 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0,
+ 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF,
+ 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02,
+ 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
+ 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06,
+ 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05,
+ 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
+ 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00,
+ 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06,
+ 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
+ 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05,
+ 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05,
+ 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
+ 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04,
+ 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF,
+ 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06,
+ 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00,
+ 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+ 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07,
+ 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07,
+ 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07,
+ 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF,
+ 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07,
+ 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06,
+ 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05,
+ 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07,
+ 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00,
+ 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00,
+ 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77,
+ 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04,
+ 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0,
+ 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1,
+ 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07,
+ 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
+ 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
+ 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
+ 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77,
+ 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1,
+ 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07,
+ 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06,
+ 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
+ 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07,
+ 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07,
+ 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00,
+ 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00,
+ 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F,
+ 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00,
+ 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00,
+ 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA,
+ 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
+ 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06,
+ 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B,
+ 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09,
+ 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05,
+ 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07,
+ 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00,
+ 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF,
+ 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05,
+ 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00,
+ 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00,
+ 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00,
+ 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09,
+ 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00,
+ 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00,
+ 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0,
+ 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67,
+ 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87,
+ 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9,
+ 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1,
+ 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF,
+ 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00,
+ 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0,
+ 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87,
+ 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
+ 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67,
+ 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+ 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+ 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67,
+ 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+ 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
+ 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
+ 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00,
+ 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF,
+ 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
+ 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
+ 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09,
+ 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+ 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA,
+ 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87,
+ 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
+ 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
+ 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
+ 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
+ 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02,
+ 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09,
+ 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
+static unsigned char setup5[] = {
+ 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00,
+ 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00,
+ 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00,
+ 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00,
+ 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00,
+ 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00,
+ 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00,
+ 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01,
+ 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01,
+ 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01,
+ 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01,
+ 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01,
+ 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01,
+ 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01,
+ 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01,
+ 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02,
+ 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02,
+ 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02,
+ 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02,
+ 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02,
+ 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02,
+ 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02,
+ 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02,
+ 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03,
+ 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03,
+ 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03,
+ 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03,
+ 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03,
+ 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03,
+ 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03,
+ 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04,
+ 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04,
+ 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04,
+ 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04,
+ 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04,
+ 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04,
+ 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04,
+ 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05,
+ 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
+};
+
+static unsigned long kvirt_to_pa(unsigned long adr)
{
unsigned long kva, ret;
@@ -106,526 +360,734 @@ static inline unsigned long kvirt_to_pa(unsigned long adr)
return ret;
}
-static void * rvmalloc(unsigned long size)
+/* rvmalloc / rvfree copied from usbvideo.c
+ *
+ * Not sure why these are not yet non-statics which I can reference through
+ * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime
+ * in the future.
+ *
+*/
+static void *rvmalloc(unsigned long size)
{
- void * mem;
+ void *mem;
unsigned long adr;
- size=PAGE_ALIGN(size);
- mem=vmalloc_32(size);
- if (mem)
- {
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr=(unsigned long) mem;
- while (size > 0)
- {
- mem_map_reserve(vmalloc_to_page((void *)adr));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
+ size = PAGE_ALIGN(size);
+ mem = vmalloc_32(size);
+ if (!mem)
+ return NULL;
+
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr = (unsigned long) mem;
+ while (size > 0) {
+ mem_map_reserve(vmalloc_to_page((void *)adr));
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
}
+
return mem;
}
-static void rvfree(void * mem, unsigned long size)
+static void rvfree(void *mem, unsigned long size)
{
unsigned long adr;
- if (mem)
- {
- adr=(unsigned long) mem;
- while ((long) size > 0)
- {
- mem_map_unreserve(vmalloc_to_page((void *)adr));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- vfree(mem);
+ if (!mem)
+ return;
+
+ adr = (unsigned long) mem;
+ while ((long) size > 0) {
+ mem_map_unreserve(vmalloc_to_page((void *)adr));
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
}
+ vfree(mem);
}
+
+struct vicam_camera {
+ u16 shutter_speed; // capture shutter speed
+ u16 gain; // capture gain
-/******************************************************************************
- *
- * Foo Bar
- *
- ******************************************************************************/
+ u8 *raw_image; // raw data captured from the camera
+ u8 *framebuf; // processed data in RGB24 format
-/**
- * usb_vicam_debug_data
- */
-static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
-{
- int i;
+ struct video_device vdev; // v4l video device
+ struct usb_device *udev; // usb device
- if (!debug)
- return;
+ struct semaphore busy_lock; // guard against SMP multithreading
- printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
- function, size);
- for (i = 0; i < size; ++i) {
- printk ("%.2x ", data[i]);
- }
- printk ("\n");
-}
+ bool is_initialized;
+ u8 open_count;
+ u8 bulkEndpoint;
+ bool needsDummyRead;
-/*****************************************************************************
- *
- * Send command to vicam
- *
- *****************************************************************************/
+ u32 framebuf_size; // # of valid bytes in framebuf
+ u32 framebuf_read_start; // position in frame buf that a read is happening at.
+
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_entry;
+#endif
-static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
- unsigned short value, unsigned char *cp, int size)
+};
+
+static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
+static void vicam_disconnect(struct usb_interface *intf);
+static void read_frame(struct vicam_camera *cam, int framenum);
+
+static int
+send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
+ unsigned char *cp, u16 size)
{
- int ret;
- unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
+ int status;
- /* Needs to return data I think, works for sending though */
+ // for reasons not yet known to me, you can't send USB control messages
+ // with data in the module (if you are compiled as a module). Whatever
+ // the reason, copying it to memory allocated as kernel memory then
+ // doing the usb control message fixes the problem.
+
+ unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
memcpy(transfer_buffer, cp, size);
-
- ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
+
+ status = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, value, index,
+ transfer_buffer, size, HZ);
kfree(transfer_buffer);
- if (ret)
- printk("vicam: error: %d\n", ret);
- mdelay(100);
- return ret;
-}
+ if (status < 0) {
+ printk(KERN_INFO "Failed sending control message, error %d.\n",
+ status);
+ }
-/*****************************************************************************
- *
- * Video4Linux Helpers
- *
- *****************************************************************************/
+ return status;
+}
-static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
+static int
+initialize_camera(struct vicam_camera *cam)
{
- dbg("vicam_get_capability");
-
- strcpy(b->name, vicam->camera_name);
- b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
- b->channels = 1;
- b->audios = 0;
-
- b->maxwidth = vicam->width[vicam->sizes-1];
- b->maxheight = vicam->height[vicam->sizes-1];
- b->minwidth = vicam->width[0];
- b->minheight = vicam->height[0];
+ struct usb_device *udev = cam->udev;
+ int status;
+
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0)
+ return status;
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0)
+ return status;
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
+ return status;
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0)
+ return status;
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0)
+ return status;
+ if ((status =
+ send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
+ return status;
return 0;
}
-
-static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
+
+static int
+set_camera_power(struct vicam_camera *cam, int state)
{
- dbg("vicam_get_channel");
+ int status;
- if (v->channel != 0)
- return -EINVAL;
-
- v->flags = 0;
- v->tuners = 0;
- v->type = VIDEO_TYPE_CAMERA;
- strcpy(v->name, "Camera");
+ if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0)
+ return status;
- return 0;
-}
-
-static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
-{
- dbg("vicam_set_channel");
+ if (state) {
+ send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0);
+ }
- if (v->channel != 0)
- return -EINVAL;
-
return 0;
}
-
-static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
+
+static int
+vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long ul_arg)
{
- int i;
+ void *arg = (void *)ul_arg;
+ struct vicam_camera *cam = file->private_data;
+ int retval = 0;
- dbg("vicam_get_mmapbuffer");
+ if (!cam)
+ return -ENODEV;
- memset(vm, 0, sizeof(vm));
- vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
- vm->frames = VICAM_NUMFRAMES;
+ /* make this _really_ smp-safe */
+ if (down_interruptible(&cam->busy_lock))
+ return -EINTR;
- for (i=0; i<VICAM_NUMFRAMES; i++)
- vm->offsets[i] = vicam->maxframesize * i;
+ switch (ioctlnr) {
+ /* query capabilites */
+ case VIDIOCGCAP:
+ {
+ struct video_capability b;
+
+ DBG("VIDIOCGCAP\n");
+ strcpy(b.name, "ViCam-based Camera");
+ b.type = VID_TYPE_CAPTURE;
+ b.channels = 1;
+ b.audios = 0;
+ b.maxwidth = 320; /* VIDEOSIZE_CIF */
+ b.maxheight = 240;
+ b.minwidth = 320; /* VIDEOSIZE_48_48 */
+ b.minheight = 240;
+
+ if (copy_to_user(arg, &b, sizeof (b)))
+ retval = -EFAULT;
+
+ break;
+ }
+ /* get/set video source - we are a camera and nothing else */
+ case VIDIOCGCHAN:
+ {
+ struct video_channel v;
+
+ DBG("VIDIOCGCHAN\n");
+ if (copy_from_user(&v, arg, sizeof (v))) {
+ retval = -EFAULT;
+ break;
+ }
+ if (v.channel != 0) {
+ retval = -EINVAL;
+ break;
+ }
+
+ v.channel = 0;
+ strcpy(v.name, "Camera");
+ v.tuners = 0;
+ v.flags = 0;
+ v.type = VIDEO_TYPE_CAMERA;
+ v.norm = 0;
+
+ if (copy_to_user(arg, &v, sizeof (v)))
+ retval = -EFAULT;
+ break;
+ }
- return 0;
-}
+ case VIDIOCSCHAN:
+ {
+ int v;
-static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
-{
- dbg("vicam_get_picture");
+ if (copy_from_user(&v, arg, sizeof (v)))
+ retval = -EFAULT;
+ DBG("VIDIOCSCHAN %d\n", v);
- /* This is probably where that weird 0x56 call goes */
- p->brightness = vicam->win.brightness;
- p->hue = vicam->win.hue;
- p->colour = vicam->win.colour;
- p->contrast = vicam->win.contrast;
- p->whiteness = vicam->win.whiteness;
- p->depth = vicam->win.depth;
- p->palette = vicam->win.palette;
+ if (retval == 0 && v != 0)
+ retval = -EINVAL;
- return 0;
-}
+ break;
+ }
-static void synchronize(struct usb_vicam *vicam)
-{
- DECLARE_WAITQUEUE(wait, current);
- change_pending = 1;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&vicam->wait, &wait);
- if (change_pending)
- schedule();
- remove_wait_queue(&vicam->wait, &wait);
- set_current_state(TASK_RUNNING);
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
- mdelay(10);
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
- mdelay(10);
-}
+ /* image properties */
+ case VIDIOCGPICT:
+ {
+ struct video_picture vp;
+ DBG("VIDIOCGPICT\n");
+ memset(&vp, 0, sizeof (struct video_picture));
+ vp.brightness = cam->gain << 8;
+ vp.depth = 24;
+ vp.palette = VIDEO_PALETTE_RGB24;
+ if (copy_to_user
+ (arg, &vp, sizeof (struct video_picture)))
+ retval = -EFAULT;
+ break;
+ }
-static void params_changed(struct usb_vicam *vicam)
-{
-#if 1
- synchronize(vicam);
- mdelay(10);
- vicam_parameters(vicam);
- printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
-#endif
+ case VIDIOCSPICT:
+ {
+ struct video_picture *vp = (struct video_picture *) arg;
+
+ DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp->depth,
+ vp->palette);
+
+ cam->gain = vp->brightness >> 8;
+
+ if (vp->depth != 24
+ || vp->palette != VIDEO_PALETTE_RGB24)
+ retval = -EINVAL;
+
+ break;
+ }
+
+ /* get/set capture window */
+ case VIDIOCGWIN:
+ {
+ struct video_window vw;
+ vw.x = 0;
+ vw.y = 0;
+ vw.width = 320;
+ vw.height = 240;
+ vw.chromakey = 0;
+ vw.flags = 0;
+ vw.clips = NULL;
+ vw.clipcount = 0;
+
+ DBG("VIDIOCGWIN\n");
+
+ if (copy_to_user
+ ((void *) arg, (void *) &vw, sizeof (vw)))
+ retval = -EFAULT;
+
+ // I'm not sure what the deal with a capture window is, it is very poorly described
+ // in the doc. So I won't support it now.
+ break;
+ }
+
+ case VIDIOCSWIN:
+ {
+
+ struct video_window *vw = (struct video_window *) arg;
+ DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height);
+
+ if ( vw->width != 320 || vw->height != 240 )
+ retval = -EFAULT;
+
+ break;
+ }
+
+ /* mmap interface */
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf vm;
+ int i;
+
+ DBG("VIDIOCGMBUF\n");
+ memset(&vm, 0, sizeof (vm));
+ vm.size =
+ VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
+ vm.frames = VICAM_FRAMES;
+ for (i = 0; i < VICAM_FRAMES; i++)
+ vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
+
+ if (copy_to_user
+ ((void *) arg, (void *) &vm, sizeof (vm)))
+ retval = -EFAULT;
+
+ break;
+ }
+
+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap vm;
+ // int video_size;
+
+ if (copy_from_user
+ ((void *) &vm, (void *) arg, sizeof (vm))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
+
+ if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
+ retval = -EINVAL;
+
+ // in theory right here we'd start the image capturing
+ // (fill in a bulk urb and submit it asynchronously)
+ //
+ // Instead we're going to do a total hack job for now and
+ // retrieve the frame in VIDIOCSYNC
+
+ break;
+ }
+
+ case VIDIOCSYNC:
+ {
+ int frame;
+
+ if (copy_from_user((void *) &frame, arg, sizeof (int))) {
+ retval = -EFAULT;
+ break;
+ }
+ DBG("VIDIOCSYNC: %d\n", frame);
+
+ read_frame(cam, frame);
+
+ break;
+ }
+
+ /* pointless to implement overlay with this camera */
+ case VIDIOCCAPTURE:
+ case VIDIOCGFBUF:
+ case VIDIOCSFBUF:
+ case VIDIOCKEY:
+ retval = -EINVAL;
+ break;
+
+ /* tuner interface - we have none */
+ case VIDIOCGTUNER:
+ case VIDIOCSTUNER:
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ retval = -EINVAL;
+ break;
+
+ /* audio interface - we have none */
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ retval = -EINVAL;
+ break;
+ default:
+ retval = -ENOIOCTLCMD;
+ break;
+ }
+
+ up(&cam->busy_lock);
+ return retval;
}
-static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
+static int
+vicam_open(struct inode *inode, struct file *file)
{
- int changed = 0;
- info("vicam_set_picture (%d)", p->brightness);
-
-
-#define SET(x) \
- if (vicam->win.x != p->x) \
- vicam->win.x = p->x, changed = 1;
- SET(brightness);
- SET(hue);
- SET(colour);
- SET(contrast);
- SET(whiteness);
- SET(depth);
- SET(palette);
- if (changed)
- params_changed(vicam);
+ struct video_device *dev = video_devdata(file);
+ struct vicam_camera *cam =
+ (struct vicam_camera *) dev->priv;
+ DBG("open\n");
+
+ if (!cam) {
+ printk(KERN_ERR
+ "vicam video_device improperly initialized");
+ }
- return 0;
- /* Investigate what should be done maybe 0x56 type call */
- if (p->depth != 8) return 1;
- if (p->palette != VIDEO_PALETTE_GREY) return 1;
+ down_interruptible(&cam->busy_lock);
+
+ if (cam->open_count > 0) {
+ printk(KERN_INFO
+ "vicam_open called on already opened camera");
+ up(&cam->busy_lock);
+ return -EBUSY;
+ }
+
+ if (!cam->raw_image) {
+ cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
+ if (!cam->raw_image) {
+ up(&cam->busy_lock);
+ return -ENOMEM;
+ }
+ }
+
+ if (!cam->framebuf) {
+ cam->framebuf =
+ rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+ if (!cam->framebuf) {
+ kfree(cam->raw_image);
+ up(&cam->busy_lock);
+ return -ENOMEM;
+ }
+ }
+ // First upload firmware, then turn the camera on
+
+ if (!cam->is_initialized) {
+ initialize_camera(cam);
+
+ cam->is_initialized = 1;
+ }
+
+ set_camera_power(cam, 1);
+
+ cam->needsDummyRead = 1;
+ cam->open_count++;
+ up(&cam->busy_lock);
+
+ file->private_data = cam;
+
return 0;
}
-/* FIXME - vicam_sync_frame - important */
-static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
+static int
+vicam_close(struct inode *inode, struct file *file)
{
- dbg("vicam_sync_frame");
+ struct vicam_camera *cam = file->private_data;
+ DBG("close\n");
+ set_camera_power(cam, 0);
- if(frame <0 || frame >= VICAM_NUMFRAMES)
- return -EINVAL;
+ cam->open_count--;
- /* Probably need to handle various cases */
-/* ret=vicam_newframe(vicam, frame);
- vicam->frame[frame].grabstate=FRAME_UNUSED;
-*/
return 0;
}
-
-static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
-{
- dbg("vicam_get_window");
- vw->x = 0;
- vw->y = 0;
- vw->chromakey = 0;
- vw->flags = 0;
- vw->clipcount = 0;
- vw->width = vicam->win.width;
- vw->height = vicam->win.height;
+inline int pin(int x)
+{
+ return((x > 255) ? 255 : ((x < 0) ? 0 : x));
+}
- return 0;
+inline void writepixel(char *rgb, int Y, int Cr, int Cb)
+{
+ Y = 1160 * (Y - 16);
+
+ rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
+ rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
+ rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
}
-static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
+#define DATA_HEADER_SIZE 64
+
+// --------------------------------------------------------------------------------
+// vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
+//
+// Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
+// --------------------------------------------------------------------------------
+
+void vicam_decode_color( char *data, char *rgb)
{
- info("vicam_set_window");
-
- if (vw->flags)
- return -EINVAL;
- if (vw->clipcount)
- return -EINVAL;
+ int x,y;
+ int Cr, Cb;
+ int sign;
+ int prevX, nextX, prevY, nextY;
+ int skip;
+ unsigned char *src;
+ unsigned char *dst;
- if (vicam->win.width == vw->width && vicam->win.height == vw->height)
- return 0;
+ prevY = 512;
+ nextY = 512;
- /* Pick largest mode that is smaller than specified res */
- /* If specified res is too small reject */
+ src = data + DATA_HEADER_SIZE;
+ dst = rgb;
- /* Add urb send to device... */
+ for(y = 1; y < 241; y += 2)
+ {
+ // even line
+ sign = 1;
+ prevX = 1;
+ nextX = 1;
- vicam->win.width = vw->width;
- vicam->win.height = vw->height;
- params_changed(vicam);
+ skip = 0;
- return 0;
-}
+ dst = rgb + (y-1)*320*3;
+
+ for(x = 0; x < 512; x++)
+ {
+ if(x == 512-1)
+ nextX = -1;
-/* FIXME - vicam_mmap_capture - important */
-static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
-{
- dbg("vicam_mmap_capture");
+ Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
+ Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
- /* usbvideo.c looks good for using here */
+ writepixel(
+ dst + ((x*5)>>3)*3,
+ src[0] + (sign * (Cr >> 1)),
+ Cr,
+ Cb);
- /*
- if (vm->frame >= VICAM_NUMFRAMES)
- return -EINVAL;
- if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
- return -EBUSY;
- vicam->frame[vm->frame].grabstate=FRAME_READY;
- */
+ src++;
+ sign *= -1;
+ prevX = -1;
+ }
- /* No need to vicam_set_window here according to Alan */
+ prevY = -512;
- /*
- if (!vicam->streaming)
- vicam_start_stream(vicam);
- */
+ if(y == (242 - 2))
+ nextY = -512;
- /* set frame as ready */
+ // odd line
+ sign = 1;
+ prevX = 1;
+ nextX = 1;
- return 0;
-}
+ skip = 0;
-/*****************************************************************************
- *
- * Video4Linux
- *
- *****************************************************************************/
+ dst = rgb + (y)*320*3;
+
+ for(x = 0; x < 512; x++)
+ {
+ if(x == 512-1)
+ nextX = -1;
+
+ Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
+ Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
+
+ writepixel(
+ dst + ((x * 5)>>3)*3,
+ src[0] - (sign * (Cb >> 1)),
+ Cr,
+ Cb);
+
+ src++;
+ sign *= -1;
+ prevX = -1;
+ }
+ }
+}
-static int vicam_v4l_open(struct inode *inode, struct file *file)
+static void
+read_frame(struct vicam_camera *cam, int framenum)
{
- struct video_device *vdev = video_devdata(file);
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- int err = 0;
-
- dbg("vicam_v4l_open");
- down(&vicam->sem);
-
- vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
- if (vicam->open_count) {
- err = -EBUSY;
- } else if (!vicam->fbuf) {
- err =- ENOMEM;
+ unsigned char request[16];
+ int realShutter;
+ int n;
+ int actual_length;
+
+ memset(request, 0, 16);
+ request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
+
+ request[1] = 0; // 512x242 capture
+
+ request[2] = 0x90; // the function of these two bytes
+ request[3] = 0x07; // is not yet understood
+
+ if (cam->shutter_speed > 60) {
+ // Short exposure
+ realShutter =
+ ((-15631900 / cam->shutter_speed) + 260533) / 1000;
+ request[4] = realShutter & 0xFF;
+ request[5] = (realShutter >> 8) & 0xFF;
+ request[6] = 0x03;
+ request[7] = 0x01;
} else {
-#ifdef BLINKING
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
- info ("led on");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
-#endif
- vicam->open_count++;
- file->private_data = vdev;
+ // Long exposure
+ realShutter = 15600 / cam->shutter_speed - 1;
+ request[4] = 0;
+ request[5] = 0;
+ request[6] = realShutter & 0xFF;
+ request[7] = realShutter >> 8;
}
- up(&vicam->sem);
- return err;
-}
-
-static int vicam_v4l_close(struct inode *inode, struct file *file)
-{
- struct video_device *vdev = file->private_data;
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+ // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
+ request[8] = 0;
+ // bytes 9-15 do not seem to affect exposure or image quality
- dbg("vicam_v4l_close");
-
- down(&vicam->sem);
+ n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16);
-#ifdef BLINKING
- info ("led off");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
-// vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
-#endif
+ if (n < 0) {
+ printk(KERN_ERR
+ " Problem sending frame capture control message");
+ return;
+ }
- rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
- vicam->fbuf = 0;
- vicam->open_count=0;
- file->private_data = NULL;
+ n = usb_bulk_msg(cam->udev,
+ usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
+ cam->raw_image,
+ 512 * 242 + 128, &actual_length, HZ*10);
- up(&vicam->sem);
- /* Why does se401.c have a usbdevice check here? */
- /* If device is unplugged while open, I guess we only may unregister now */
- return 0;
-}
+ if (n < 0) {
+ printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
+ n);
+ }
-static int vicam_v4l_read(struct file *file, char *user_buf,
- size_t buflen, loff_t *ppos)
-{
- struct video_device *vdev = file->private_data;
- //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+ vicam_decode_color(cam->raw_image,
+ cam->framebuf +
+ framenum * VICAM_MAX_FRAME_SIZE );
- dbg("vicam_v4l_read(%d)", buflen);
+ cam->framebuf_size =
+ 320 * 240 * VICAM_BYTES_PER_PIXEL;
+ cam->framebuf_read_start = 0;
- if (!vdev || !buf)
- return -EFAULT;
+ return;
- if (copy_to_user(user_buf, buf2, buflen))
- return -EFAULT;
- return buflen;
}
-static int vicam_v4l_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int
+vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos )
{
- struct video_device *vdev = file->private_data;
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
- int ret = -EL3RST;
+ struct vicam_camera *cam = file->private_data;
+ DBG("read %d bytes.\n", (int) count);
- if (!vicam->udev)
- return -EIO;
+ if (!buf)
+ return -EINVAL;
- down(&vicam->sem);
+ if (!count)
+ return -EINVAL;
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability *b = arg;
- ret = vicam_get_capability(vicam,b);
- dbg("name %s",b->name);
- break;
- }
- case VIDIOCGFBUF:
- {
- struct video_buffer *vb = arg;
- info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
- /* frame buffer not supported, not used */
- memset(vb, 0, sizeof(*vb));
- ret = 0;
- break;
- }
- case VIDIOCGWIN:
- {
- struct video_window *vw = arg;
- ret = vicam_get_window(vicam, vw);
- break;
- }
- case VIDIOCSWIN:
- {
- struct video_window *vw = arg;
- ret = vicam_set_window(vicam, vw);
- break;
+ // This is some code that will hopefully allow us to do shell copies from
+ // the /dev/videoX to a file and have it actually work.
+ if (cam->framebuf_size != 0) {
+ if (cam->framebuf_read_start == cam->framebuf_size) {
+ cam->framebuf_size = cam->framebuf_read_start = 0;
+ return 0;
+ } else {
+ if (cam->framebuf_read_start + count <=
+ cam->framebuf_size) {
+ // count does not exceed available bytes
+ copy_to_user(buf,
+ (cam->framebuf) +
+ cam->framebuf_read_start, count);
+ cam->framebuf_read_start += count;
+ return count;
+ } else {
+ count =
+ cam->framebuf_size -
+ cam->framebuf_read_start;
+ copy_to_user(buf,
+ (cam->framebuf) +
+ cam->framebuf_read_start, count);
+ cam->framebuf_read_start = cam->framebuf_size;
+ return count;
+ }
+ }
}
- case VIDIOCGCHAN:
- {
- struct video_channel *v = arg;
- ret = vicam_get_channel(vicam,v);
- break;
- }
- case VIDIOCSCHAN:
- {
- struct video_channel *v = arg;
- ret = vicam_set_channel(vicam,v);
- break;
- }
- case VIDIOCGPICT:
- {
- struct video_picture *p = arg;
- ret = vicam_get_picture(vicam,p);
- break;
- }
- case VIDIOCSPICT:
- {
- struct video_picture *p = arg;
- ret = vicam_set_picture(vicam,p);
- break;
- }
- case VIDIOCGMBUF:
- {
- struct video_mbuf *vm = arg;
- ret = vicam_get_mmapbuffer(vicam,vm);
- break;
- }
- case VIDIOCMCAPTURE:
- {
- struct video_mmap *vm = arg;
- ret = vicam_mmap_capture(vicam,vm);
- break;
- }
- case VIDIOCSYNC:
- {
- int *frame = arg;
- ret = vicam_sync_frame(vicam,*frame);
- break;
+ down_interruptible(&cam->busy_lock);
+
+ if (cam->needsDummyRead) {
+ read_frame(cam, 0);
+ cam->needsDummyRead = 0;
}
+ // read_frame twice because the camera doesn't seem to take the shutter speed for the first one.
- case VIDIOCKEY:
- ret = 0;
-
- case VIDIOCCAPTURE:
- case VIDIOCSFBUF:
- case VIDIOCGTUNER:
- case VIDIOCSTUNER:
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- case VIDIOCGUNIT:
- ret = -EINVAL;
+ read_frame(cam, 0);
- default:
- {
- info("vicam_v4l_ioctl - %ui",cmd);
- ret = -ENOIOCTLCMD;
- }
- } /* end switch */
+ if (count > cam->framebuf_size)
+ count = cam->framebuf_size;
- up(&vicam->sem);
- return ret;
-}
+ copy_to_user(buf, cam->framebuf, count);
-static int vicam_v4l_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return video_usercopy(inode, file, cmd, arg, vicam_v4l_do_ioctl);
+ if (count != cam->framebuf_size)
+ cam->framebuf_read_start = count;
+ else
+ cam->framebuf_size = 0;
+
+ up(&cam->busy_lock);
+
+ return count;
}
-static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma)
+
+static int
+vicam_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct video_device *vdev = file->private_data;
- struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+ // TODO: allocate the raw frame buffer if necessary
+ unsigned long page, pos;
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end-vma->vm_start;
- unsigned long page, pos;
+ struct vicam_camera *cam = file->private_data;
- down(&vicam->sem);
-
- if (vicam->udev == NULL) {
- up(&vicam->sem);
- return -EIO;
- }
-#if 0
- if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
- up(&vicam->sem);
- return -EINVAL;
+ if (!cam)
+ return -ENODEV;
+
+ DBG("vicam_mmap: %ld\n", size);
+
+ /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
+ * to the size the application requested for mmap and it was screwing apps up.
+ if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
+ return -EINVAL;
+ */
+
+ /* make this _really_ smp-safe */
+ if (down_interruptible(&cam->busy_lock))
+ return -EINTR;
+
+ if (!cam->framebuf) { /* we do lazy allocation */
+ cam->framebuf =
+ rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+ if (!cam->framebuf) {
+ up(&cam->busy_lock);
+ return -ENOMEM;
+ }
}
-#endif
- pos = (unsigned long)vicam->fbuf;
+
+ pos = (unsigned long)cam->framebuf;
while (size > 0) {
page = kvirt_to_pa(pos);
- if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
- up(&vicam->sem);
+ if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
return -EAGAIN;
- }
+
start += PAGE_SIZE;
pos += PAGE_SIZE;
if (size > PAGE_SIZE)
@@ -633,299 +1095,315 @@ static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma)
else
size = 0;
}
- up(&vicam->sem);
- return 0;
+ up(&cam->busy_lock);
+
+ return 0;
}
-/* FIXME - vicam_template - important */
-static struct file_operations vicam_fops = {
- .owner = THIS_MODULE,
- .open = vicam_v4l_open,
- .release = vicam_v4l_close,
- .read = vicam_v4l_read,
- .mmap = vicam_v4l_mmap,
- .ioctl = vicam_v4l_ioctl,
- .llseek = no_llseek,
-};
-static struct video_device vicam_template = {
- .owner = THIS_MODULE,
- .name = "vicam USB camera",
- .type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_SE401, /* need to ask for own id */
- .fops = &vicam_fops,
-};
+#ifdef CONFIG_PROC_FS
-/******************************************************************************
- *
- * Some Routines
- *
- ******************************************************************************/
+static struct proc_dir_entry *vicam_proc_root = NULL;
-/*
-Flash the led
-vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
-info ("led on");
-vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
-info ("led off");
-vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
-vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
-*/
+static int
+vicam_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *out = page;
+ int len;
+ struct vicam_camera *cam = (struct vicam_camera *) data;
+
+ out +=
+ sprintf(out, "Vicam-based WebCam Linux Driver.\n");
+ out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");
+ out += sprintf(out, "vicam stats:\n");
+ out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed);
+ out += sprintf(out, " Gain: %d\n", cam->gain);
+
+ len = out - page;
+ len -= off;
+ if (len < count) {
+ *eof = 1;
+ if (len <= 0)
+ return 0;
+ } else
+ len = count;
+
+ *start = page + off;
+ return len;
+}
-static void vicam_bulk(struct urb *urb)
+static int
+vicam_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
{
- struct usb_vicam *vicam = urb->context;
+ char *in;
+ char *start;
+ struct vicam_camera *cam = (struct vicam_camera *) data;
- /* if (!vicam || !vicam->dev || !vicam->used)
- return;
- */
+ in = kmalloc(count + 1, GFP_KERNEL);
+ if (!in)
+ return -ENOMEM;
- if (urb->status)
- printk("vicam%d: nonzero read/write bulk status received: %d",
- 0, urb->status);
+ in[count] = 0; // I'm not sure buffer is gauranteed to be null terminated
+ // so I do this to make sure I have a null in there.
- urb->actual_length = 0;
- urb->dev = vicam->udev;
+ strncpy(in, buffer, count);
- memcpy(buf2, buf+64, 0x1e480);
- if (vicam->fbuf)
- memcpy(vicam->fbuf, buf+64, 0x1e480);
+ start = strstr(in, "gain=");
+ if (start
+ && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
+ cam->gain = simple_strtoul(start + 5, NULL, 10);
- if (!change_pending) {
- if (usb_submit_urb(urb, GFP_ATOMIC))
- dbg("failed resubmitting read urb");
- } else {
- change_pending = 0;
- wake_up_interruptible(&vicam->wait);
- }
+ start = strstr(in, "shutter=");
+ if (start
+ && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
+ cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
+
+ kfree(in);
+ return count;
}
-static int vicam_parameters(struct usb_vicam *vicam)
+void
+vicam_create_proc_root(void)
{
- unsigned char req[0x10];
- unsigned int shutter;
- shutter = 10;
+ vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
- switch (vicam->win.width) {
- case 512:
- default:
- memcpy(req, s512x242bw, 0x10);
- break;
- case 256:
- memcpy(req, s256x242bw, 0x10);
- break;
- case 128:
- memcpy(req, s128x122bw, 0x10);
- break;
- }
+ if (vicam_proc_root)
+ vicam_proc_root->owner = THIS_MODULE;
+ else
+ printk(KERN_ERR
+ "could not create /proc entry for vicam!");
+}
+void
+vicam_destroy_proc_root(void)
+{
+ if (vicam_proc_root)
+ remove_proc_entry("video/vicam", 0);
+}
- mdelay(10);
- vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
- info ("led on");
- vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+void
+vicam_create_proc_entry(void *ptr)
+{
+ struct vicam_camera *cam = (struct vicam_camera *) ptr;
- mdelay(10);
+ char name[7];
+ struct proc_dir_entry *ent;
- shutter = vicam->win.contrast / 256;
- if (shutter == 0)
- shutter = 1;
- printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
- req[0] = vicam->win.brightness /256;
- shutter = 15600/shutter - 1;
- req[6] = shutter & 0xff;
- req[7] = (shutter >> 8) & 0xff;
- vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
- mdelay(10);
- vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
- mdelay(10);
+ DBG(KERN_INFO "vicam: creating proc entry\n");
- return 0;
+ if (!vicam_proc_root || !cam) {
+ printk(KERN_INFO
+ "vicam: could not create proc entry, %s pointer is null.\n",
+ (!cam ? "camera" : "root"));
+ return;
+ }
+
+ sprintf(name, "video%d", cam->vdev.minor);
+
+ ent =
+ create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+ vicam_proc_root);
+ if (!ent)
+ return;
+
+ ent->data = cam;
+ ent->read_proc = vicam_read_proc;
+ ent->write_proc = vicam_write_proc;
+ ent->size = 512;
+ cam->proc_entry = ent;
}
-static int vicam_init(struct usb_vicam *vicam)
+void
+vicam_destroy_proc_entry(void *ptr)
{
- int width[] = {128, 256, 512};
- int height[] = {122, 242, 242};
-
- dbg("vicam_init");
- buf = kmalloc(0x1e480, GFP_KERNEL);
- buf2 = kmalloc(0x1e480, GFP_KERNEL);
- if ((!buf) || (!buf2)) {
- printk("Not enough memory for vicam!\n");
- goto error;
- }
+ struct vicam_camera *cam = (struct vicam_camera *) ptr;
+ char name[7];
- /* do we do aspect correction in kernel or not? */
- vicam->sizes = 3;
- vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
- vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
- memcpy(vicam->width, &width, sizeof(width));
- memcpy(vicam->height, &height, sizeof(height));
- vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
+ if (!cam || !cam->proc_entry)
+ return;
- /* Download firmware to camera */
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
- vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+ sprintf(name, "video%d", cam->vdev.minor);
+ remove_proc_entry(name, vicam_proc_root);
+ cam->proc_entry = NULL;
- vicam_parameters(vicam);
+}
- FILL_BULK_URB(vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
- buf, 0x1e480, vicam_bulk, vicam);
- printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
+#endif
+int
+vicam_video_init(struct video_device *vdev)
+{
+ // This would normally create the proc entry for this camera
+#ifdef CONFIG_PROC_FS
+ vicam_create_proc_entry(vdev->priv);
+#endif
return 0;
-error:
- if (buf)
- kfree(buf);
- if (buf2)
- kfree(buf2);
- return 1;
}
-static int vicam_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_vicam *vicam;
- char *camera_name=NULL;
+static struct file_operations vicam_fops = {
+ .owner = THIS_MODULE,
+ .open = vicam_open,
+ .release =vicam_close,
+ .read = vicam_read,
+ .mmap = vicam_mmap,
+ .ioctl = vicam_ioctl,
+ .llseek = no_llseek,
+};
+
+static struct video_device vicam_template = {
+ .owner = THIS_MODULE,
+ .name = "ViCam-based USB Camera",
+ .type = VID_TYPE_CAPTURE,
+ .hardware = VID_HARDWARE_VICAM,
+ .fops = &vicam_fops,
+// .initialize = vicam_video_init,
+ .minor = -1,
+};
+
+/* table of devices that work with this driver */
+static struct usb_device_id vicam_table[] = {
+ {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, vicam_table);
- dbg("vicam_probe");
+static struct usb_driver vicam_driver = {
+ name:"vicam",
+ probe:vicam_probe,
+ disconnect:vicam_disconnect,
+ id_table:vicam_table
+};
+/**
+ * vicam_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int
+vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ int bulkEndpoint = 0;
+ const struct usb_interface_descriptor *interface;
+ const struct usb_endpoint_descriptor *endpoint;
+ struct vicam_camera *cam;
+
/* See if the device offered us matches what we can accept */
- if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
+ if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
+ (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
return -ENODEV;
}
-
- camera_name="3Com HomeConnect USB";
- info("ViCAM camera found: %s", camera_name);
-
- vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
- if (vicam == NULL) {
- err ("couldn't kmalloc vicam struct");
- return -ENOMEM;
+
+ printk(KERN_INFO "ViCam based webcam connected\n");
+
+ interface = &intf->altsetting[0];
+
+ DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
+ ifnum, (unsigned) (interface->bNumEndpoints));
+ endpoint = &interface->endpoint[0];
+
+ if ((endpoint->bEndpointAddress & 0x80) &&
+ ((endpoint->bmAttributes & 3) == 0x02)) {
+ /* we found a bulk in endpoint */
+ bulkEndpoint = endpoint->bEndpointAddress;
+ } else {
+ printk(KERN_ERR
+ "No bulk in endpoint was found ?! (this is bad)\n");
}
- memset(vicam, 0, sizeof(*vicam));
- vicam->readurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!vicam->readurb) {
- kfree(vicam);
+ if ((cam =
+ kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING
+ "could not allocate kernel memory for vicam_camera struct\n");
return -ENOMEM;
}
- vicam->udev = udev;
- vicam->camera_name = camera_name;
- vicam->win.brightness = 128;
- vicam->win.contrast = 10;
+ memset(cam, 0, sizeof (struct vicam_camera));
- /* FIXME */
- if (vicam_init(vicam)) {
- usb_free_urb(vicam->readurb);
- kfree(vicam);
- return -ENOMEM;
- }
- memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
- memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
-
- if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
- err("video_register_device");
- usb_free_urb(vicam->readurb);
- kfree(vicam);
+ cam->shutter_speed = 15;
+
+ init_MUTEX(&cam->busy_lock);
+
+ memcpy(&cam->vdev, &vicam_template,
+ sizeof (vicam_template));
+ cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only
+
+ cam->udev = dev;
+ cam->bulkEndpoint = bulkEndpoint;
+
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
+ kfree(cam);
+ printk(KERN_WARNING "video_register_device failed\n");
return -EIO;
}
- info("registered new video device: video%d", vicam->vdev.minor);
-
- init_MUTEX (&vicam->sem);
- init_waitqueue_head(&vicam->wait);
+ printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
+
+ dev_set_drvdata(&intf->dev, cam);
- dev_set_drvdata (&intf->dev, vicam);
return 0;
}
-
-/* FIXME - vicam_disconnect - important */
-static void vicam_disconnect(struct usb_interface *intf)
+static void
+vicam_disconnect(struct usb_interface *intf)
{
- struct usb_vicam *vicam;
+ struct vicam_camera *cam = dev_get_drvdata(&intf->dev);
- vicam = dev_get_drvdata (&intf->dev);
+ dev_set_drvdata ( &intf->dev, NULL );
+ usb_put_dev(cam->udev);
+
+ cam->udev = NULL;
+
+ video_unregister_device(&cam->vdev);
- dev_set_drvdata (&intf->dev, NULL);
+#ifdef CONFIG_PROC_FS
+ vicam_destroy_proc_entry(cam);
+#endif
- if (vicam) {
- video_unregister_device(&vicam->vdev);
- vicam->udev = NULL;
-/*
- vicam->frame[0].grabstate = FRAME_ERROR;
- vicam->frame[1].grabstate = FRAME_ERROR;
-*/
+ if (cam->raw_image)
+ kfree(cam->raw_image);
+ if (cam->framebuf)
+ rvfree(cam->framebuf,
+ VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
- /* Free buffers and shit */
- info("%s disconnected", vicam->camera_name);
- synchronize(vicam);
+ kfree(cam);
- if (!vicam->open_count) {
- /* Other random junk */
- usb_free_urb(vicam->readurb);
- kfree(vicam);
- vicam = NULL;
- }
- }
+ printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
}
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver vicam_driver = {
- .owner = THIS_MODULE,
- .name = "vicam",
- .probe = vicam_probe,
- .disconnect = vicam_disconnect,
- .id_table = vicam_table,
-};
-
-/******************************************************************************
- *
- * Module Routines
- *
- ******************************************************************************/
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-/* Module paramaters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-static int __init usb_vicam_init(void)
+/*
+ */
+static int __init
+usb_vicam_init(void)
{
- int result;
-
- printk("VICAM: initializing\n");
- /* register this driver with the USB subsystem */
- result = usb_register(&vicam_driver);
- if (result < 0) {
- err("usb_register failed for the "__FILE__" driver. Error number %d",
- result);
- return -1;
- }
-
- info(DRIVER_VERSION " " DRIVER_AUTHOR);
- info(DRIVER_DESC);
+ DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
+#ifdef CONFIG_PROC_FS
+ vicam_create_proc_root();
+#endif
+ if (usb_register(&vicam_driver) != 0)
+ printk(KERN_WARNING "usb_register failed!\n");
return 0;
}
-static void __exit usb_vicam_exit(void)
+static void __exit
+usb_vicam_exit(void)
{
- /* deregister this driver with the USB subsystem */
+ DBG(KERN_INFO
+ "ViCam-based WebCam driver shutdown\n");
+
usb_deregister(&vicam_driver);
+#ifdef CONFIG_PROC_FS
+ vicam_destroy_proc_root();
+#endif
}
module_init(usb_vicam_init);
module_exit(usb_vicam_exit);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/media/vicam.h b/drivers/usb/media/vicam.h
deleted file mode 100644
index 4527d8e644f7..000000000000
--- a/drivers/usb/media/vicam.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *
- * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
- * Christopher L Cheney (C) 2001
- *
- */
-
-#ifndef __LINUX_VICAM_H
-#define __LINUX_VICAM_H
-
-
-#ifdef CONFIG_USB_DEBUG
- static int debug = 1;
-#else
- static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-#define VICAM_NUMFRAMES 30
-#define VICAM_NUMSBUF 1
-
-/* USB REQUEST NUMBERS */
-#define VICAM_REQ_VENDOR 0xff
-#define VICAM_REQ_CAMERA_POWER 0x50
-#define VICAM_REQ_CAPTURE 0x51
-#define VICAM_REQ_LED_CONTROL 0x55
-#define VICAM_REQ_GET_SOMETHIN 0x56
-
-/* not required but lets you know camera is on */
-/* camera must be on to turn on led */
-/* 0x01 always on 0x03 on when picture taken (flashes) */
-
-struct picture_parm
-{
- int width;
- int height;
- int brightness;
- int hue;
- int colour;
- int contrast;
- int whiteness;
- int depth;
- int palette;
-};
-
-struct vicam_scratch {
- unsigned char *data;
- volatile int state;
- int offset;
- int length;
-};
-
-/* Structure to hold all of our device specific stuff */
-struct usb_vicam
-{
- struct video_device vdev;
- struct usb_device *udev;
-
- int open_count; /* number of times this port has been opened */
- struct semaphore sem; /* locks this structure */
- wait_queue_head_t wait; /* Processes waiting */
-
- int streaming;
-
- /* v4l stuff */
- char *camera_name;
- char *fbuf;
- struct urb *urb[VICAM_NUMSBUF];
- int sizes;
- int *width;
- int *height;
- int maxframesize;
- struct picture_parm win;
- struct proc_dir_entry *proc_entry; /* /proc/se401/videoX */
- struct urb *readurb;
-};
-
-#endif
diff --git a/drivers/usb/media/vicamurbs.h b/drivers/usb/media/vicamurbs.h
deleted file mode 100644
index 5068d01330c3..000000000000
--- a/drivers/usb/media/vicamurbs.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- *
- * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
- * Christopher L Cheney (C) 2001
- *
- */
-
-
-#ifndef __LINUX_VICAMURBS_H
-#define __LINUX_VICAMURBS_H
-
-/* -------------------------------------------------------------------------- */
-
-/* FIXME - Figure out transfers so that this doesn't need to be here
- *
- * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
-
-/* Request 0x51 Image Setup */
-
-#if 0
-/* 128x98 ? 0x3180 size */
-static unsigned char s128x98bw[] = {
- 0, 0x34, 0xC4, 0x00, 0x00, 0x00, 0, 0,
- 0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-#endif
-
-/* 128x122 3D80 size */
-static unsigned char s128x122bw[] = {
- 0, 0x34, 0xF4, 0x00, 0x00, 0x00, 0, 0,
- 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* 256x242 ? 0xF280 size */
-static unsigned char s256x242bw[] = {
- 0, 0x03, 0xC8, 0x03, 0x00, 0x00, 0, 0,
- 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* 512x242 0x1E480 size */
-static unsigned char s512x242bw[] = {
- 0, 0x05, 0x90, 0x07, 0x00, 0x00, 0, 0,
- 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* In s512x242:
- byte 0: gain -- higher number means brighter image
- byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
-*/
-
-/* -------------------------------------------------------------------------- */
-
-static unsigned char fsetup[] = {
- 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
-
- 0x00, 0x00
-};
-
-static unsigned char firmware1[] = {
- 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
-
- 0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
- 0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
- 0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
- 0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
-};
-
-static unsigned char findex1[] = {
- 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
-
- 0x18, 0x00, 0x00, 0x00
-};
-
-static unsigned char firmware2[] = {
- 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
-
- 0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
- 0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
- 0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
- 0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
- 0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
- 0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
- 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
- 0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
- 0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
- 0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
- 0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
- 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
- 0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
- 0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
- 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
- 0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
- 0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
- 0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
- 0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
- 0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
- 0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
- 0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
- 0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
- 0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
- 0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
- 0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
- 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
- 0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
- 0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
- 0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
- 0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
- 0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
- 0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
- 0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
- 0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
- 0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
- 0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
- 0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
- 0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
- 0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
- 0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
- 0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
- 0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
- 0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
- 0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
- 0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
- 0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
- 0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
- 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
- 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
- 0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
- 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
- 0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
- 0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
- 0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
- 0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
- 0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
- 0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
- 0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
- 0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
- 0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
- 0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
- 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
- 0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
- 0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
- 0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
- 0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
- 0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
- 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
- 0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
- 0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
- 0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
- 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
- 0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
- 0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
- 0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
- 0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
- 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
- 0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
- 0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
- 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
- 0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
- 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
- 0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
- 0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
- 0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
- 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
- 0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
- 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
- 0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
- 0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
- 0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
- 0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
- 0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
- 0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
- 0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
- 0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
- 0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
- 0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
- 0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
- 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
- 0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
- 0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
- 0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
- 0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
- 0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
- 0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
- 0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
- 0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
- 0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
- 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
- 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
- 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
- 0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
- 0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
- 0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
- 0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
- 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
- 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
- 0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
- 0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
- 0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
- 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
- 0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
- 0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
- 0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
- 0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
- 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
- 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
- 0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
- 0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
- 0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
- 0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
- 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
- 0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
- 0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
- 0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
- 0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
- 0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
- 0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
- 0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
- 0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
- 0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
- 0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
- 0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
- 0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
- 0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
- 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
- 0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
- 0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
- 0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
- 0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
- 0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
- 0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
- 0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
- 0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
- 0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
- 0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
- 0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
- 0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
- 0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
- 0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
- 0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
- 0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
- 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
- 0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
- 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
- 0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
- 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
- 0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
- 0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
- 0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
- 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
- 0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
- 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
- 0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
- 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
- 0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
- 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
- 0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
- 0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
- 0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
- 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
- 0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
- 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
- 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
- 0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char findex2[] = {
- 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
-
- 0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
- 0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
- 0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
- 0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
- 0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
- 0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
- 0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
- 0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
- 0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
- 0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
- 0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
- 0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
- 0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
- 0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
- 0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
- 0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
- 0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
- 0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
- 0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
- 0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
- 0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
- 0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
- 0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
- 0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
- 0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
- 0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
- 0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
- 0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
- 0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
- 0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
- 0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
- 0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
- 0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
- 0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
- 0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
- 0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
- 0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
- 0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
-};
-
-#endif
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 45c76c1b8b97..15b5030ebee8 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -2092,7 +2092,7 @@ static const struct usb_device_id products [] = {
#ifdef CONFIG_USB_EPSON2888
{
USB_DEVICE (0x0525, 0x2888), // EPSON USB client
- driver_info: (unsigned long) &epson2888_info,
+ .driver_info = (unsigned long) &epson2888_info,
},
#endif
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 81fa9f2479eb..11ec19125bcd 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2617,47 +2617,47 @@ static void edge_shutdown (struct usb_serial *serial)
static struct usb_serial_device_type edgeport_1port_device = {
- owner: THIS_MODULE,
- name: "Edgeport TI 1 port adapter",
- id_table: edgeport_1port_id_table,
- num_interrupt_in: 1,
- num_bulk_in: 1,
- num_bulk_out: 1,
- num_ports: 1,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- attach: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
+ .owner = THIS_MODULE,
+ .name = "Edgeport TI 1 port adapter",
+ .id_table = edgeport_1port_id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = edge_open,
+ .close = edge_close,
+ .throttle = edge_throttle,
+ .unthrottle = edge_unthrottle,
+ .attach = edge_startup,
+ .shutdown = edge_shutdown,
+ .ioctl = edge_ioctl,
+ .set_termios = edge_set_termios,
+ .write = edge_write,
+ .write_room = edge_write_room,
+ .chars_in_buffer = edge_chars_in_buffer,
+ .break_ctl = edge_break,
};
static struct usb_serial_device_type edgeport_2port_device = {
- owner: THIS_MODULE,
- name: "Edgeport TI 2 port adapter",
- id_table: edgeport_2port_id_table,
- num_interrupt_in: 1,
- num_bulk_in: 2,
- num_bulk_out: 2,
- num_ports: 2,
- open: edge_open,
- close: edge_close,
- throttle: edge_throttle,
- unthrottle: edge_unthrottle,
- attach: edge_startup,
- shutdown: edge_shutdown,
- ioctl: edge_ioctl,
- set_termios: edge_set_termios,
- write: edge_write,
- write_room: edge_write_room,
- chars_in_buffer: edge_chars_in_buffer,
- break_ctl: edge_break,
+ .owner = THIS_MODULE,
+ .name = "Edgeport TI 2 port adapter",
+ .id_table = edgeport_2port_id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 2,
+ .num_bulk_out = 2,
+ .num_ports = 2,
+ .open = edge_open,
+ .close = edge_close,
+ .throttle = edge_throttle,
+ .unthrottle = edge_unthrottle,
+ .attach = edge_startup,
+ .shutdown = edge_shutdown,
+ .ioctl = edge_ioctl,
+ .set_termios = edge_set_termios,
+ .write = edge_write,
+ .write_room = edge_write_room,
+ .chars_in_buffer = edge_chars_in_buffer,
+ .break_ctl = edge_break,
};
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 4b133ec1ad66..4cb3cb879e1b 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1237,16 +1237,17 @@ int usb_serial_probe(struct usb_interface *interface,
}
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
-#if 0
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
- if (ifnum == 1) {
- if (((dev->descriptor.idVendor == PL2303_VENDOR_ID) &&
- (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) ||
- ((dev->descriptor.idVendor == ATEN_VENDOR_ID) &&
- (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) {
+ if (((dev->descriptor.idVendor == PL2303_VENDOR_ID) &&
+ (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) ||
+ ((dev->descriptor.idVendor == ATEN_VENDOR_ID) &&
+ (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) {
+ //if (ifnum == 1) {
+ if (interface != &dev->actconfig->interface[0]) {
/* check out the endpoints of the other interface*/
- interface = &dev->actconfig->interface[ifnum ^ 1];
+ //interface = &dev->actconfig->interface[ifnum ^ 1];
+ interface = &dev->actconfig->interface[0];
iface_desc = &interface->altsetting[0];
for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i];
@@ -1259,10 +1260,19 @@ int usb_serial_probe(struct usb_interface *interface,
}
}
}
+
+ /* Now make sure the PL-2303 is configured correctly.
+ * If not, give up now and hope this hack will work
+ * properly during a later invocation of usb_serial_probe
+ */
+ if (num_bulk_in == 0 || num_bulk_out == 0) {
+ info("PL-2303 hack: descriptors matched but endpoints did not");
+ kfree (serial);
+ return -ENODEV;
+ }
}
/* END HORRIBLE HACK FOR PL2303 */
#endif
-#endif
/* found all that we need */
info("%s converter detected", type->name);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 69ede41337e6..65164618696c 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -669,7 +669,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
/* get the interface number */
result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
USB_REQ_GET_INTERFACE,
- USB_DIR_IN | USB_DT_DEVICE,
+ USB_DIR_IN | USB_RECIP_INTERFACE,
0, 0, &data, 1, HZ * 3);
if (result < 0) {
err("%s: get interface number failed: %d", __FUNCTION__, result);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 57ad099241fd..5ba0d8471674 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -334,6 +334,12 @@ static int whiteheat_attach (struct usb_serial *serial)
command_port = &serial->port[COMMAND_PORT];
pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
+ /*
+ * When the module is reloaded the firmware is still there and
+ * the endpoints are still in the usb core unchanged. This is the
+ * unlinking bug in disguise. Same for the call below.
+ */
+ usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, COMMAND_TIMEOUT);
if (ret) {
err("%s: Couldn't send command [%d]", serial->type->name, ret);
@@ -344,6 +350,8 @@ static int whiteheat_attach (struct usb_serial *serial)
}
pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
+ /* See the comment on the usb_clear_halt() above */
+ usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, COMMAND_TIMEOUT);
if (ret) {
err("%s: Couldn't get results [%d]", serial->type->name, ret);
@@ -438,6 +446,10 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
if (retval)
goto exit;
+ /* Work around HCD bugs */
+ usb_clear_halt(port->serial->dev, port->read_urb->pipe);
+ usb_clear_halt(port->serial->dev, port->write_urb->pipe);
+
/* Start reading from the device */
port->read_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
@@ -489,7 +501,8 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
{
dbg("%s - port %d", __FUNCTION__, port->number);
- if (tty_hung_up_p(filp)) {
+ /* filp is NULL when called from usb_serial_disconnect */
+ if (filp && (tty_hung_up_p(filp))) {
return;
}
@@ -1145,6 +1158,9 @@ static int start_command_port(struct usb_serial *serial)
command_info = (struct whiteheat_command_private *)command_port->private;
spin_lock_irqsave(&command_info->lock, flags);
if (!command_info->port_running) {
+ /* Work around HCD bugs */
+ usb_clear_halt(serial->dev, command_port->read_urb->pipe);
+
command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) {
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 8e1514ac51e2..980253839108 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -67,25 +67,23 @@ static int datafab_determine_lun(struct us_data *us,
static inline int
datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
- unsigned int act_len; /* ignored */
-
if (len == 0)
return USB_STOR_XFER_GOOD;
US_DEBUGP("datafab_bulk_read: len = %d\n", len);
- return usb_storage_raw_bulk(us, SCSI_DATA_READ, data, len, &act_len);
+ return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, len, NULL);
}
static inline int
datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
- unsigned int act_len; /* ignored */
-
if (len == 0)
return USB_STOR_XFER_GOOD;
US_DEBUGP("datafab_bulk_write: len = %d\n", len);
- return usb_storage_raw_bulk(us, SCSI_DATA_WRITE, data, len, &act_len);
+ return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ data, len, NULL);
}
@@ -522,6 +520,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
};
+ srb->resid = 0;
if (!us->extra) {
us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO);
if (!us->extra) {
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 13c758c8a0e6..72112d97487a 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -108,72 +108,9 @@ struct freecom_status {
/* All packets (except for status) are 64 bytes long. */
#define FCM_PACKET_LENGTH 64
-/*
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately. For now, it also re-interprets the error codes.
- */
-static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer_amount)
-{
- int i;
- int result = -1;
- struct scatterlist *sg;
- unsigned int total_transferred = 0;
-
- /* was someone foolish enough to request more data than available
- * buffer space? */
- if (transfer_amount > srb->request_bufflen)
- transfer_amount = srb->request_bufflen;
-
- /* are we scatter-gathering? */
- if (srb->use_sg) {
-
- /* loop over all the scatter gather structures and
- * make the appropriate requests for each, until done
- */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++) {
-
- US_DEBUGP("transfer_amount: %d and total_transferred: %d\n", transfer_amount, total_transferred);
-
- /* End this if we're done */
- if (transfer_amount == total_transferred)
- break;
-
- /* transfer the lesser of the next buffer or the
- * remaining data */
- if (transfer_amount - total_transferred >=
- sg[i].length) {
- result = usb_stor_transfer_partial(us,
- sg_address(sg[i]), sg[i].length);
- total_transferred += sg[i].length;
- } else {
- result = usb_stor_transfer_partial(us,
- sg_address(sg[i]),
- transfer_amount - total_transferred);
- total_transferred += transfer_amount - total_transferred;
- }
-
- /* if we get an error, end the loop here */
- if (result)
- break;
- }
- }
- else
- /* no scatter-gather, just make the request */
- result = usb_stor_transfer_partial(us, srb->request_buffer,
- transfer_amount);
-
- /* return the result in the data structure itself */
- srb->result = result;
-}
-
static int
freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
- int ipipe, int opipe, int count)
+ unsigned int ipipe, unsigned int opipe, int count)
{
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
@@ -206,15 +143,15 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
/* Now transfer all of our blocks. */
US_DEBUGP("Start of read\n");
- us_transfer_freecom(srb, us, count);
+ result = usb_stor_bulk_transfer_srb(us, ipipe, srb, count);
US_DEBUGP("freecom_readdata done!\n");
- return USB_STOR_TRANSPORT_GOOD;
+ return result;
}
static int
freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
- int ipipe, int opipe, int count)
+ int unsigned ipipe, unsigned int opipe, int count)
{
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
@@ -248,10 +185,10 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
/* Now transfer all of our blocks. */
US_DEBUGP("Start of write\n");
- us_transfer_freecom(srb, us, count);
+ result = usb_stor_bulk_transfer_srb(us, opipe, srb, count);
US_DEBUGP("freecom_writedata done!\n");
- return USB_STOR_TRANSPORT_GOOD;
+ return result;
}
/*
@@ -262,7 +199,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
{
struct freecom_cb_wrap *fcb;
struct freecom_status *fst;
- int ipipe, opipe; /* We need both pipes. */
+ unsigned int ipipe, opipe; /* We need both pipes. */
int result;
int partial;
int length;
@@ -276,8 +213,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("Freecom TRANSPORT STARTED\n");
/* Get handles for both transports. */
- opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
- ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
+ opipe = us->send_bulk_pipe;
+ ipipe = us->recv_bulk_pipe;
/* The ATAPI Command always goes out first. */
fcb->Type = FCM_PACKET_ATAPI | 0x00;
@@ -515,8 +452,7 @@ freecom_init (struct us_data *us)
}
}
- result = usb_control_msg(us->pusb_dev,
- usb_rcvctrlpipe(us->pusb_dev, 0),
+ result = usb_control_msg(us->pusb_dev, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
buffer[32] = '\0';
US_DEBUGP("String returned from FC init is: %s\n", buffer);
@@ -528,8 +464,7 @@ freecom_init (struct us_data *us)
*/
/* send reset */
- result = usb_control_msg(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from activate reset is %d\n", result);
@@ -537,8 +472,7 @@ freecom_init (struct us_data *us)
mdelay(250);
/* clear reset */
- result = usb_control_msg(us->pusb_dev,
- usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from clear reset is %d\n", result);
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index f89bd597bbfe..76b1782a24c2 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -50,7 +50,7 @@ int usb_stor_euscsi_init(struct us_data *us)
int result;
US_DEBUGP("Attempting to init eUSCSI bridge...\n");
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
0x01, 0x0, &data, 0x1, 5*HZ);
US_DEBUGP("-- result is %d\n", result);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index f80db3ba115b..5fb82bfaa294 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -408,13 +408,13 @@ static int isd200_transfer_partial( struct us_data *us,
{
int result;
int partial;
- int pipe;
+ unsigned int pipe;
/* calculate the appropriate pipe information */
if (dataDirection == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+ pipe = us->recv_bulk_pipe;
else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+ pipe = us->send_bulk_pipe;
/* transfer the data */
US_DEBUGP("isd200_transfer_partial(): xfer %d bytes\n", length);
@@ -546,7 +546,6 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
struct bulk_cb_wrap bcb;
struct bulk_cs_wrap bcs;
int result;
- int pipe;
int partial;
unsigned int transfer_amount;
@@ -566,9 +565,6 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
bcb.Length = AtaCdbLength;
- /* construct the pipe handle */
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, AtaCdb, bcb.Length);
@@ -578,8 +574,8 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
le32_to_cpu(bcb.Signature), bcb.Tag,
(bcb.Lun >> 4), (bcb.Lun & 0xFF),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
- result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
- &partial);
+ result = usb_stor_bulk_msg(us, &bcb, us->send_bulk_pipe,
+ US_BULK_CB_WRAP_LEN, &partial);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* did we abort this command? */
@@ -589,8 +585,9 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
else if (result == -EPIPE) {
/* if we stall, we need to clear it before we go on */
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- if (usb_stor_clear_halt(us, pipe) < 0)
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
+ us->send_bulk_pipe);
+ if (usb_stor_clear_halt(us, us->send_bulk_pipe) < 0)
return ISD200_TRANSPORT_ERROR;
} else if (result)
return ISD200_TRANSPORT_ERROR;
@@ -608,13 +605,10 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
* an explanation of how this code works.
*/
- /* construct the pipe handle */
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
- &partial);
+ result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
+ US_BULK_CS_WRAP_LEN, &partial);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
return ISD200_TRANSPORT_ABORTED;
@@ -622,13 +616,14 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
/* did the attempt to read the CSW fail? */
if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- if (usb_stor_clear_halt(us, pipe) < 0)
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
+ us->recv_bulk_pipe);
+ if (usb_stor_clear_halt(us, us->recv_bulk_pipe) < 0)
return ISD200_TRANSPORT_ERROR;
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe,
+ result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
US_BULK_CS_WRAP_LEN, &partial);
/* if the command was aborted, indicate that */
@@ -638,8 +633,9 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
- US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
- usb_stor_clear_halt(us, pipe);
+ US_DEBUGP("clearing halt for pipe 0x%x\n",
+ us->recv_bulk_pipe);
+ usb_stor_clear_halt(us, us->recv_bulk_pipe);
return ISD200_TRANSPORT_ERROR;
}
}
@@ -937,7 +933,7 @@ int isd200_write_config( struct us_data *us )
/* let's send the command via the control pipe */
result = usb_stor_control_msg(
us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ us->send_ctrl_pipe,
0x01,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x0000,
@@ -978,7 +974,7 @@ int isd200_read_config( struct us_data *us )
result = usb_stor_control_msg(
us,
- usb_rcvctrlpipe(us->pusb_dev,0),
+ us->recv_ctrl_pipe,
0x02,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x0000,
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 34e639762b69..e599c83fbc31 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -62,13 +62,12 @@ static inline int jumpshot_bulk_read(struct us_data *us,
unsigned char *data,
unsigned int len)
{
- unsigned int act_len; /* ignored */
-
if (len == 0)
return USB_STOR_XFER_GOOD;
US_DEBUGP("jumpshot_bulk_read: len = %d\n", len);
- return usb_storage_raw_bulk(us, SCSI_DATA_READ, data, len, &act_len);
+ return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, len, NULL);
}
@@ -76,13 +75,12 @@ static inline int jumpshot_bulk_write(struct us_data *us,
unsigned char *data,
unsigned int len)
{
- unsigned int act_len; /* ignored */
-
if (len == 0)
return USB_STOR_XFER_GOOD;
US_DEBUGP("jumpshot_bulk_write: len = %d\n", len);
- return usb_storage_raw_bulk(us, SCSI_DATA_WRITE, data, len, &act_len);
+ return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ data, len, NULL);
}
@@ -95,12 +93,11 @@ static int jumpshot_get_status(struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
// send the setup
- rc = usb_storage_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev, 0),
+ rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
0, 0xA0, 0, 7, &reply, 1);
- if (rc != USB_STOR_TRANSPORT_GOOD)
- return rc;
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
if (reply != 0x50) {
US_DEBUGP("jumpshot_get_status: 0x%2x\n",
@@ -160,10 +157,9 @@ static int jumpshot_read_data(struct us_data *us,
command[5] |= (sector >> 24) & 0x0F;
// send the setup + command
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
0, 0x20, 0, 1, command, 7);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result != USB_STOR_XFER_GOOD)
goto leave;
// read the result
@@ -247,9 +243,10 @@ static int jumpshot_write_data(struct us_data *us,
command[5] |= (sector >> 24) & 0x0F;
// send the setup + command
- result = usb_storage_send_control(
- us, usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
0, 0x20, 0, 1, command, 7);
+ if (result != USB_STOR_XFER_GOOD)
+ goto leave;
// send the data
result = jumpshot_bulk_write(us, ptr, len);
@@ -302,11 +299,10 @@ static int jumpshot_id_device(struct us_data *us,
return USB_STOR_TRANSPORT_ERROR;
// send the setup
- rc = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
+ rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
0, 0x20, 0, 6, command, 2);
- if (rc != USB_STOR_TRANSPORT_GOOD) {
+ if (rc != USB_STOR_XFER_GOOD) {
US_DEBUGP("jumpshot_id_device: Gah! "
"send_control for read_capacity failed\n");
return rc;
@@ -468,7 +464,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
};
-
+ srb->resid = 0;
if (!us->extra) {
us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO);
if (!us->extra) {
diff --git a/drivers/usb/storage/raw_bulk.c b/drivers/usb/storage/raw_bulk.c
index 4e3b755d5cdc..eef495ea97b5 100644
--- a/drivers/usb/storage/raw_bulk.c
+++ b/drivers/usb/storage/raw_bulk.c
@@ -13,219 +13,6 @@
#include "transport.h"
#include "raw_bulk.h"
-#ifdef CONFIG_USB_STORAGE_DEBUG
-#define DEBUG_PRCT 12
-#else
-#define DEBUG_PRCT 0
-#endif
-
-/*
- * Send a control message and wait for the response.
- *
- * us - the pointer to the us_data structure for the device to use
- *
- * request - the URB Setup Packet's first 6 bytes. The first byte always
- * corresponds to the request type, and the second byte always corresponds
- * to the request. The other 4 bytes do not correspond to value and index,
- * since they are used in a custom way by the SCM protocol.
- *
- * xfer_data - a buffer from which to get, or to which to store, any data
- * that gets send or received, respectively, with the URB. Even though
- * it looks like we allocate a buffer in this code for the data, xfer_data
- * must contain enough allocated space.
- *
- * xfer_len - the number of bytes to send or receive with the URB.
- *
- */
-
-int
-usb_storage_send_control(struct us_data *us,
- int pipe,
- unsigned char request,
- unsigned char requesttype,
- unsigned int value,
- unsigned int index,
- unsigned char *xfer_data,
- unsigned int xfer_len) {
-
- int result;
-
- // Send the URB to the device and wait for a response.
-
- /* Why are request and request type reversed in this call? */
-
- result = usb_stor_control_msg(us, pipe,
- request, requesttype, value, index,
- xfer_data, xfer_len);
-
- /* did we abort this command? */
- if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
- US_DEBUGP("usb_stor_send_control(): transfer aborted\n");
- return USB_STOR_TRANSPORT_ABORTED;
- }
-
- // Check the return code for the command.
- if (result < 0) {
-
- /* a stall indicates a protocol error */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-int
-usb_storage_raw_bulk(struct us_data *us, int direction, unsigned char *data,
- unsigned int len, unsigned int *act_len) {
-
- int result;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, act_len);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("EPIPE: clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n",
- pipe, *act_len);
- if (usb_stor_clear_halt(us, pipe) < 0)
- return USB_STOR_XFER_ERROR;
- return USB_STOR_XFER_STALLED;
- }
-
- /* did we abort this command? */
- if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
- US_DEBUGP("usb_storage_raw_bulk(): transfer aborted\n");
- return USB_STOR_XFER_ABORTED;
- }
-
- if (result) {
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT)
- US_DEBUGP("raw_bulk(): device NAKed\n");
- else if (result == -EOVERFLOW)
- US_DEBUGP("raw_bulk(): babble/overflow\n");
- else if (result == -ECONNRESET)
- US_DEBUGP("raw_bulk(): asynchronous reset\n");
- else if (result != -EPIPE)
- US_DEBUGP("raw_bulk(): unknown error %d\n",
- result);
-
- return USB_STOR_XFER_ERROR;
- }
-
- if (*act_len != len) {
- US_DEBUGP("Warning: Transferred only %d of %d bytes\n",
- *act_len, len);
- return USB_STOR_XFER_SHORT;
- }
-
-#if 0
- US_DEBUGP("raw_bulk(): Transferred %s %d of %d bytes\n",
- (direction == SCSI_DATA_READ) ? "in" : "out",
- *act_len, len);
-#endif
-
- return USB_STOR_XFER_GOOD;
-}
-
-int
-usb_storage_bulk_transport(struct us_data *us, int direction,
- unsigned char *data, unsigned int len,
- int use_sg) {
-
- int result = USB_STOR_XFER_ERROR;
- int transferred = 0;
- int i;
- struct scatterlist *sg;
- unsigned int act_len;
-
- if (len == 0)
- return USB_STOR_XFER_GOOD;
-
-#if DEBUG_PRCT
-
- if (direction == SCSI_DATA_WRITE && !use_sg) {
- char string[64];
-
- /* Debug-print the first N bytes of the write transfer */
-
- strcpy(string, "wr: ");
- for (i=0; i<len && i<DEBUG_PRCT; i++) {
- sprintf(string+strlen(string), "%02X ", data[i]);
- if ((i%16) == 15) {
- US_DEBUGP("%s\n", string);
- strcpy(string, "wr: ");
- }
- }
- if ((i%16)!=0)
- US_DEBUGP("%s\n", string);
- }
-
- US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
- (direction == SCSI_DATA_READ) ? "in" : "out",
- len, use_sg);
-
-#endif /* DEBUG_PRCT */
-
- if (!use_sg)
- result = usb_storage_raw_bulk(us, direction,
- data, len, &act_len);
- else {
- sg = (struct scatterlist *)data;
-
- for (i=0; i<use_sg && transferred<len; i++) {
- unsigned char *buf;
- unsigned int length;
-
- buf = sg_address(sg[i]);
- length = len-transferred;
- if (length > sg[i].length)
- length = sg[i].length;
-
- result = usb_storage_raw_bulk(us, direction,
- buf, length, &act_len);
- if (result != USB_STOR_XFER_GOOD)
- break;
- transferred += length;
- }
- }
-
-#if DEBUG_PRCT
-
- if (direction == SCSI_DATA_READ && !use_sg) {
- char string[64];
-
- /* Debug-print the first N bytes of the read transfer */
-
- strcpy(string, "rd: ");
- for (i=0; i<len && i<act_len && i<DEBUG_PRCT; i++) {
- sprintf(string+strlen(string), "%02X ", data[i]);
- if ((i%16) == 15) {
- US_DEBUGP("%s\n", string);
- strcpy(string, "rd: ");
- }
- }
- if ((i%16)!=0)
- US_DEBUGP("%s\n", string);
- }
-
-#endif /* DEBUG_PRCT */
-
- return result;
-}
-
/*
* The routines below convert scatter-gather to single buffer.
* Some drivers claim this is necessary.
diff --git a/drivers/usb/storage/raw_bulk.h b/drivers/usb/storage/raw_bulk.h
index 0361b39ec1f9..9a0e479eaf2e 100644
--- a/drivers/usb/storage/raw_bulk.h
+++ b/drivers/usb/storage/raw_bulk.h
@@ -1,21 +1,6 @@
#ifndef _USB_STORAGE_RAW_BULK_H_
#define _USB_STORAGE_RAW_BULK_H_
-/* usb bulk */
-extern int usb_storage_send_control(
- struct us_data *us, int pipe,
- unsigned char request, unsigned char requesttype,
- unsigned int value, unsigned int index,
- unsigned char *xfer_data, unsigned int xfer_len);
-
-extern int usb_storage_raw_bulk(
- struct us_data *us, int direction,
- unsigned char *data, unsigned int len, unsigned int *act_len);
-
-extern int usb_storage_bulk_transport(
- struct us_data *us, int direction,
- unsigned char *data, unsigned int len, int use_sg);
-
/* scatter-gather */
extern unsigned char *us_copy_from_sgbuf(
unsigned char *content, int buflen,
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 718759ecd8d4..79ca7238af77 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -224,18 +224,21 @@ sddr09_send_command(struct us_data *us,
unsigned char direction,
unsigned char *xfer_data,
unsigned int xfer_len) {
- int pipe;
+ unsigned int pipe;
unsigned char requesttype = (0x41 | direction);
+ int rc;
// Get the receive or send control pipe number
if (direction == USB_DIR_IN)
- pipe = usb_rcvctrlpipe(us->pusb_dev,0);
+ pipe = us->recv_ctrl_pipe;
else
- pipe = usb_sndctrlpipe(us->pusb_dev,0);
+ pipe = us->send_ctrl_pipe;
- return usb_storage_send_control(us, pipe, request, requesttype,
+ rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype,
0, 0, xfer_data, xfer_len);
+ return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD :
+ USB_STOR_TRANSPORT_ERROR);
}
static int
@@ -276,7 +279,6 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
0x03, LUNBITS, 0, 0, buflen, 0, 0, 0, 0, 0, 0, 0
};
int result;
- unsigned int act_len;
result = sddr09_send_scsi_command(us, command, sizeof(command));
if (result != USB_STOR_TRANSPORT_GOOD) {
@@ -284,7 +286,8 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
return result;
}
- result = usb_storage_raw_bulk(us, SCSI_DATA_READ, sensebuf, buflen, &act_len);
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ sensebuf, buflen, NULL);
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP("request sense bulk in failed\n");
return USB_STOR_TRANSPORT_ERROR;
@@ -343,11 +346,11 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
return result;
}
- result = usb_storage_bulk_transport(us, SCSI_DATA_READ,
- buf, bulklen, use_sg);
+ result = usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe,
+ buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transport in sddr09_read2%d %d\n",
+ US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
x, result);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -510,11 +513,11 @@ sddr09_writeX(struct us_data *us,
return result;
}
- result = usb_storage_bulk_transport(us, SCSI_DATA_WRITE,
- buf, bulklen, use_sg);
+ result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,
+ buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transport in sddr09_writeX %d\n",
+ US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
result);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -592,11 +595,11 @@ sddr09_read_sg_test_only(struct us_data *us) {
if (!buf)
return USB_STOR_TRANSPORT_ERROR;
- result = usb_storage_bulk_transport(us, SCSI_DATA_READ,
- buf, bulklen, 0);
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ buf, bulklen, NULL);
kfree(buf);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transport in sddr09_read_sg %d\n",
+ US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
result);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -631,8 +634,8 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- result = usb_storage_bulk_transport(us, SCSI_DATA_READ,
- data, sizeof(data), 0);
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, sizeof(data), NULL);
*status = data[0];
return (result == USB_STOR_XFER_GOOD ?
USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
@@ -954,7 +957,8 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- result = usb_storage_bulk_transport(us, SCSI_DATA_READ, content, 64, 0);
+ result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ content, 64, NULL);
for (i = 0; i < 4; i++)
deviceID[i] = content[i];
@@ -1368,6 +1372,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ srb->resid = 0;
info = (struct sddr09_card_info *)us->extra;
if (!info) {
nand_init_ecc();
@@ -1544,17 +1549,16 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
if (srb->sc_data_direction == SCSI_DATA_WRITE ||
srb->sc_data_direction == SCSI_DATA_READ) {
+ unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE)
+ ? us->send_bulk_pipe : us->recv_bulk_pipe;
US_DEBUGP("SDDR09: %s %d bytes\n",
(srb->sc_data_direction == SCSI_DATA_WRITE) ?
"sending" : "receiving",
srb->request_bufflen);
- result = usb_storage_bulk_transport(us,
- srb->sc_data_direction,
- srb->request_buffer,
- srb->request_bufflen,
- srb->use_sg);
+ result = usb_stor_bulk_transfer_srb(us, pipe, srb,
+ srb->request_bufflen);
return (result == USB_STOR_XFER_GOOD ?
USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 20c9692c1027..484576cc3c90 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -75,10 +75,13 @@ static int
sddr55_bulk_transport(struct us_data *us, int direction,
unsigned char *data, unsigned int len) {
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
+ unsigned int pipe = (direction == SCSI_DATA_READ) ?
+ us->recv_bulk_pipe : us->send_bulk_pipe;
- if (len)
- info->last_access = jiffies;
- return usb_storage_bulk_transport(us, direction, data, len, 0);
+ if (!len)
+ return USB_STOR_XFER_GOOD;
+ info->last_access = jiffies;
+ return usb_stor_bulk_transfer_buf(us, pipe, data, len, NULL);
}
/* check if card inserted, if there is, update read_only status
@@ -743,6 +746,7 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned short pages;
struct sddr55_card_info *info;
+ srb->resid = 0;
if (!us->extra) {
us->extra = kmalloc(
sizeof(struct sddr55_card_info), GFP_NOIO);
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 21a74c17df38..8bec05bdd5b5 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -50,12 +50,6 @@
#include <linux/errno.h>
#include <linux/slab.h>
-extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size);
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
-
#define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
@@ -69,8 +63,8 @@ int usbat_read(struct us_data *us,
int result;
- result = usb_storage_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->recv_ctrl_pipe,
access,
0xC0,
(u16)reg,
@@ -88,8 +82,8 @@ int usbat_write(struct us_data *us,
int result;
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
access|0x01,
0x40,
short_pack(reg, content),
@@ -114,8 +108,8 @@ int usbat_set_shuttle_features(struct us_data *us,
test_pattern, mask_byte, subcountL, subcountH
};
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x80,
0x40,
0,
@@ -139,8 +133,11 @@ int usbat_read_block(struct us_data *us,
LSB_of(len), MSB_of(len)
};
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ if (!len)
+ return USB_STOR_TRANSPORT_GOOD;
+
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x80,
0x40,
0,
@@ -148,10 +145,11 @@ int usbat_read_block(struct us_data *us,
command,
8);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- result = usb_storage_bulk_transport(us, SCSI_DATA_READ, content, len, use_sg);
+ result = usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe,
+ content, len, use_sg, NULL);
return (result == USB_STOR_XFER_GOOD ?
USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
@@ -178,8 +176,8 @@ int usbat_wait_not_busy(struct us_data *us, int minutes) {
result = usbat_read(us, USBAT_ATA, 0x17, &status);
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result!=USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
if (status&0x01) { // check condition
result = usbat_read(us, USBAT_ATA, 0x10, &status);
return USB_STOR_TRANSPORT_FAILED;
@@ -221,8 +219,11 @@ int usbat_write_block(struct us_data *us,
LSB_of(len), MSB_of(len)
};
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ if (!len)
+ return USB_STOR_TRANSPORT_GOOD;
+
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x80,
0x40,
0,
@@ -230,10 +231,11 @@ int usbat_write_block(struct us_data *us,
command,
8);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- result = usb_storage_bulk_transport(us, SCSI_DATA_WRITE, content, len, use_sg);
+ result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,
+ content, len, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -257,6 +259,8 @@ int usbat_rw_block_test(struct us_data *us,
int minutes) {
int result;
+ unsigned int pipe = (direction == SCSI_DATA_READ) ?
+ us->recv_bulk_pipe : us->send_bulk_pipe;
// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
// but that's what came out of the trace every single time.
@@ -292,8 +296,8 @@ int usbat_rw_block_test(struct us_data *us,
* that, we just return a failure.
*/
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x80,
0x40,
0,
@@ -301,16 +305,16 @@ int usbat_rw_block_test(struct us_data *us,
(i==0 ? command : command+8),
(i==0 ? 16 : 8));
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
if (i==0) {
- result = usb_storage_bulk_transport(us,
- SCSI_DATA_WRITE,
- data, num_registers*2, 0);
+ result = usb_stor_bulk_transfer_buf(us,
+ us->send_bulk_pipe,
+ data, num_registers*2, NULL);
- if (result!=USB_STOR_XFER_GOOD)
+ if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
@@ -320,8 +324,8 @@ int usbat_rw_block_test(struct us_data *us,
// direction == SCSI_DATA_WRITE ? "out" : "in",
// len, use_sg);
- result = usb_storage_bulk_transport(us,
- direction, content, len, use_sg);
+ result = usb_stor_bulk_transfer_sg(us,
+ pipe, content, len, use_sg, NULL);
/*
* If we get a stall on the bulk download, we'll retry
@@ -352,8 +356,7 @@ int usbat_rw_block_test(struct us_data *us,
if (direction==SCSI_DATA_READ && i==0) {
if (usb_stor_clear_halt(us,
- usb_sndbulkpipe(us->pusb_dev,
- us->ep_out)) < 0)
+ us->send_bulk_pipe) < 0)
return USB_STOR_TRANSPORT_ERROR;
}
@@ -365,8 +368,8 @@ int usbat_rw_block_test(struct us_data *us,
direction==SCSI_DATA_WRITE ? 0x17 : 0x0E,
&status);
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result!=USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
if (status&0x01) // check condition
return USB_STOR_TRANSPORT_FAILED;
if (status&0x20) // device fault
@@ -412,8 +415,8 @@ int usbat_multiple_write(struct us_data *us,
data[1+(i<<1)] = data_out[i];
}
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x80,
0x40,
0,
@@ -421,11 +424,11 @@ int usbat_multiple_write(struct us_data *us,
command,
8);
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- result = usb_storage_bulk_transport(us,
- SCSI_DATA_WRITE, data, num_registers*2, 0);
+ result = usb_stor_bulk_transfer_buf(us,
+ us->send_bulk_pipe, data, num_registers*2, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -438,8 +441,8 @@ int usbat_read_user_io(struct us_data *us,
int result;
- result = usb_storage_send_control(us,
- usb_rcvctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->recv_ctrl_pipe,
0x82,
0xC0,
0,
@@ -456,8 +459,8 @@ int usbat_write_user_io(struct us_data *us,
int result;
- result = usb_storage_send_control(us,
- usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us,
+ us->send_ctrl_pipe,
0x82,
0x40,
short_pack(enable_flags, data_flags),
@@ -589,7 +592,6 @@ int usbat_handle_read10(struct us_data *us,
static int hp_8200e_select_and_test_registers(struct us_data *us) {
- int result;
int selector;
unsigned char status;
@@ -597,44 +599,44 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) {
for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
- if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_write(us, USBAT_ATA, 0x16, selector) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x17, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x16, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_write(us, USBAT_ATA, 0x14, 0x55) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_write(us, USBAT_ATA, 0x15, 0xAA) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
}
- return result;
+ return USB_STOR_TRANSPORT_GOOD;
}
int init_8200e(struct us_data *us) {
@@ -644,44 +646,44 @@ int init_8200e(struct us_data *us) {
// Enable peripheral control signals
- if ( (result = usbat_write_user_io(us,
+ if (usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
+ USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 1\n");
wait_ms(2000);
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 2\n");
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 3\n");
// Reset peripheral, enable periph control signals
// (bring reset signal up)
- if ( (result = usbat_write_user_io(us,
+ if (usbat_write_user_io(us,
USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
+ USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 4\n");
// Enable periph control signals
// (bring reset signal down)
- if ( (result = usbat_write_user_io(us,
+ if (usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
+ USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 5\n");
@@ -689,23 +691,23 @@ int init_8200e(struct us_data *us) {
// Write 0x80 to ISA port 0x3F
- if ( (result = usbat_write(us, USBAT_ISA, 0x3F, 0x80)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_write(us, USBAT_ISA, 0x3F, 0x80) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 6\n");
// Read ISA port 0x27
- if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read(us, USBAT_ISA, 0x27, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 7\n");
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 8\n");
@@ -715,32 +717,32 @@ int init_8200e(struct us_data *us) {
US_DEBUGP("INIT 9\n");
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 10\n");
// Enable periph control signals and card detect
- if ( (result = usbat_write_user_io(us,
+ if (usbat_write_user_io(us,
USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
+ USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 11\n");
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 12\n");
wait_ms(1400);
- if ( (result = usbat_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_read_user_io(us, &status) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 13\n");
@@ -750,14 +752,14 @@ int init_8200e(struct us_data *us) {
US_DEBUGP("INIT 14\n");
- if ( (result = usbat_set_shuttle_features(us,
- 0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ if (usbat_set_shuttle_features(us,
+ 0x83, 0x00, 0x88, 0x08, 0x15, 0x14) !=
+ USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 15\n");
- return result;
+ return USB_STOR_TRANSPORT_ERROR;
}
/*
@@ -773,6 +775,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
int i;
char string[64];
+ srb->resid = 0;
len = srb->request_bufflen;
/* Send A0 (ATA PACKET COMMAND).
@@ -863,17 +866,16 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
// How many bytes to read in? Check cylL register
- if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
+ USB_STOR_XFER_GOOD) {
+ return USB_STOR_TRANSPORT_ERROR;
}
- if (len>0xFF) { // need to read cylH also
+ if (len > 0xFF) { // need to read cylH also
len = status;
- if ( (result = usbat_read(us, USBAT_ATA, 0x15,
- &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
+ if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
+ USB_STOR_XFER_GOOD) {
+ return USB_STOR_TRANSPORT_ERROR;
}
len += ((unsigned int)status)<<8;
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 9303b8b502a7..6281a3e5e81a 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -488,7 +488,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
/* This is our function to emulate usb_bulk_msg() with enough control
* to make aborts/resets/timeouts work
*/
-int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
+int usb_stor_bulk_msg(struct us_data *us, void *data, unsigned int pipe,
unsigned int len, unsigned int *act_len)
{
int status;
@@ -515,13 +515,12 @@ int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
* Since many vendors in this space limit their testing to interoperability
* with these two OSes, specification violations like this one are common.
*/
-int usb_stor_clear_halt(struct us_data *us, int pipe)
+int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
{
int result;
int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
- result = usb_stor_control_msg(us,
- usb_sndctrlpipe(us->pusb_dev, 0),
+ result = usb_stor_control_msg(us, us->send_ctrl_pipe,
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
endp, NULL, 0); /* note: no 3*HZ timeout */
US_DEBUGP("usb_stor_clear_halt: result=%d\n", result);
@@ -542,37 +541,81 @@ int usb_stor_clear_halt(struct us_data *us, int pipe)
}
/*
- * Transfer one SCSI scatter-gather buffer via bulk transfer
+ * Transfer one control message
*
- * Note that this function is necessary because we want the ability to
- * use scatter-gather memory. Good performance is achieved by a combination
- * of scatter-gather and clustering (which makes each chunk bigger).
+ * This function does basically the same thing as usb_stor_control_msg()
+ * above, except that return codes are USB_STOR_XFER_xxx rather than the
+ * urb status or transfer length.
+ */
+int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ u8 request, u8 requesttype, u16 value, u16 index,
+ void *data, u16 size) {
+ int result;
+
+ US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
+ "value=%04x index=%02x len=%d\n",
+ request, requesttype, value, index, size);
+ result = usb_stor_control_msg(us, pipe, request, requesttype,
+ value, index, data, size);
+ US_DEBUGP("usb_stor_control_msg returned %d\n", result);
+
+ /* did we abort this command? */
+ if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+ US_DEBUGP("-- transfer aborted\n");
+ return USB_STOR_XFER_ABORTED;
+ }
+
+ /* a stall indicates a protocol error */
+ if (result == -EPIPE) {
+ US_DEBUGP("-- stall on control pipe\n");
+ return USB_STOR_XFER_ERROR;
+ }
+
+ /* some other serious problem here */
+ if (result < 0) {
+ US_DEBUGP("-- unknown error\n");
+ return USB_STOR_XFER_ERROR;
+ }
+
+ /* was the entire command transferred? */
+ if (result < size) {
+ US_DEBUGP("-- transferred only %d bytes\n", result);
+ return USB_STOR_XFER_SHORT;
+ }
+
+ US_DEBUGP("-- transfer completed successfully\n");
+ return USB_STOR_XFER_GOOD;
+}
+
+/*
+ * Transfer one buffer via bulk transfer
+ *
+ * This function does basically the same thing as usb_stor_bulk_msg()
+ * above, except that:
*
- * Note that the lower layer will always retry when a NAK occurs, up to the
- * timeout limit. Thus we don't have to worry about it for individual
- * packets.
+ * 1. If the bulk pipe stalls during the transfer, the halt is
+ * automatically cleared;
+ * 2. Return codes are USB_STOR_XFER_xxx rather than the
+ * urb status or transfer length.
*/
-int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
+int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+ char *buf, unsigned int length, unsigned int *act_len)
{
int result;
int partial;
- int pipe;
-
- /* calculate the appropriate pipe information */
- if (us->srb->sc_data_direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
/* transfer the data */
- US_DEBUGP("usb_stor_transfer_partial(): xfer %d bytes\n", length);
+ US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %d bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
result, partial, length);
+ if (act_len)
+ *act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
+ " stalled at %d bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
@@ -580,25 +623,25 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
- US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
+ US_DEBUGP("-- transfer aborted\n");
return USB_STOR_XFER_ABORTED;
}
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT) {
- US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
+ US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result) {
- US_DEBUGP("usb_stor_transfer_partial(): unknown error\n");
+ US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* did we send all the data? */
if (partial == length) {
- US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n");
+ US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
@@ -611,59 +654,51 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
*
- * Note that this uses usb_stor_transfer_partial to achieve its goals -- this
+ * Note that this uses usb_stor_transfer_buf to achieve its goals -- this
* function simply determines if we're going to use scatter-gather or not,
* and acts appropriately. For now, it also re-interprets the error codes.
*/
-void usb_stor_transfer(Scsi_Cmnd *srb, struct us_data* us)
+int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
+ char *buf, unsigned int length_left, int use_sg, int *residual)
{
int i;
int result = -1;
struct scatterlist *sg;
- unsigned int total_transferred = 0;
- unsigned int transfer_amount;
-
- /* calculate how much we want to transfer */
- transfer_amount = usb_stor_transfer_length(srb);
-
- /* was someone foolish enough to request more data than available
- * buffer space? */
- if (transfer_amount > srb->request_bufflen)
- transfer_amount = srb->request_bufflen;
+ unsigned int amount;
+ unsigned int partial;
/* are we scatter-gathering? */
- if (srb->use_sg) {
+ if (use_sg) {
/* loop over all the scatter gather structures and
* make the appropriate requests for each, until done
*/
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++) {
+ sg = (struct scatterlist *) buf;
+ for (i = 0; (i < use_sg) && (length_left > 0); (i++, ++sg)) {
/* transfer the lesser of the next buffer or the
* remaining data */
- if (transfer_amount - total_transferred >=
- sg[i].length) {
- result = usb_stor_transfer_partial(us,
- sg_address(sg[i]), sg[i].length);
- total_transferred += sg[i].length;
- } else
- result = usb_stor_transfer_partial(us,
- sg_address(sg[i]),
- transfer_amount - total_transferred);
+ amount = sg->length < length_left ?
+ sg->length : length_left;
+ result = usb_stor_bulk_transfer_buf(us, pipe,
+ sg_address(*sg), amount, &partial);
+ length_left -= partial;
/* if we get an error, end the loop here */
- if (result)
+ if (result != USB_STOR_XFER_GOOD)
break;
}
- }
- else
+ } else {
/* no scatter-gather, just make the request */
- result = usb_stor_transfer_partial(us, srb->request_buffer,
- transfer_amount);
+ result = usb_stor_bulk_transfer_buf(us, pipe, buf,
+ length_left, &partial);
+ length_left -= partial;
+ }
- /* return the result in the data structure itself */
- srb->result = result;
+ /* store the residual and return the error code */
+ if (residual)
+ *residual = length_left;
+ return result;
}
/***********************************************************************
@@ -742,7 +777,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
* Also, if we have a short transfer on a command that can't have
* a short transfer, we're going to do this.
*/
- if ((srb->result == USB_STOR_XFER_SHORT) &&
+ if ((srb->resid > 0) &&
!((srb->cmnd[0] == REQUEST_SENSE) ||
(srb->cmnd[0] == INQUIRY) ||
(srb->cmnd[0] == MODE_SENSE) ||
@@ -974,6 +1009,7 @@ void usb_stor_CBI_irq(struct urb *urb)
int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
{
+ unsigned int transfer_length = usb_stor_transfer_length(srb);
int result;
/* re-initialize the mutex so that we avoid any races with
@@ -985,14 +1021,14 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* COMMAND STAGE */
/* let's send the command via the control pipe */
- result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
us->ifnum, srb->cmnd, srb->cmd_len);
/* check the return code for the command */
- US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
- if (result < 0) {
+ US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+ if (result != USB_STOR_XFER_GOOD) {
/* Reset flag for status notification */
clear_bit(US_FLIDX_IP_WANTED, &us->flags);
}
@@ -1003,22 +1039,16 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_ABORTED;
}
- /* a stall indicates a protocol error */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- if (result < 0) {
+ if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR;
}
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (usb_stor_transfer_length(srb)) {
- usb_stor_transfer(srb, us);
- result = srb->result;
+ if (transfer_length > 0) {
+ result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
+ srb, transfer_length);
US_DEBUGP("CBI data stage result is 0x%x\n", result);
/* report any errors */
@@ -1093,39 +1123,34 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
*/
int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
{
+ unsigned int transfer_length = usb_stor_transfer_length(srb);
int result;
/* COMMAND STAGE */
/* let's send the command via the control pipe */
- result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
us->ifnum, srb->cmnd, srb->cmd_len);
/* check the return code for the command */
- US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
- if (result < 0) {
- /* did we abort this command? */
- if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
- US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
- return USB_STOR_TRANSPORT_ABORTED;
- }
+ US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
- /* a stall indicates a protocol error */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe\n");
- return USB_STOR_TRANSPORT_ERROR;
- }
+ /* did we abort this command? */
+ if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+ US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
+ return USB_STOR_TRANSPORT_ABORTED;
+ if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */
return USB_STOR_TRANSPORT_ERROR;
}
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (usb_stor_transfer_length(srb)) {
- usb_stor_transfer(srb, us);
- result = srb->result;
+ if (transfer_length)
+ result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
+ srb, transfer_length);
US_DEBUGP("CB data stage result is 0x%x\n", result);
/* report any errors */
@@ -1153,12 +1178,12 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
{
unsigned char data;
int result;
- int pipe;
- /* issue the command -- use usb_control_msg() because
- * this is not a scsi queued-command */
- pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
- result = usb_control_msg(us->pusb_dev, pipe,
+ /* Issue the command -- use usb_control_msg() because this is
+ * not a scsi queued-command. Also note that at this point the
+ * cached pipe values have not yet been stored. */
+ result = usb_control_msg(us->pusb_dev,
+ usb_rcvctrlpipe(us->pusb_dev, 0),
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE,
@@ -1179,13 +1204,13 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
{
struct bulk_cb_wrap bcb;
struct bulk_cs_wrap bcs;
+ unsigned int transfer_length = usb_stor_transfer_length(srb);
int result;
- int pipe;
int partial;
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
+ bcb.DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
@@ -1193,9 +1218,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
bcb.Lun |= srb->target << 4;
bcb.Length = srb->cmd_len;
- /* construct the pipe handle */
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
@@ -1205,8 +1227,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
le32_to_cpu(bcb.Signature), bcb.Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F),
bcb.DataTransferLength, bcb.Flags, bcb.Length);
- result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
- &partial);
+ result = usb_stor_bulk_msg(us, &bcb, us->send_bulk_pipe,
+ US_BULK_CB_WRAP_LEN, &partial);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* did we abort this command? */
@@ -1217,47 +1239,45 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- result = usb_stor_clear_halt(us, pipe);
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
+ us->send_bulk_pipe);
+ result = usb_stor_clear_halt(us, us->send_bulk_pipe);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED;
}
- if (result < 0)
- return USB_STOR_TRANSPORT_ERROR;
- result = -EPIPE;
+ return USB_STOR_TRANSPORT_ERROR;
} else if (result) {
/* unknown error -- we've got a problem */
return USB_STOR_TRANSPORT_ERROR;
}
- /* if the command transfered well, then we go to the data stage */
- if (result == 0) {
- /* send/receive data payload, if there is any */
- if (bcb.DataTransferLength) {
- usb_stor_transfer(srb, us);
- result = srb->result;
- US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-
- /* if it was aborted, we need to indicate that */
- if (result == USB_STOR_XFER_ABORTED)
- return USB_STOR_TRANSPORT_ABORTED;
- }
+ /* DATA STAGE */
+ /* send/receive data payload, if there is any */
+ if (transfer_length) {
+ unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ?
+ us->recv_bulk_pipe : us->send_bulk_pipe;
+ result = usb_stor_bulk_transfer_srb(us, pipe, srb,
+ transfer_length);
+ US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+
+ /* if it was aborted, we need to indicate that */
+ if (result == USB_STOR_XFER_ABORTED)
+ return USB_STOR_TRANSPORT_ABORTED;
+ if (result == USB_STOR_XFER_ERROR)
+ return USB_STOR_TRANSPORT_ERROR;
}
/* See flow chart on pg 15 of the Bulk Only Transport spec for
* an explanation of how this code works.
*/
- /* construct the pipe handle */
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
- &partial);
+ result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
+ US_BULK_CS_WRAP_LEN, &partial);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
@@ -1267,8 +1287,9 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* did the attempt to read the CSW fail? */
if (result == -EPIPE) {
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
- result = usb_stor_clear_halt(us, pipe);
+ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n",
+ us->recv_bulk_pipe);
+ result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
@@ -1280,7 +1301,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
- result = usb_stor_bulk_msg(us, &bcs, pipe,
+ result = usb_stor_bulk_msg(us, &bcs, us->recv_bulk_pipe,
US_BULK_CS_WRAP_LEN, &partial);
/* did we abort this command? */
@@ -1291,8 +1312,9 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
- US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
- result = usb_stor_clear_halt(us, pipe);
+ US_DEBUGP("clearing halt for pipe 0x%x\n",
+ us->recv_bulk_pipe);
+ result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
@@ -1364,7 +1386,7 @@ static int usb_stor_reset_common(struct us_data *us,
* following a powerup or USB attach event. */
/* Use usb_control_msg() because this is not a queued-command */
- result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+ result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
request, requesttype, value, index, data, size,
20*HZ);
if (result < 0)
@@ -1377,14 +1399,12 @@ static int usb_stor_reset_common(struct us_data *us,
/* Use usb_clear_halt() because this is not a queued-command */
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
- result = usb_clear_halt(us->pusb_dev,
- usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
+ result = usb_clear_halt(us->pusb_dev, us->recv_bulk_pipe);
if (result < 0)
goto Done;
US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
- result = usb_clear_halt(us->pusb_dev,
- usb_sndbulkpipe(us->pusb_dev, us->ep_out));
+ result = usb_clear_halt(us->pusb_dev, us->send_bulk_pipe);
Done:
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 914ecb8be155..7b40bc350ae0 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -115,7 +115,7 @@ struct bulk_cs_wrap {
#define US_BULK_GET_MAX_LUN 0xfe
/*
- * usb_stor_transfer() return codes, in order of severity
+ * usb_stor_bulk_transfer_xxx() return codes, in order of severity
*/
#define USB_STOR_XFER_GOOD 0 /* good transfer */
#define USB_STOR_XFER_SHORT 1 /* transfered less than expected */
@@ -151,14 +151,26 @@ extern int usb_stor_Bulk_reset(struct us_data*);
extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern void usb_stor_abort_transport(struct us_data*);
-extern int usb_stor_transfer_partial(struct us_data*, char*, int);
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
+extern int usb_stor_bulk_msg(struct us_data *us, void *data,
+ unsigned int pipe, unsigned int len, unsigned int *act_len);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
-extern int usb_stor_clear_halt(struct us_data*, int );
-extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe);
+extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ u8 request, u8 requesttype, u16 value, u16 index,
+ void *data, u16 size);
+extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+ char *buf, unsigned int length, unsigned int *act_len);
+extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
+ char *buf, unsigned int length, int use_sg, int *residual);
+
+static __inline__ int usb_stor_bulk_transfer_srb(struct us_data *us,
+ unsigned int pipe, Scsi_Cmnd *srb, unsigned int length) {
+ return usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer,
+ length, srb->use_sg, &srb->resid);
+}
+
#endif
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index f423b7e69ab5..6eebb126156d 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -525,6 +525,12 @@ static int usb_stor_allocate_urbs(struct us_data *ss)
int maxp;
int result;
+ /* calculate and store the pipe values */
+ ss->send_bulk_pipe = usb_sndbulkpipe(ss->pusb_dev, ss->ep_out);
+ ss->recv_bulk_pipe = usb_rcvbulkpipe(ss->pusb_dev, ss->ep_in);
+ ss->send_ctrl_pipe = usb_sndctrlpipe(ss->pusb_dev, 0);
+ ss->recv_ctrl_pipe = usb_rcvctrlpipe(ss->pusb_dev, 0);
+
/* allocate the usb_ctrlrequest for control packets */
US_DEBUGP("Allocating usb_ctrlrequest\n");
ss->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 2a9e9a1f6c2e..9b078b5c4c2a 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -134,6 +134,10 @@ struct us_data {
struct semaphore dev_semaphore; /* protect pusb_dev */
struct usb_device *pusb_dev; /* this usb_device */
unsigned long flags; /* from filter initially */
+ unsigned int send_bulk_pipe; /* cached pipe values */
+ unsigned int recv_bulk_pipe;
+ unsigned int send_ctrl_pipe;
+ unsigned int recv_ctrl_pipe;
/* information about the device -- always good */
char vendor[USB_STOR_STRING_LEN];
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 5dbc3cb115f7..fe144bda56f0 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -222,12 +222,42 @@ struct usb_interface_descriptor {
int extralen;
};
+/**
+ * struct usb_interface - what usb device drivers talk to
+ * @altsetting: array of interface descriptors, one for each alternate
+ * setting that may be selected. each one includes a set of
+ * endpoint configurations.
+ * @num_altsetting: number of altsettings defined.
+ * @act_altsetting: index of current altsetting. this number is always
+ * less than num_altsetting. after the device is configured, each
+ * interface uses its default setting of zero.
+ * @dev: driver model's view of this device
+ *
+ * USB device drivers attach to interfaces on a physical device. Each
+ * interface encapsulates a single high level function, such as feeding
+ * an audio stream to a speaker or reporting a change in a volume control.
+ * Many USB devices only have one interface. The protocol used to talk to
+ * an interface's endpoints can be defined in a usb "class" specification,
+ * or by a product's vendor. The (default) control endpoint is part of
+ * every interface, but is never listed among the interface's descriptors.
+ *
+ * The driver that is bound to the interface can use standard driver model
+ * calls such as dev_get_drvdata() on the dev member of this structure.
+ *
+ * Each interface may have alternate settings. The initial configuration
+ * of a device sets the first of these, but the device driver can change
+ * that setting using usb_set_interface(). Alternate settings are often
+ * used to control the the use of periodic endpoints, such as by having
+ * different endpoints use different amounts of reserved USB bandwidth.
+ * All standards-conformant USB devices that use isochronous endpoints
+ * will use them in non-default settings.
+ */
struct usb_interface {
struct usb_interface_descriptor *altsetting;
- int act_altsetting; /* active alternate setting */
- int num_altsetting; /* number of alternate settings */
- int max_altsetting; /* total memory allocated */
+ unsigned act_altsetting; /* active alternate setting */
+ unsigned num_altsetting; /* number of alternate settings */
+ unsigned max_altsetting; /* total memory allocated */
struct usb_driver *driver; /* driver */
struct device dev; /* interface specific device info */
@@ -670,6 +700,7 @@ extern void usb_deregister_dev(int num_minors, int start_minor);
extern int usb_device_probe(struct device *dev);
extern int usb_device_remove(struct device *dev);
+extern int usb_disabled(void);
/* -------------------------------------------------------------------------- */
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 80966ed8e288..a90d968374eb 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -397,6 +397,7 @@ struct video_code
#define VID_HARDWARE_PWC 31 /* Philips webcams */
#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
#define VID_HARDWARE_CPIA2 33
+#define VID_HARDWARE_VICAM 34
#endif /* __LINUX_VIDEODEV_H */