aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-03-01 15:59:52 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-01 15:59:52 -0800
commite449d88200084a27997993b78956a6f2b252f2df (patch)
treeac004a1ce27b9c3a2cb6e25241a81417fb090a43 /usb
parente946d6a860ccbbc527c85411ff97104eb7904018 (diff)
downloadpatches-e449d88200084a27997993b78956a6f2b252f2df.tar.gz
usb patches added
Diffstat (limited to 'usb')
-rw-r--r--usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch182
-rw-r--r--usb/usb-et61x51-driver-updates.patch1211
-rw-r--r--usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch690
-rw-r--r--usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch186
-rw-r--r--usb/usb-pl2303-and-tiocmiwait.patch39
-rw-r--r--usb/usb-serial-dynamic-id.patch6
-rw-r--r--usb/usb-sn9c10x-driver-updates.patch1073
-rw-r--r--usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch42
-rw-r--r--usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch59
-rw-r--r--usb/usb-zc0301-driver-updates-2.patch496
10 files changed, 3981 insertions, 3 deletions
diff --git a/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch b/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch
new file mode 100644
index 0000000000000..a7910af76c86f
--- /dev/null
+++ b/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch
@@ -0,0 +1,182 @@
+From linux-usb-devel-admin@lists.sourceforge.net Wed Mar 1 15:19:12 2006
+Message-ID: <4405CFA4.3010604@austin.rr.com>
+From: Lonnie Mendez <lmendez19@austin.rr.com>
+To: linux-usb-devel@lists.sourceforge.net
+Subject: USB: cypress_m8: add support for the Nokia ca42-version 2 cable
+Date: Wed, 01 Mar 2006 10:45:24 -0600
+
+This patch adds support for the Nokia ca42 version 2 cable to the
+cypress_m8 driver. The device was tested by others with this patch and
+found to be compatible with the cypress_m8 driver. A special note
+should be taken that this cable seems to vary in the type of chipset
+used. This patch supports the cable with product id 0x4101.
+
+Signed-off-by: Lonnie Mendez <lmendez19@austin.rr.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/cypress_m8.c | 70 ++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/serial/cypress_m8.h | 5 ++
+ 2 files changed, 75 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.c
++++ gregkh-2.6/drivers/usb/serial/cypress_m8.c
+@@ -98,10 +98,16 @@ static struct usb_device_id id_table_cyp
+ { } /* Terminating entry */
+ };
+
++static struct usb_device_id id_table_nokiaca42v2 [] = {
++ { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
++ { } /* Terminating entry */
++};
++
+ static struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
+ { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
+ { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
++ { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
+ { } /* Terminating entry */
+ };
+
+@@ -149,6 +155,7 @@ struct cypress_buf {
+ /* function prototypes for the Cypress USB to serial device */
+ static int cypress_earthmate_startup (struct usb_serial *serial);
+ static int cypress_hidcom_startup (struct usb_serial *serial);
++static int cypress_ca42v2_startup (struct usb_serial *serial);
+ static void cypress_shutdown (struct usb_serial *serial);
+ static int cypress_open (struct usb_serial_port *port, struct file *filp);
+ static void cypress_close (struct usb_serial_port *port, struct file *filp);
+@@ -235,6 +242,34 @@ static struct usb_serial_driver cypress_
+ .write_int_callback = cypress_write_int_callback,
+ };
+
++static struct usb_serial_driver cypress_ca42v2_device = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "nokiaca42v2",
++ },
++ .description = "Nokia CA-42 V2 Adapter",
++ .id_table = id_table_nokiaca42v2,
++ .num_interrupt_in = 1,
++ .num_interrupt_out = 1,
++ .num_bulk_in = NUM_DONT_CARE,
++ .num_bulk_out = NUM_DONT_CARE,
++ .num_ports = 1,
++ .attach = cypress_ca42v2_startup,
++ .shutdown = cypress_shutdown,
++ .open = cypress_open,
++ .close = cypress_close,
++ .write = cypress_write,
++ .write_room = cypress_write_room,
++ .ioctl = cypress_ioctl,
++ .set_termios = cypress_set_termios,
++ .tiocmget = cypress_tiocmget,
++ .tiocmset = cypress_tiocmset,
++ .chars_in_buffer = cypress_chars_in_buffer,
++ .throttle = cypress_throttle,
++ .unthrottle = cypress_unthrottle,
++ .read_int_callback = cypress_read_int_callback,
++ .write_int_callback = cypress_write_int_callback,
++};
+
+ /*****************************************************************************
+ * Cypress serial helper functions
+@@ -286,6 +321,12 @@ static int cypress_serial_control (struc
+ __FUNCTION__);
+ new_baudrate = priv->baud_rate;
+ }
++ } else if (priv->chiptype == CT_CA42V2) {
++ if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
++ err("%s - failed setting baud rate, unsupported speed",
++ __FUNCTION__);
++ new_baudrate = priv->baud_rate;
++ }
+ } else if (priv->chiptype == CT_GENERIC) {
+ if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+ err("%s - failed setting baud rate, unsupported speed",
+@@ -499,6 +540,25 @@ static int cypress_hidcom_startup (struc
+ } /* cypress_hidcom_startup */
+
+
++static int cypress_ca42v2_startup (struct usb_serial *serial)
++{
++ struct cypress_private *priv;
++
++ dbg("%s", __FUNCTION__);
++
++ if (generic_startup(serial)) {
++ dbg("%s - Failed setting up port %d", __FUNCTION__,
++ serial->port[0]->number);
++ return 1;
++ }
++
++ priv = usb_get_serial_port_data(serial->port[0]);
++ priv->chiptype = CT_CA42V2;
++
++ return 0;
++} /* cypress_ca42v2_startup */
++
++
+ static void cypress_shutdown (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
+@@ -943,6 +1003,10 @@ static void cypress_set_termios (struct
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
++ } else if (priv->chiptype == CT_CA42V2) {
++ *(tty->termios) = tty_std_termios;
++ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
++ CLOCAL;
+ }
+ priv->termios_initialized = 1;
+ }
+@@ -1541,6 +1605,9 @@ static int __init cypress_init(void)
+ retval = usb_serial_register(&cypress_hidcom_device);
+ if (retval)
+ goto failed_hidcom_register;
++ retval = usb_serial_register(&cypress_ca42v2_device);
++ if (retval)
++ goto failed_ca42v2_register;
+ retval = usb_register(&cypress_driver);
+ if (retval)
+ goto failed_usb_register;
+@@ -1549,6 +1616,8 @@ static int __init cypress_init(void)
+ return 0;
+ failed_usb_register:
+ usb_deregister(&cypress_driver);
++failed_ca42v2_register:
++ usb_serial_deregister(&cypress_ca42v2_device);
+ failed_hidcom_register:
+ usb_serial_deregister(&cypress_hidcom_device);
+ failed_em_register:
+@@ -1565,6 +1634,7 @@ static void __exit cypress_exit (void)
+ usb_deregister (&cypress_driver);
+ usb_serial_deregister (&cypress_earthmate_device);
+ usb_serial_deregister (&cypress_hidcom_device);
++ usb_serial_deregister (&cypress_ca42v2_device);
+ }
+
+
+--- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.h
++++ gregkh-2.6/drivers/usb/serial/cypress_m8.h
+@@ -18,6 +18,10 @@
+ /* Cypress HID->COM RS232 Adapter */
+ #define VENDOR_ID_CYPRESS 0x04b4
+ #define PRODUCT_ID_CYPHIDCOM 0x5500
++
++/* Nokia CA-42 USB to serial cable */
++#define VENDOR_ID_DAZZLE 0x07d0
++#define PRODUCT_ID_CA42 0x4101
+ /* End of device listing */
+
+ /* Used for setting / requesting serial line settings */
+@@ -34,6 +38,7 @@
+
+ #define CT_EARTHMATE 0x01
+ #define CT_CYPHIDCOM 0x02
++#define CT_CA42V2 0x03
+ #define CT_GENERIC 0x0F
+ /* End of chiptype definitions */
+
diff --git a/usb/usb-et61x51-driver-updates.patch b/usb/usb-et61x51-driver-updates.patch
new file mode 100644
index 0000000000000..b2b1b194f4af2
--- /dev/null
+++ b/usb/usb-et61x51-driver-updates.patch
@@ -0,0 +1,1211 @@
+From luca.risolia@studio.unibo.it Fri Feb 24 21:52:39 2006
+Date: Sat, 25 Feb 2006 06:54:18 +0000
+From: Luca Risolia <luca.risolia@studio.unibo.it>
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB: ET61X[12]51 driver updates
+Message-ID: <20060225065418.GB31623@studio.unibo.it>
+Content-Disposition: inline
+
+USB: ET61X[12]51 driver updates
+
+Changes: + new, - removed, * cleanup, @ bugfix
+
+@ Fix stream_interrupt()
+@ Fix vidioc_enum_input() and split vidioc_gs_input()
+@ Need usb_get|put_dev() when disconnecting, if the device is open
+* Use wait_event_interruptible_timeout() instead of wait_event_interruptible()
+ when waiting for video frames
+* replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream)
+* Cleanups and updates in the documentation
+* Use mutexes instead of semaphores
++ Use per-device sensor structures
++ Add support for PAS202BCA image sensors
++ Add frame_timeout module parameter
+
+Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/et61x251.txt | 10
+ drivers/usb/media/et61x251.h | 28 ++
+ drivers/usb/media/et61x251_core.c | 321 +++++++++++++++++---------------
+ drivers/usb/media/et61x251_sensor.h | 5
+ drivers/usb/media/et61x251_tas5130d1b.c | 10
+ 5 files changed, 213 insertions(+), 161 deletions(-)
+
+--- gregkh-2.6.orig/Documentation/usb/et61x251.txt
++++ gregkh-2.6/Documentation/usb/et61x251.txt
+@@ -176,6 +176,14 @@ Description: Force the application to
+ 1 = force memory unmapping (save memory)
+ Default: 0
+ -------------------------------------------------------------------------------
++Name: frame_timeout
++Type: uint array (min = 0, max = 64)
++Syntax: <n[,...]>
++Description: Timeout for a video frame in seconds. This parameter is
++ specific for each detected camera. This parameter can be
++ changed at runtime thanks to the /sys filesystem interface.
++Default: 2
++-------------------------------------------------------------------------------
+ Name: debug
+ Type: ushort
+ Syntax: <n>
+@@ -266,7 +274,7 @@ the V4L2 interface.
+
+
+ 10. Notes for V4L2 application developers
+-========================================
++=========================================
+ This driver follows the V4L2 API specifications. In particular, it enforces two
+ rules:
+
+--- gregkh-2.6.orig/drivers/usb/media/et61x251_core.c
++++ gregkh-2.6/drivers/usb/media/et61x251_core.c
+@@ -25,11 +25,9 @@
+ #include <linux/moduleparam.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+-#include <linux/string.h>
+ #include <linux/device.h>
+ #include <linux/fs.h>
+ #include <linux/delay.h>
+-#include <linux/stddef.h>
+ #include <linux/compiler.h>
+ #include <linux/ioctl.h>
+ #include <linux/poll.h>
+@@ -50,8 +48,8 @@
+ #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
+ #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
+ #define ET61X251_MODULE_LICENSE "GPL"
+-#define ET61X251_MODULE_VERSION "1:1.01"
+-#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1)
++#define ET61X251_MODULE_VERSION "1:1.02"
++#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2)
+
+ /*****************************************************************************/
+
+@@ -90,6 +88,16 @@ MODULE_PARM_DESC(force_munmap,
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
+
++static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
++ ET61X251_FRAME_TIMEOUT};
++module_param_array(frame_timeout, uint, NULL, 0644);
++MODULE_PARM_DESC(frame_timeout,
++ "\n<n[,...]> Timeout for a video frame in seconds."
++ "\nThis parameter is specific for each detected camera."
++ "\nDefault value is "
++ __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"."
++ "\n");
++
+ #ifdef ET61X251_DEBUG
+ static unsigned short debug = ET61X251_DEBUG_LEVEL;
+ module_param(debug, ushort, 0644);
+@@ -111,8 +119,8 @@ static u32
+ et61x251_request_buffers(struct et61x251_device* cam, u32 count,
+ enum et61x251_io_method io)
+ {
+- struct v4l2_pix_format* p = &(cam->sensor->pix_format);
+- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
++ struct v4l2_pix_format* p = &(cam->sensor.pix_format);
++ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
+ const size_t imagesize = cam->module_param.force_munmap ||
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+@@ -268,8 +276,8 @@ et61x251_i2c_try_read(struct et61x251_de
+ int err = 0, res;
+
+ data[0] = address;
+- data[1] = cam->sensor->i2c_slave_id;
+- data[2] = cam->sensor->rsta | 0x10;
++ data[1] = cam->sensor.i2c_slave_id;
++ data[2] = cam->sensor.rsta | 0x10;
+ data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02);
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
+@@ -301,8 +309,8 @@ et61x251_i2c_try_write(struct et61x251_d
+ int err = 0, res;
+
+ data[0] = address;
+- data[1] = cam->sensor->i2c_slave_id;
+- data[2] = cam->sensor->rsta | 0x12;
++ data[1] = cam->sensor.i2c_slave_id;
++ data[2] = cam->sensor.rsta | 0x12;
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+@@ -334,9 +342,6 @@ et61x251_i2c_raw_write(struct et61x251_d
+ u8* data = cam->control_buffer;
+ int err = 0, res;
+
+- if (!cam->sensor)
+- return -1;
+-
+ data[0] = data2;
+ data[1] = data3;
+ data[2] = data4;
+@@ -350,8 +355,8 @@ et61x251_i2c_raw_write(struct et61x251_d
+ err += res;
+
+ data[0] = address;
+- data[1] = cam->sensor->i2c_slave_id;
+- data[2] = cam->sensor->rsta | 0x02 | (n << 4);
++ data[1] = cam->sensor.i2c_slave_id;
++ data[2] = cam->sensor.rsta | 0x02 | (n << 4);
+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ if (res < 0)
+@@ -364,11 +369,11 @@ et61x251_i2c_raw_write(struct et61x251_d
+ if (res < 0)
+ err += res;
+
+- err += et61x251_i2c_wait(cam, cam->sensor);
++ err += et61x251_i2c_wait(cam, &cam->sensor);
+
+ if (err)
+ DBG(3, "I2C raw write failed for %s image sensor",
+- cam->sensor->name);
++ cam->sensor.name);
+
+ PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, "
+ "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X,"
+@@ -382,19 +387,13 @@ et61x251_i2c_raw_write(struct et61x251_d
+
+ int et61x251_i2c_read(struct et61x251_device* cam, u8 address)
+ {
+- if (!cam->sensor)
+- return -1;
+-
+- return et61x251_i2c_try_read(cam, cam->sensor, address);
++ return et61x251_i2c_try_read(cam, &cam->sensor, address);
+ }
+
+
+ int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value)
+ {
+- if (!cam->sensor)
+- return -1;
+-
+- return et61x251_i2c_try_write(cam, cam->sensor, address, value);
++ return et61x251_i2c_try_write(cam, &cam->sensor, address, value);
+ }
+
+ /*****************************************************************************/
+@@ -417,7 +416,7 @@ static void et61x251_urb_complete(struct
+ if ((*f))
+ (*f)->state = F_QUEUED;
+ DBG(3, "Stream interrupted");
+- wake_up_interruptible(&cam->wait_stream);
++ wake_up(&cam->wait_stream);
+ }
+
+ if (cam->state & DEV_DISCONNECTED)
+@@ -435,9 +434,9 @@ static void et61x251_urb_complete(struct
+ (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t,
+ frame);
+
+- imagesize = (cam->sensor->pix_format.width *
+- cam->sensor->pix_format.height *
+- cam->sensor->pix_format.priv) / 8;
++ imagesize = (cam->sensor.pix_format.width *
++ cam->sensor.pix_format.height *
++ cam->sensor.pix_format.priv) / 8;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ unsigned int len, status;
+@@ -476,7 +475,7 @@ start_of_frame:
+
+ if ((*f)->state == F_GRABBING) {
+ if (sof && (*f)->buf.bytesused) {
+- if (cam->sensor->pix_format.pixelformat ==
++ if (cam->sensor.pix_format.pixelformat ==
+ V4L2_PIX_FMT_ET61X251)
+ goto end_of_frame;
+ else {
+@@ -521,7 +520,7 @@ end_of_frame:
+ goto resubmit_urb;
+
+ if (sof &&
+- cam->sensor->pix_format.pixelformat ==
++ cam->sensor.pix_format.pixelformat ==
+ V4L2_PIX_FMT_ET61X251)
+ goto start_of_frame;
+ }
+@@ -650,21 +649,21 @@ static int et61x251_stop_transfer(struct
+
+ static int et61x251_stream_interrupt(struct et61x251_device* cam)
+ {
+- int err = 0;
++ long timeout;
+
+ cam->stream = STREAM_INTERRUPT;
+- err = wait_event_timeout(cam->wait_stream,
+- (cam->stream == STREAM_OFF) ||
+- (cam->state & DEV_DISCONNECTED),
+- ET61X251_URB_TIMEOUT);
++ timeout = wait_event_timeout(cam->wait_stream,
++ (cam->stream == STREAM_OFF) ||
++ (cam->state & DEV_DISCONNECTED),
++ ET61X251_URB_TIMEOUT);
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+- else if (err) {
++ else if (cam->stream != STREAM_OFF) {
+ cam->state |= DEV_MISCONFIGURED;
+ DBG(1, "URB timeout reached. The camera is misconfigured. To "
+ "use it, close and open /dev/video%d again.",
+ cam->v4ldev->minor);
+- return err;
++ return -EIO;
+ }
+
+ return 0;
+@@ -709,18 +708,18 @@ static ssize_t et61x251_show_reg(struct
+ struct et61x251_device* cam;
+ ssize_t count;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ count = sprintf(buf, "%u\n", cam->sysfs.reg);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -733,18 +732,18 @@ et61x251_store_reg(struct class_device*
+ u8 index;
+ ssize_t count;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ index = et61x251_strtou8(buf, len, &count);
+ if (index > 0x8e || !count) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+@@ -753,7 +752,7 @@ et61x251_store_reg(struct class_device*
+ DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg);
+ DBG(3, "Written bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -765,17 +764,17 @@ static ssize_t et61x251_show_val(struct
+ ssize_t count;
+ int val;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+@@ -783,7 +782,7 @@ static ssize_t et61x251_show_val(struct
+
+ DBG(3, "Read bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -797,24 +796,24 @@ et61x251_store_val(struct class_device*
+ ssize_t count;
+ int err;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ value = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ err = et61x251_write_reg(cam, value, cam->sysfs.reg);
+ if (err) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+@@ -822,7 +821,7 @@ et61x251_store_val(struct class_device*
+ cam->sysfs.reg, value);
+ DBG(3, "Written bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -833,12 +832,12 @@ static ssize_t et61x251_show_i2c_reg(str
+ struct et61x251_device* cam;
+ ssize_t count;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+@@ -846,7 +845,7 @@ static ssize_t et61x251_show_i2c_reg(str
+
+ DBG(3, "Read bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -859,18 +858,18 @@ et61x251_store_i2c_reg(struct class_devi
+ u8 index;
+ ssize_t count;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+ index = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+@@ -879,7 +878,7 @@ et61x251_store_i2c_reg(struct class_devi
+ DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+ DBG(3, "Written bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -891,22 +890,22 @@ static ssize_t et61x251_show_i2c_val(str
+ ssize_t count;
+ int val;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+- if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+- up(&et61x251_sysfs_lock);
++ if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) {
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENOSYS;
+ }
+
+ if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+@@ -914,7 +913,7 @@ static ssize_t et61x251_show_i2c_val(str
+
+ DBG(3, "Read bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -928,29 +927,29 @@ et61x251_store_i2c_val(struct class_devi
+ ssize_t count;
+ int err;
+
+- if (down_interruptible(&et61x251_sysfs_lock))
++ if (mutex_lock_interruptible(&et61x251_sysfs_lock))
+ return -ERESTARTSYS;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENODEV;
+ }
+
+- if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) {
+- up(&et61x251_sysfs_lock);
++ if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) {
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -ENOSYS;
+ }
+
+ value = et61x251_strtou8(buf, len, &count);
+ if (!count) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EINVAL;
+ }
+
+ err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value);
+ if (err) {
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+ return -EIO;
+ }
+
+@@ -958,7 +957,7 @@ et61x251_store_i2c_val(struct class_devi
+ cam->sysfs.i2c_reg, value);
+ DBG(3, "Written bytes: %zd", count);
+
+- up(&et61x251_sysfs_lock);
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ return count;
+ }
+@@ -980,7 +979,7 @@ static void et61x251_create_sysfs(struct
+
+ video_device_create_file(v4ldev, &class_device_attr_reg);
+ video_device_create_file(v4ldev, &class_device_attr_val);
+- if (cam->sensor && cam->sensor->sysfs_ops) {
++ if (cam->sensor.sysfs_ops) {
+ video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+ video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+ }
+@@ -1048,7 +1047,7 @@ static int et61x251_set_scale(struct et6
+ static int
+ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left +
+ s->active_pixel.left),
+ fmw_sy = (u16)(rect->top - s->cropcap.bounds.top +
+@@ -1076,7 +1075,7 @@ et61x251_set_crop(struct et61x251_device
+
+ static int et61x251_init(struct et61x251_device* cam)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ struct v4l2_queryctrl *qctrl;
+ struct v4l2_rect* rect;
+@@ -1143,7 +1142,7 @@ static int et61x251_init(struct et61x251
+ }
+
+ if (!(cam->state & DEV_INITIALIZED)) {
+- init_MUTEX(&cam->fileop_sem);
++ mutex_init(&cam->fileop_mutex);
+ spin_lock_init(&cam->queue_lock);
+ init_waitqueue_head(&cam->wait_frame);
+ init_waitqueue_head(&cam->wait_stream);
+@@ -1161,13 +1160,15 @@ static int et61x251_init(struct et61x251
+
+ static void et61x251_release_resources(struct et61x251_device* cam)
+ {
+- down(&et61x251_sysfs_lock);
++ mutex_lock(&et61x251_sysfs_lock);
+
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ video_set_drvdata(cam->v4ldev, NULL);
+ video_unregister_device(cam->v4ldev);
+
+- up(&et61x251_sysfs_lock);
++ usb_put_dev(cam->usbdev);
++
++ mutex_unlock(&et61x251_sysfs_lock);
+
+ kfree(cam->control_buffer);
+ }
+@@ -1188,7 +1189,7 @@ static int et61x251_open(struct inode* i
+
+ cam = video_get_drvdata(video_devdata(filp));
+
+- if (down_interruptible(&cam->dev_sem)) {
++ if (mutex_lock_interruptible(&cam->dev_mutex)) {
+ up_read(&et61x251_disconnect);
+ return -ERESTARTSYS;
+ }
+@@ -1200,7 +1201,7 @@ static int et61x251_open(struct inode* i
+ err = -EWOULDBLOCK;
+ goto out;
+ }
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+ err = wait_event_interruptible_exclusive(cam->open,
+ cam->state & DEV_DISCONNECTED
+ || !cam->users);
+@@ -1212,7 +1213,7 @@ static int et61x251_open(struct inode* i
+ up_read(&et61x251_disconnect);
+ return -ENODEV;
+ }
+- down(&cam->dev_sem);
++ mutex_lock(&cam->dev_mutex);
+ }
+
+
+@@ -1240,7 +1241,7 @@ static int et61x251_open(struct inode* i
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+
+ out:
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+ up_read(&et61x251_disconnect);
+ return err;
+ }
+@@ -1250,7 +1251,7 @@ static int et61x251_release(struct inode
+ {
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+
+- down(&cam->dev_sem); /* prevent disconnect() to be called */
++ mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
+
+ et61x251_stop_transfer(cam);
+
+@@ -1258,7 +1259,7 @@ static int et61x251_release(struct inode
+
+ if (cam->state & DEV_DISCONNECTED) {
+ et61x251_release_resources(cam);
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+ kfree(cam);
+ return 0;
+ }
+@@ -1268,7 +1269,7 @@ static int et61x251_release(struct inode
+
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+
+ return 0;
+ }
+@@ -1281,28 +1282,29 @@ et61x251_read(struct file* filp, char __
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ struct et61x251_frame_t* f, * i;
+ unsigned long lock_flags;
++ long timeout;
+ int err = 0;
+
+- if (down_interruptible(&cam->fileop_sem))
++ if (mutex_lock_interruptible(&cam->fileop_mutex))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EIO;
+ }
+
+ if (cam->io == IO_MMAP) {
+ DBG(3, "Close and open the device again to choose the read "
+ "method");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EINVAL;
+ }
+
+@@ -1310,7 +1312,7 @@ et61x251_read(struct file* filp, char __
+ if (!et61x251_request_buffers(cam, cam->nreadbuffers,
+ IO_READ)) {
+ DBG(1, "read() failed, not enough memory");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -ENOMEM;
+ }
+ cam->io = IO_READ;
+@@ -1324,30 +1326,32 @@ et61x251_read(struct file* filp, char __
+ }
+
+ if (!count) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return 0;
+ }
+
+ if (list_empty(&cam->outqueue)) {
+ if (filp->f_flags & O_NONBLOCK) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EAGAIN;
+ }
+- err = wait_event_interruptible
+- ( cam->wait_frame,
+- (!list_empty(&cam->outqueue)) ||
+- (cam->state & DEV_DISCONNECTED) ||
+- (cam->state & DEV_MISCONFIGURED) );
+- if (err) {
+- up(&cam->fileop_sem);
+- return err;
++ timeout = wait_event_interruptible_timeout
++ ( cam->wait_frame,
++ (!list_empty(&cam->outqueue)) ||
++ (cam->state & DEV_DISCONNECTED) ||
++ (cam->state & DEV_MISCONFIGURED),
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
++ if (timeout < 0) {
++ mutex_unlock(&cam->fileop_mutex);
++ return timeout;
+ }
+ if (cam->state & DEV_DISCONNECTED) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -ENODEV;
+ }
+- if (cam->state & DEV_MISCONFIGURED) {
+- up(&cam->fileop_sem);
++ if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
++ mutex_unlock(&cam->fileop_mutex);
+ return -EIO;
+ }
+ }
+@@ -1375,7 +1379,7 @@ exit:
+ PDBGG("Frame #%lu, bytes read: %zu",
+ (unsigned long)f->buf.index, count);
+
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+
+ return err ? err : count;
+ }
+@@ -1388,7 +1392,7 @@ static unsigned int et61x251_poll(struct
+ unsigned long lock_flags;
+ unsigned int mask = 0;
+
+- if (down_interruptible(&cam->fileop_sem))
++ if (mutex_lock_interruptible(&cam->fileop_mutex))
+ return POLLERR;
+
+ if (cam->state & DEV_DISCONNECTED) {
+@@ -1426,12 +1430,12 @@ static unsigned int et61x251_poll(struct
+ if (!list_empty(&cam->outqueue))
+ mask |= POLLIN | POLLRDNORM;
+
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+
+ return mask;
+
+ error:
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return POLLERR;
+ }
+
+@@ -1465,25 +1469,25 @@ static int et61x251_mmap(struct file* fi
+ void *pos;
+ u32 i;
+
+- if (down_interruptible(&cam->fileop_sem))
++ if (mutex_lock_interruptible(&cam->fileop_mutex))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EIO;
+ }
+
+ if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ size != PAGE_ALIGN(cam->frame[0].buf.length)) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EINVAL;
+ }
+
+@@ -1492,7 +1496,7 @@ static int et61x251_mmap(struct file* fi
+ break;
+ }
+ if (i == cam->nbuffers) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EINVAL;
+ }
+
+@@ -1502,7 +1506,7 @@ static int et61x251_mmap(struct file* fi
+ pos = cam->frame[i].bufmem;
+ while (size > 0) { /* size is page-aligned */
+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+@@ -1515,7 +1519,7 @@ static int et61x251_mmap(struct file* fi
+
+ et61x251_vm_open(vma);
+
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+
+ return 0;
+ }
+@@ -1557,6 +1561,7 @@ et61x251_vidioc_enuminput(struct et61x25
+
+ memset(&i, 0, sizeof(i));
+ strcpy(i.name, "Camera");
++ i.type = V4L2_INPUT_TYPE_CAMERA;
+
+ if (copy_to_user(arg, &i, sizeof(i)))
+ return -EFAULT;
+@@ -1566,7 +1571,19 @@ et61x251_vidioc_enuminput(struct et61x25
+
+
+ static int
+-et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg)
++et61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg)
++{
++ int index = 0;
++
++ if (copy_to_user(arg, &index, sizeof(index)))
++ return -EFAULT;
++
++ return 0;
++}
++
++
++static int
++et61x251_vidioc_s_input(struct et61x251_device* cam, void __user * arg)
+ {
+ int index;
+
+@@ -1583,7 +1600,7 @@ et61x251_vidioc_gs_input(struct et61x251
+ static int
+ et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_queryctrl qc;
+ u8 i;
+
+@@ -1605,7 +1622,7 @@ et61x251_vidioc_query_ctrl(struct et61x2
+ static int
+ et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ int err = 0;
+ u8 i;
+@@ -1637,7 +1654,7 @@ exit:
+ static int
+ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ u8 i;
+ int err = 0;
+@@ -1650,6 +1667,8 @@ et61x251_vidioc_s_ctrl(struct et61x251_d
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
++ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
++ return -EINVAL;
+ if (ctrl.value < s->qctrl[i].minimum ||
+ ctrl.value > s->qctrl[i].maximum)
+ return -ERANGE;
+@@ -1669,7 +1688,7 @@ et61x251_vidioc_s_ctrl(struct et61x251_d
+ static int
+ et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg)
+ {
+- struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
++ struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
+
+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cc->pixelaspect.numerator = 1;
+@@ -1685,7 +1704,7 @@ et61x251_vidioc_cropcap(struct et61x251_
+ static int
+ et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_crop crop = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ };
+@@ -1702,7 +1721,7 @@ et61x251_vidioc_g_crop(struct et61x251_d
+ static int
+ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_crop crop;
+ struct v4l2_rect* rect;
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+@@ -1843,7 +1862,7 @@ static int
+ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
+ {
+ struct v4l2_format format;
+- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
++ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
+
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
+@@ -1868,7 +1887,7 @@ static int
+ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
+ void __user * arg)
+ {
+- struct et61x251_sensor* s = cam->sensor;
++ struct et61x251_sensor* s = &cam->sensor;
+ struct v4l2_format format;
+ struct v4l2_pix_format* pix;
+ struct v4l2_pix_format* pfmt = &(s->pix_format);
+@@ -2155,7 +2174,7 @@ et61x251_vidioc_dqbuf(struct et61x251_de
+ struct v4l2_buffer b;
+ struct et61x251_frame_t *f;
+ unsigned long lock_flags;
+- int err = 0;
++ long timeout;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+@@ -2168,16 +2187,18 @@ et61x251_vidioc_dqbuf(struct et61x251_de
+ return -EINVAL;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+- err = wait_event_interruptible
+- ( cam->wait_frame,
+- (!list_empty(&cam->outqueue)) ||
+- (cam->state & DEV_DISCONNECTED) ||
+- (cam->state & DEV_MISCONFIGURED) );
+- if (err)
+- return err;
++ timeout = wait_event_interruptible_timeout
++ ( cam->wait_frame,
++ (!list_empty(&cam->outqueue)) ||
++ (cam->state & DEV_DISCONNECTED) ||
++ (cam->state & DEV_MISCONFIGURED),
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
++ if (timeout < 0)
++ return timeout;
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+- if (cam->state & DEV_MISCONFIGURED)
++ if (!timeout || (cam->state & DEV_MISCONFIGURED))
+ return -EIO;
+ }
+
+@@ -2309,8 +2330,10 @@ static int et61x251_ioctl_v4l2(struct in
+ return et61x251_vidioc_enuminput(cam, arg);
+
+ case VIDIOC_G_INPUT:
++ return et61x251_vidioc_g_input(cam, arg);
++
+ case VIDIOC_S_INPUT:
+- return et61x251_vidioc_gs_input(cam, arg);
++ return et61x251_vidioc_s_input(cam, arg);
+
+ case VIDIOC_QUERYCTRL:
+ return et61x251_vidioc_query_ctrl(cam, arg);
+@@ -2393,19 +2416,19 @@ static int et61x251_ioctl(struct inode*
+ struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+ int err = 0;
+
+- if (down_interruptible(&cam->fileop_sem))
++ if (mutex_lock_interruptible(&cam->fileop_mutex))
+ return -ERESTARTSYS;
+
+ if (cam->state & DEV_DISCONNECTED) {
+ DBG(1, "Device not present");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -ENODEV;
+ }
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ DBG(1, "The camera is misconfigured. Close and open it "
+ "again.");
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+ return -EIO;
+ }
+
+@@ -2413,7 +2436,7 @@ static int et61x251_ioctl(struct inode*
+
+ err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+
+- up(&cam->fileop_sem);
++ mutex_unlock(&cam->fileop_mutex);
+
+ return err;
+ }
+@@ -2459,7 +2482,7 @@ et61x251_usb_probe(struct usb_interface*
+ goto fail;
+ }
+
+- init_MUTEX(&cam->dev_sem);
++ mutex_init(&cam->dev_mutex);
+
+ DBG(2, "ET61X[12]51 PC Camera Controller detected "
+ "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
+@@ -2470,8 +2493,8 @@ et61x251_usb_probe(struct usb_interface*
+ break;
+ }
+
+- if (!err && cam->sensor)
+- DBG(2, "%s image sensor detected", cam->sensor->name);
++ if (!err)
++ DBG(2, "%s image sensor detected", cam->sensor.name);
+ else {
+ DBG(1, "No supported image sensor detected");
+ err = -ENODEV;
+@@ -2492,7 +2515,7 @@ et61x251_usb_probe(struct usb_interface*
+ cam->v4ldev->release = video_device_release;
+ video_set_drvdata(cam->v4ldev, cam);
+
+- down(&cam->dev_sem);
++ mutex_lock(&cam->dev_mutex);
+
+ err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
+ video_nr[dev_nr]);
+@@ -2502,13 +2525,14 @@ et61x251_usb_probe(struct usb_interface*
+ DBG(1, "Free /dev/videoX node not found");
+ video_nr[dev_nr] = -1;
+ dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+ goto fail;
+ }
+
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+
+ cam->module_param.force_munmap = force_munmap[dev_nr];
++ cam->module_param.frame_timeout = frame_timeout[dev_nr];
+
+ dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+@@ -2519,7 +2543,7 @@ et61x251_usb_probe(struct usb_interface*
+
+ usb_set_intfdata(intf, cam);
+
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+
+ return 0;
+
+@@ -2543,7 +2567,7 @@ static void et61x251_usb_disconnect(stru
+
+ down_write(&et61x251_disconnect);
+
+- down(&cam->dev_sem);
++ mutex_lock(&cam->dev_mutex);
+
+ DBG(2, "Disconnecting %s...", cam->v4ldev->name);
+
+@@ -2557,13 +2581,14 @@ static void et61x251_usb_disconnect(stru
+ et61x251_stop_transfer(cam);
+ cam->state |= DEV_DISCONNECTED;
+ wake_up_interruptible(&cam->wait_frame);
+- wake_up_interruptible(&cam->wait_stream);
++ wake_up(&cam->wait_stream);
++ usb_get_dev(cam->usbdev);
+ } else {
+ cam->state |= DEV_DISCONNECTED;
+ et61x251_release_resources(cam);
+ }
+
+- up(&cam->dev_sem);
++ mutex_unlock(&cam->dev_mutex);
+
+ if (!cam->users)
+ kfree(cam);
+--- gregkh-2.6.orig/drivers/usb/media/et61x251.h
++++ gregkh-2.6/drivers/usb/media/et61x251.h
+@@ -33,7 +33,9 @@
+ #include <linux/types.h>
+ #include <linux/param.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/stddef.h>
++#include <linux/string.h>
+
+ #include "et61x251_sensor.h"
+
+@@ -51,6 +53,7 @@
+ #define ET61X251_ALTERNATE_SETTING 13
+ #define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS)
+ #define ET61X251_CTRL_TIMEOUT 100
++#define ET61X251_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -127,15 +130,16 @@ struct et61x251_sysfs_attr {
+
+ struct et61x251_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+-static DECLARE_MUTEX(et61x251_sysfs_lock);
++static DEFINE_MUTEX(et61x251_sysfs_lock);
+ static DECLARE_RWSEM(et61x251_disconnect);
+
+ struct et61x251_device {
+ struct video_device* v4ldev;
+
+- struct et61x251_sensor* sensor;
++ struct et61x251_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[ET61X251_URBS];
+@@ -157,19 +161,28 @@ struct et61x251_device {
+ enum et61x251_dev_state state;
+ u8 users;
+
+- struct semaphore dev_sem, fileop_sem;
++ struct mutex dev_mutex, fileop_mutex;
+ spinlock_t queue_lock;
+ wait_queue_head_t open, wait_frame, wait_stream;
+ };
+
+ /*****************************************************************************/
+
++struct et61x251_device*
++et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
++
+ void
+ et61x251_attach_sensor(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
+ }
+
+ /*****************************************************************************/
+@@ -212,7 +225,8 @@ do {
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
++dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args)
+
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+--- gregkh-2.6.orig/drivers/usb/media/et61x251_sensor.h
++++ gregkh-2.6/drivers/usb/media/et61x251_sensor.h
+@@ -42,6 +42,9 @@ static int (*et61x251_sensor_table[])(st
+ NULL, \
+ };
+
++extern struct et61x251_device*
++et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id);
++
+ extern void
+ et61x251_attach_sensor(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor);
+@@ -105,8 +108,6 @@ struct et61x251_sensor {
+ int (*set_pix_format)(struct et61x251_device* cam,
+ const struct v4l2_pix_format* pix);
+
+- const struct usb_device* usbdev;
+-
+ /* Private */
+ struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS];
+ struct v4l2_rect _rect;
+--- gregkh-2.6.orig/drivers/usb/media/et61x251_tas5130d1b.c
++++ gregkh-2.6/drivers/usb/media/et61x251_tas5130d1b.c
+@@ -126,12 +126,16 @@ static struct et61x251_sensor tas5130d1b
+
+ int et61x251_probe_tas5130d1b(struct et61x251_device* cam)
+ {
+- /* This sensor has no identifiers, so let's attach it anyway */
+- et61x251_attach_sensor(cam, &tas5130d1b);
++ const struct usb_device_id tas5130d1b_id_table[] = {
++ { USB_DEVICE(0x102c, 0x6251), },
++ { }
++ };
+
+ /* Sensor detection is based on USB pid/vid */
+- if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251)
++ if (!et61x251_match_id(cam, tas5130d1b_id_table))
+ return -ENODEV;
+
++ et61x251_attach_sensor(cam, &tas5130d1b);
++
+ return 0;
+ }
diff --git a/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch b/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch
new file mode 100644
index 0000000000000..4691e5d8f105b
--- /dev/null
+++ b/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch
@@ -0,0 +1,690 @@
+From snakebyte@gmx.de Mon Feb 27 12:29:47 2006
+From: Eric Sesterhenn <snakebyte@gmx.de>
+To: Greg KH <gregkh@suse.de>
+Cc: kernel-janitors@lists.osdl.org
+Subject: USB: kzalloc() conversion for rest of drivers/usb
+Date: Mon, 27 Feb 2006 21:29:43 +0100
+Message-Id: <1141072183.32324.0.camel@alice>
+
+
+Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-mem.c | 10 +++-------
+ drivers/usb/host/ehci-sched.c | 3 +--
+ drivers/usb/host/hc_crisv10.c | 12 ++++--------
+ drivers/usb/media/ov511.c | 4 +---
+ drivers/usb/media/pwc/pwc-if.c | 3 +--
+ drivers/usb/media/se401.c | 4 +---
+ drivers/usb/media/stv680.c | 7 ++-----
+ drivers/usb/misc/auerswald.c | 6 ++----
+ drivers/usb/misc/usblcd.c | 3 +--
+ drivers/usb/misc/usbtest.c | 9 +++------
+ drivers/usb/mon/mon_main.c | 3 +--
+ drivers/usb/mon/mon_text.c | 3 +--
+ drivers/usb/net/zd1201.c | 9 +++------
+ drivers/usb/serial/cp2101.c | 4 +---
+ drivers/usb/serial/cypress_m8.c | 3 +--
+ drivers/usb/serial/ftdi_sio.c | 3 +--
+ drivers/usb/serial/garmin_gps.c | 3 +--
+ drivers/usb/serial/io_edgeport.c | 3 +--
+ drivers/usb/serial/io_ti.c | 6 ++----
+ drivers/usb/serial/ir-usb.c | 3 +--
+ drivers/usb/serial/keyspan.c | 6 ++----
+ drivers/usb/serial/kobil_sct.c | 16 +++++-----------
+ drivers/usb/serial/mct_u232.c | 3 +--
+ drivers/usb/serial/option.c | 3 +--
+ drivers/usb/serial/pl2303.c | 6 ++----
+ drivers/usb/serial/ti_usb_3410_5052.c | 3 +--
+ drivers/usb/serial/usb-serial.c | 6 ++----
+ drivers/usb/serial/visor.c | 3 +--
+ drivers/usb/storage/isd200.c | 2 +-
+ 29 files changed, 48 insertions(+), 101 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/host/ehci-mem.c
++++ gregkh-2.6/drivers/usb/host/ehci-mem.c
+@@ -220,13 +220,9 @@ static int ehci_mem_init (struct ehci_hc
+ ehci->periodic [i] = EHCI_LIST_END;
+
+ /* software shadow of hardware table */
+- ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags);
+- if (ehci->pshadow == NULL) {
+- goto fail;
+- }
+- memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *));
+-
+- return 0;
++ ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
++ if (ehci->pshadow != NULL)
++ return 0;
+
+ fail:
+ ehci_dbg (ehci, "couldn't init memory\n");
+--- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c
++++ gregkh-2.6/drivers/usb/host/ehci-sched.c
+@@ -864,9 +864,8 @@ iso_sched_alloc (unsigned packets, gfp_t
+ int size = sizeof *iso_sched;
+
+ size += packets * sizeof (struct ehci_iso_packet);
+- iso_sched = kmalloc (size, mem_flags);
++ iso_sched = kzalloc(size, mem_flags);
+ if (likely (iso_sched != NULL)) {
+- memset(iso_sched, 0, size);
+ INIT_LIST_HEAD (&iso_sched->td_list);
+ }
+ return iso_sched;
+--- gregkh-2.6.orig/drivers/usb/host/hc_crisv10.c
++++ gregkh-2.6/drivers/usb/host/hc_crisv10.c
+@@ -2137,10 +2137,9 @@ static int etrax_usb_submit_bulk_urb(str
+ urb->status = -EINPROGRESS;
+
+ /* Setup the hcpriv data. */
+- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
++ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
+ assert(urb_priv != NULL);
+ /* This sets rx_offset to 0. */
+- memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
+ urb_priv->urb_state = NOT_STARTED;
+ urb->hcpriv = urb_priv;
+
+@@ -2475,10 +2474,9 @@ static int etrax_usb_submit_ctrl_urb(str
+ urb->status = -EINPROGRESS;
+
+ /* Setup the hcpriv data. */
+- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
++ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
+ assert(urb_priv != NULL);
+ /* This sets rx_offset to 0. */
+- memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
+ urb_priv->urb_state = NOT_STARTED;
+ urb->hcpriv = urb_priv;
+
+@@ -2767,9 +2765,8 @@ static void etrax_usb_add_to_intr_sb_lis
+ maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+ interval = urb->interval;
+
+- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
++ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
+ assert(urb_priv != NULL);
+- memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
+ urb->hcpriv = urb_priv;
+
+ first_ep = &TxIntrEPList[0];
+@@ -2997,9 +2994,8 @@ static void etrax_usb_add_to_isoc_sb_lis
+
+ prev_sb_desc = next_sb_desc = temp_sb_desc = NULL;
+
+- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC);
++ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC);
+ assert(urb_priv != NULL);
+- memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
+
+ urb->hcpriv = urb_priv;
+ urb_priv->epid = epid;
+--- gregkh-2.6.orig/drivers/usb/media/ov511.c
++++ gregkh-2.6/drivers/usb/media/ov511.c
+@@ -5686,13 +5686,11 @@ ov51x_probe(struct usb_interface *intf,
+ if (idesc->bInterfaceSubClass != 0x00)
+ return -ENODEV;
+
+- if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
++ if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
+ err("couldn't kmalloc ov struct");
+ goto error_out;
+ }
+
+- memset(ov, 0, sizeof(*ov));
+-
+ ov->dev = dev;
+ ov->iface = idesc->bInterfaceNumber;
+ ov->led_policy = led;
+--- gregkh-2.6.orig/drivers/usb/media/pwc/pwc-if.c
++++ gregkh-2.6/drivers/usb/media/pwc/pwc-if.c
+@@ -1867,12 +1867,11 @@ static int usb_pwc_probe(struct usb_inte
+ Info("Warning: more than 1 configuration available.\n");
+
+ /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+- pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
++ pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
+ if (pdev == NULL) {
+ Err("Oops, could not allocate memory for pwc_device.\n");
+ return -ENOMEM;
+ }
+- memset(pdev, 0, sizeof(struct pwc_device));
+ pdev->type = type_id;
+ pdev->vsize = default_size;
+ pdev->vframes = default_fps;
+--- gregkh-2.6.orig/drivers/usb/media/se401.c
++++ gregkh-2.6/drivers/usb/media/se401.c
+@@ -1345,13 +1345,11 @@ static int se401_probe(struct usb_interf
+ /* We found one */
+ info("SE401 camera found: %s", camera_name);
+
+- if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
++ if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
+ err("couldn't kmalloc se401 struct");
+ return -ENOMEM;
+ }
+
+- memset(se401, 0, sizeof(*se401));
+-
+ se401->dev = dev;
+ se401->iface = interface->bInterfaceNumber;
+ se401->camera_name = camera_name;
+--- gregkh-2.6.orig/drivers/usb/media/stv680.c
++++ gregkh-2.6/drivers/usb/media/stv680.c
+@@ -318,12 +318,11 @@ static int stv_init (struct usb_stv *stv
+ unsigned char *buffer;
+ unsigned long int bufsize;
+
+- buffer = kmalloc (40, GFP_KERNEL);
++ buffer = kzalloc (40, GFP_KERNEL);
+ if (buffer == NULL) {
+ PDEBUG (0, "STV(e): Out of (small buf) memory");
+ return -1;
+ }
+- memset (buffer, 0, 40);
+ udelay (100);
+
+ /* set config 1, interface 0, alternate 0 */
+@@ -1388,14 +1387,12 @@ static int stv680_probe (struct usb_inte
+ goto error;
+ }
+ /* We found one */
+- if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
++ if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
+ PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
+ retval = -ENOMEM;
+ goto error;
+ }
+
+- memset (stv680, 0, sizeof (*stv680));
+-
+ stv680->udev = dev;
+ stv680->camera_name = camera_name;
+
+--- gregkh-2.6.orig/drivers/usb/misc/auerswald.c
++++ gregkh-2.6/drivers/usb/misc/auerswald.c
+@@ -570,10 +570,9 @@ static int auerchain_setup (pauerchain_t
+
+ /* fill the list of free elements */
+ for (;numElements; numElements--) {
+- acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL);
++ acep = kzalloc(sizeof(auerchainelement_t), GFP_KERNEL);
+ if (!acep)
+ goto ac_fail;
+- memset (acep, 0, sizeof (auerchainelement_t));
+ INIT_LIST_HEAD (&acep->list);
+ list_add_tail (&acep->list, &acp->free_list);
+ }
+@@ -761,10 +760,9 @@ static int auerbuf_setup (pauerbufctl_t
+
+ /* fill the list of free elements */
+ for (;numElements; numElements--) {
+- bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL);
++ bep = kzalloc(sizeof(auerbuf_t), GFP_KERNEL);
+ if (!bep)
+ goto bl_fail;
+- memset (bep, 0, sizeof (auerbuf_t));
+ bep->list = bcp;
+ INIT_LIST_HEAD (&bep->buff_list);
+ bep->bufp = kmalloc (bufsize, GFP_KERNEL);
+--- gregkh-2.6.orig/drivers/usb/misc/usblcd.c
++++ gregkh-2.6/drivers/usb/misc/usblcd.c
+@@ -270,12 +270,11 @@ static int lcd_probe(struct usb_interfac
+ int retval = -ENOMEM;
+
+ /* allocate memory for our device state and initialize it */
+- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ err("Out of memory");
+ goto error;
+ }
+- memset(dev, 0x00, sizeof(*dev));
+ kref_init(&dev->kref);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+--- gregkh-2.6.orig/drivers/usb/misc/usbtest.c
++++ gregkh-2.6/drivers/usb/misc/usbtest.c
+@@ -382,12 +382,11 @@ alloc_sglist (int nents, int max, int va
+ for (i = 0; i < nents; i++) {
+ char *buf;
+
+- buf = kmalloc (size, SLAB_KERNEL);
++ buf = kzalloc (size, SLAB_KERNEL);
+ if (!buf) {
+ free_sglist (sg, i);
+ return NULL;
+ }
+- memset (buf, 0, size);
+
+ /* kmalloc pages are always physically contiguous! */
+ sg_init_one(&sg[i], buf, size);
+@@ -842,10 +841,9 @@ test_ctrl_queue (struct usbtest_dev *dev
+ * as with bulk/intr sglists, sglen is the queue depth; it also
+ * controls which subtests run (more tests than sglen) or rerun.
+ */
+- urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL);
++ urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL);
+ if (!urb)
+ return -ENOMEM;
+- memset (urb, 0, param->sglen * sizeof (struct urb *));
+ for (i = 0; i < param->sglen; i++) {
+ int pipe = usb_rcvctrlpipe (udev, 0);
+ unsigned len;
+@@ -1865,10 +1863,9 @@ usbtest_probe (struct usb_interface *int
+ }
+ #endif
+
+- dev = kmalloc (sizeof *dev, SLAB_KERNEL);
++ dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+- memset (dev, 0, sizeof *dev);
+ info = (struct usbtest_info *) id->driver_info;
+ dev->info = info;
+ init_MUTEX (&dev->sem);
+--- gregkh-2.6.orig/drivers/usb/mon/mon_main.c
++++ gregkh-2.6/drivers/usb/mon/mon_main.c
+@@ -277,9 +277,8 @@ static void mon_bus_init(struct dentry *
+ char name[NAMESZ];
+ int rc;
+
+- if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
++ if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
+ goto err_alloc;
+- memset(mbus, 0, sizeof(struct mon_bus));
+ kref_init(&mbus->ref);
+ spin_lock_init(&mbus->lock);
+ INIT_LIST_HEAD(&mbus->r_list);
+--- gregkh-2.6.orig/drivers/usb/mon/mon_text.c
++++ gregkh-2.6/drivers/usb/mon/mon_text.c
+@@ -213,12 +213,11 @@ static int mon_text_open(struct inode *i
+ mbus = inode->u.generic_ip;
+ ubus = mbus->u_bus;
+
+- rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
++ rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
+ if (rp == NULL) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+- memset(rp, 0, sizeof(struct mon_reader_text));
+ INIT_LIST_HEAD(&rp->e_list);
+ init_waitqueue_head(&rp->wait);
+ mutex_init(&rp->printf_lock);
+--- gregkh-2.6.orig/drivers/usb/net/zd1201.c
++++ gregkh-2.6/drivers/usb/net/zd1201.c
+@@ -621,10 +621,9 @@ static int zd1201_drvr_start(struct zd12
+ __le16 zdmax;
+ unsigned char *buffer;
+
+- buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL);
++ buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+- memset(buffer, 0, ZD1201_RXSIZE);
+
+ usb_fill_bulk_urb(zd->rx_urb, zd->usb,
+ usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
+@@ -1750,11 +1749,9 @@ static int zd1201_probe(struct usb_inter
+
+ usb = interface_to_usbdev(interface);
+
+- zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL);
+- if (!zd) {
++ zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL);
++ if (!zd)
+ return -ENOMEM;
+- }
+- memset(zd, 0, sizeof(struct zd1201));
+ zd->ap = ap;
+ zd->usb = usb;
+ zd->removed = 0;
+--- gregkh-2.6.orig/drivers/usb/serial/cp2101.c
++++ gregkh-2.6/drivers/usb/serial/cp2101.c
+@@ -169,9 +169,7 @@ static int cp2101_get_config(struct usb_
+ /* Number of integers required to contain the array */
+ length = (((size - 1) | 3) + 1)/4;
+
+- buf = kmalloc (length * sizeof(u32), GFP_KERNEL);
+- memset(buf, 0, length * sizeof(u32));
+-
++ buf = kcalloc(length, sizeof(u32), GFP_KERNEL);
+ if (!buf) {
+ dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+ return -ENOMEM;
+--- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.c
++++ gregkh-2.6/drivers/usb/serial/cypress_m8.c
+@@ -435,11 +435,10 @@ static int generic_startup (struct usb_s
+
+ dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+
+- priv = kmalloc(sizeof (struct cypress_private), GFP_KERNEL);
++ priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+- memset(priv, 0x00, sizeof (struct cypress_private));
+ spin_lock_init(&priv->lock);
+ priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
+ if (priv->buf == NULL) {
+--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c
++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c
+@@ -1141,12 +1141,11 @@ static int ftdi_sio_attach (struct usb_s
+
+ dbg("%s",__FUNCTION__);
+
+- priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
++ priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ if (!priv){
+ err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
+ return -ENOMEM;
+ }
+- memset(priv, 0, sizeof(*priv));
+
+ spin_lock_init(&priv->rx_lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+--- gregkh-2.6.orig/drivers/usb/serial/garmin_gps.c
++++ gregkh-2.6/drivers/usb/serial/garmin_gps.c
+@@ -1422,12 +1422,11 @@ static int garmin_attach (struct usb_ser
+
+ dbg("%s", __FUNCTION__);
+
+- garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
++ garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+ if (garmin_data_p == NULL) {
+ dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+- memset (garmin_data_p, 0, sizeof(struct garmin_data));
+ init_timer(&garmin_data_p->timer);
+ spin_lock_init(&garmin_data_p->lock);
+ INIT_LIST_HEAD(&garmin_data_p->pktlist);
+--- gregkh-2.6.orig/drivers/usb/serial/io_edgeport.c
++++ gregkh-2.6/drivers/usb/serial/io_edgeport.c
+@@ -2725,12 +2725,11 @@ static int edge_startup (struct usb_seri
+ dev = serial->dev;
+
+ /* create our private serial structure */
+- edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
++ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ if (edge_serial == NULL) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+- memset (edge_serial, 0, sizeof(struct edgeport_serial));
+ spin_lock_init(&edge_serial->es_lock);
+ edge_serial->serial = serial;
+ usb_set_serial_data(serial, edge_serial);
+--- gregkh-2.6.orig/drivers/usb/serial/io_ti.c
++++ gregkh-2.6/drivers/usb/serial/io_ti.c
+@@ -2727,12 +2727,11 @@ static int edge_startup (struct usb_seri
+ dev = serial->dev;
+
+ /* create our private serial structure */
+- edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
++ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ if (edge_serial == NULL) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+- memset (edge_serial, 0, sizeof(struct edgeport_serial));
+ sema_init(&edge_serial->es_sem, 1);
+ edge_serial->serial = serial;
+ usb_set_serial_data(serial, edge_serial);
+@@ -2745,12 +2744,11 @@ static int edge_startup (struct usb_seri
+
+ /* set up our port private structures */
+ for (i = 0; i < serial->num_ports; ++i) {
+- edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
++ edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
+ if (edge_port == NULL) {
+ dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+ goto cleanup;
+ }
+- memset (edge_port, 0, sizeof(struct edgeport_port));
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
+ if (edge_port->ep_out_buf == NULL) {
+--- gregkh-2.6.orig/drivers/usb/serial/ir-usb.c
++++ gregkh-2.6/drivers/usb/serial/ir-usb.c
+@@ -184,10 +184,9 @@ static struct irda_class_desc *irda_usb_
+ struct irda_class_desc *desc;
+ int ret;
+
+- desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
++ desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
+ if (desc == NULL)
+ return NULL;
+- memset(desc, 0, sizeof(struct irda_class_desc));
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+ IU_REQ_GET_CLASS_DESC,
+--- gregkh-2.6.orig/drivers/usb/serial/keyspan.c
++++ gregkh-2.6/drivers/usb/serial/keyspan.c
+@@ -2250,12 +2250,11 @@ static int keyspan_startup (struct usb_s
+ }
+
+ /* Setup private data for serial driver */
+- s_priv = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
++ s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
+ if (!s_priv) {
+ dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__);
+ return -ENOMEM;
+ }
+- memset(s_priv, 0, sizeof(struct keyspan_serial_private));
+
+ s_priv->device_details = d_details;
+ usb_set_serial_data(serial, s_priv);
+@@ -2263,12 +2262,11 @@ static int keyspan_startup (struct usb_s
+ /* Now setup per port private data */
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+- p_priv = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
++ p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ if (!p_priv) {
+ dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i);
+ return (1);
+ }
+- memset(p_priv, 0, sizeof(struct keyspan_port_private));
+ p_priv->device_details = d_details;
+ usb_set_serial_port_data(port, p_priv);
+ }
+--- gregkh-2.6.orig/drivers/usb/serial/kobil_sct.c
++++ gregkh-2.6/drivers/usb/serial/kobil_sct.c
+@@ -255,11 +255,9 @@ static int kobil_open (struct usb_serial
+ }
+
+ // allocate memory for transfer buffer
+- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
++ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
+ if (! transfer_buffer) {
+ return -ENOMEM;
+- } else {
+- memset(transfer_buffer, 0, transfer_buffer_length);
+ }
+
+ // allocate write_urb
+@@ -383,11 +381,10 @@ static void kobil_read_int_callback( str
+
+ // BEGIN DEBUG
+ /*
+- dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
++ dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
+ if (! dbg_data) {
+ return;
+ }
+- memset(dbg_data, 0, (3 * purb->actual_length + 10));
+ for (i = 0; i < purb->actual_length; i++) {
+ sprintf(dbg_data +3*i, "%02X ", data[i]);
+ }
+@@ -518,11 +515,10 @@ static int kobil_tiocmget(struct usb_ser
+ }
+
+ // allocate memory for transfer buffer
+- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
++ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
+ if (!transfer_buffer) {
+ return -ENOMEM;
+ }
+- memset(transfer_buffer, 0, transfer_buffer_length);
+
+ result = usb_control_msg( port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0 ),
+@@ -564,11 +560,10 @@ static int kobil_tiocmset(struct usb_se
+ }
+
+ // allocate memory for transfer buffer
+- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
++ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
+ if (! transfer_buffer) {
+ return -ENOMEM;
+ }
+- memset(transfer_buffer, 0, transfer_buffer_length);
+
+ if (set & TIOCM_RTS)
+ rts = 1;
+@@ -655,11 +650,10 @@ static int kobil_ioctl(struct usb_seria
+ (struct termios __user *)arg))
+ return -EFAULT;
+
+- settings = (unsigned char *) kmalloc(50, GFP_KERNEL);
++ settings = kzalloc(50, GFP_KERNEL);
+ if (! settings) {
+ return -ENOBUFS;
+ }
+- memset(settings, 0, 50);
+
+ switch (priv->internal_termios.c_cflag & CBAUD) {
+ case B1200:
+--- gregkh-2.6.orig/drivers/usb/serial/mct_u232.c
++++ gregkh-2.6/drivers/usb/serial/mct_u232.c
+@@ -348,10 +348,9 @@ static int mct_u232_startup (struct usb_
+ struct mct_u232_private *priv;
+ struct usb_serial_port *port, *rport;
+
+- priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
++ priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+- memset(priv, 0, sizeof(struct mct_u232_private));
+ spin_lock_init(&priv->lock);
+ usb_set_serial_port_data(serial->port[0], priv);
+
+--- gregkh-2.6.orig/drivers/usb/serial/option.c
++++ gregkh-2.6/drivers/usb/serial/option.c
+@@ -631,13 +631,12 @@ static int option_startup(struct usb_ser
+ /* Now setup per port private data */
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+- portdata = kmalloc(sizeof(*portdata), GFP_KERNEL);
++ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ if (!portdata) {
+ dbg("%s: kmalloc for option_port_private (%d) failed!.",
+ __FUNCTION__, i);
+ return (1);
+ }
+- memset(portdata, 0, sizeof(struct option_port_private));
+
+ usb_set_serial_port_data(port, portdata);
+
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
++++ gregkh-2.6/drivers/usb/serial/pl2303.c
+@@ -218,10 +218,9 @@ static int pl2303_startup (struct usb_se
+ dbg("device type: %d", type);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+- priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL);
++ priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
+ if (!priv)
+ goto cleanup;
+- memset (priv, 0x00, sizeof (struct pl2303_private));
+ spin_lock_init(&priv->lock);
+ priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+ if (priv->buf == NULL) {
+@@ -383,12 +382,11 @@ static void pl2303_set_termios (struct u
+ }
+ }
+
+- buf = kmalloc (7, GFP_KERNEL);
++ buf = kzalloc (7, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+ return;
+ }
+- memset (buf, 0x00, 0x07);
+
+ i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
+ GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+--- gregkh-2.6.orig/drivers/usb/serial/ti_usb_3410_5052.c
++++ gregkh-2.6/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -416,12 +416,11 @@ static int ti_startup(struct usb_serial
+ dev->actconfig->desc.bConfigurationValue);
+
+ /* create device structure */
+- tdev = kmalloc(sizeof(struct ti_device), GFP_KERNEL);
++ tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
+ if (tdev == NULL) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+- memset(tdev, 0, sizeof(struct ti_device));
+ sema_init(&tdev->td_open_close_sem, 1);
+ tdev->td_serial = serial;
+ usb_set_serial_data(serial, tdev);
+--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c
++++ gregkh-2.6/drivers/usb/serial/usb-serial.c
+@@ -564,12 +564,11 @@ static struct usb_serial * create_serial
+ {
+ struct usb_serial *serial;
+
+- serial = kmalloc (sizeof (*serial), GFP_KERNEL);
++ serial = kzalloc(sizeof(*serial), GFP_KERNEL);
+ if (!serial) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ return NULL;
+ }
+- memset (serial, 0, sizeof(*serial));
+ serial->dev = usb_get_dev(dev);
+ serial->type = driver;
+ serial->interface = interface;
+@@ -778,10 +777,9 @@ int usb_serial_probe(struct usb_interfac
+ serial->num_port_pointers = max_endpoints;
+ dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
+ for (i = 0; i < max_endpoints; ++i) {
+- port = kmalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
++ port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
+ if (!port)
+ goto probe_error;
+- memset(port, 0x00, sizeof(struct usb_serial_port));
+ port->number = i + serial->minor;
+ port->serial = serial;
+ spin_lock_init(&port->lock);
+--- gregkh-2.6.orig/drivers/usb/serial/visor.c
++++ gregkh-2.6/drivers/usb/serial/visor.c
+@@ -763,10 +763,9 @@ static int generic_startup(struct usb_se
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+- priv = kmalloc (sizeof(*priv), GFP_KERNEL);
++ priv = kzalloc (sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+- memset (priv, 0x00, sizeof(*priv));
+ spin_lock_init(&priv->lock);
+ usb_set_serial_port_data(serial->port[i], priv);
+ }
+--- gregkh-2.6.orig/drivers/usb/storage/isd200.c
++++ gregkh-2.6/drivers/usb/storage/isd200.c
+@@ -1382,7 +1382,7 @@ static int isd200_init_info(struct us_da
+ } else
+ US_DEBUGP("ERROR - kmalloc failure\n");
+
+- return(retStatus);
++ return retStatus;
+ }
+
+ /**************************************************************************
diff --git a/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch b/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch
new file mode 100644
index 0000000000000..e5d034766505f
--- /dev/null
+++ b/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch
@@ -0,0 +1,186 @@
+From david-b@pacbell.net Mon Feb 27 13:34:15 2006
+From: Eric Sesterhenn <snakebyte@gmx.de>
+Subject: USB: kzalloc() conversion in drivers/usb/gadget
+Date: Mon, 27 Feb 2006 13:34:10 -0800
+To: Greg KH <greg@kroah.com>
+Cc: Eric Sesterhenn <snakebyte@gmx.de>
+Content-Disposition: inline
+Message-Id: <200602271334.10698.david-b@pacbell.net>
+
+this patch converts drivers/usb to kzalloc usage.
+Compile tested with allyes config.
+
+I think there was a bug in drivers/usb/gadget/inode.c because
+it used sizeof(*data) for the kmalloc() and sizeof(data) for
+the memset(), since sizeof(data) just returns the size for a pointer.
+
+Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/gadget/dummy_hcd.c | 3 +--
+ drivers/usb/gadget/goku_udc.c | 3 +--
+ drivers/usb/gadget/inode.c | 6 ++----
+ drivers/usb/gadget/lh7a40x_udc.c | 3 +--
+ drivers/usb/gadget/net2280.c | 3 +--
+ drivers/usb/gadget/omap_udc.c | 6 ++----
+ drivers/usb/gadget/pxa2xx_udc.c | 3 +--
+ drivers/usb/gadget/serial.c | 3 +--
+ drivers/usb/gadget/zero.c | 3 +--
+ 9 files changed, 11 insertions(+), 22 deletions(-)
+
+--- gregkh-2.6.orig/drivers/usb/gadget/dummy_hcd.c
++++ gregkh-2.6/drivers/usb/gadget/dummy_hcd.c
+@@ -478,10 +478,9 @@ dummy_alloc_request (struct usb_ep *_ep,
+ return NULL;
+ ep = usb_ep_to_dummy_ep (_ep);
+
+- req = kmalloc (sizeof *req, mem_flags);
++ req = kzalloc(sizeof(*req), mem_flags);
+ if (!req)
+ return NULL;
+- memset (req, 0, sizeof *req);
+ INIT_LIST_HEAD (&req->queue);
+ return &req->req;
+ }
+--- gregkh-2.6.orig/drivers/usb/gadget/goku_udc.c
++++ gregkh-2.6/drivers/usb/gadget/goku_udc.c
+@@ -275,11 +275,10 @@ goku_alloc_request(struct usb_ep *_ep, g
+
+ if (!_ep)
+ return NULL;
+- req = kmalloc(sizeof *req, gfp_flags);
++ req = kzalloc(sizeof *req, gfp_flags);
+ if (!req)
+ return NULL;
+
+- memset(req, 0, sizeof *req);
+ req->req.dma = DMA_ADDR_INVALID;
+ INIT_LIST_HEAD(&req->queue);
+ return &req->req;
+--- gregkh-2.6.orig/drivers/usb/gadget/inode.c
++++ gregkh-2.6/drivers/usb/gadget/inode.c
+@@ -170,10 +170,9 @@ static struct dev_data *dev_new (void)
+ {
+ struct dev_data *dev;
+
+- dev = kmalloc (sizeof *dev, GFP_KERNEL);
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+- memset (dev, 0, sizeof *dev);
+ dev->state = STATE_DEV_DISABLED;
+ atomic_set (&dev->count, 1);
+ spin_lock_init (&dev->lock);
+@@ -1592,10 +1591,9 @@ static int activate_ep_files (struct dev
+ gadget_for_each_ep (ep, dev->gadget) {
+ struct ep_data *data;
+
+- data = kmalloc (sizeof *data, GFP_KERNEL);
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ goto enomem;
+- memset (data, 0, sizeof data);
+ data->state = STATE_EP_DISABLED;
+ init_MUTEX (&data->lock);
+ init_waitqueue_head (&data->wait);
+--- gregkh-2.6.orig/drivers/usb/gadget/lh7a40x_udc.c
++++ gregkh-2.6/drivers/usb/gadget/lh7a40x_udc.c
+@@ -1114,11 +1114,10 @@ static struct usb_request *lh7a40x_alloc
+
+ DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+- req = kmalloc(sizeof *req, gfp_flags);
++ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return 0;
+
+- memset(req, 0, sizeof *req);
+ INIT_LIST_HEAD(&req->queue);
+
+ return &req->req;
+--- gregkh-2.6.orig/drivers/usb/gadget/net2280.c
++++ gregkh-2.6/drivers/usb/gadget/net2280.c
+@@ -386,11 +386,10 @@ net2280_alloc_request (struct usb_ep *_e
+ return NULL;
+ ep = container_of (_ep, struct net2280_ep, ep);
+
+- req = kmalloc (sizeof *req, gfp_flags);
++ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return NULL;
+
+- memset (req, 0, sizeof *req);
+ req->req.dma = DMA_ADDR_INVALID;
+ INIT_LIST_HEAD (&req->queue);
+
+--- gregkh-2.6.orig/drivers/usb/gadget/omap_udc.c
++++ gregkh-2.6/drivers/usb/gadget/omap_udc.c
+@@ -273,9 +273,8 @@ omap_alloc_request(struct usb_ep *ep, gf
+ {
+ struct omap_req *req;
+
+- req = kmalloc(sizeof *req, gfp_flags);
++ req = kzalloc(sizeof(*req), gfp_flags);
+ if (req) {
+- memset (req, 0, sizeof *req);
+ req->req.dma = DMA_ADDR_INVALID;
+ INIT_LIST_HEAD (&req->queue);
+ }
+@@ -2586,11 +2585,10 @@ omap_udc_setup(struct platform_device *o
+ /* UDC_PULLUP_EN gates the chip clock */
+ // OTG_SYSCON_1_REG |= DEV_IDLE_EN;
+
+- udc = kmalloc (sizeof *udc, SLAB_KERNEL);
++ udc = kzalloc(sizeof(*udc), SLAB_KERNEL);
+ if (!udc)
+ return -ENOMEM;
+
+- memset(udc, 0, sizeof *udc);
+ spin_lock_init (&udc->lock);
+
+ udc->gadget.ops = &omap_gadget_ops;
+--- gregkh-2.6.orig/drivers/usb/gadget/pxa2xx_udc.c
++++ gregkh-2.6/drivers/usb/gadget/pxa2xx_udc.c
+@@ -335,11 +335,10 @@ pxa2xx_ep_alloc_request (struct usb_ep *
+ {
+ struct pxa2xx_request *req;
+
+- req = kmalloc (sizeof *req, gfp_flags);
++ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return NULL;
+
+- memset (req, 0, sizeof *req);
+ INIT_LIST_HEAD (&req->queue);
+ return &req->req;
+ }
+--- gregkh-2.6.orig/drivers/usb/gadget/serial.c
++++ gregkh-2.6/drivers/usb/gadget/serial.c
+@@ -2178,10 +2178,9 @@ static int gs_alloc_ports(struct gs_dev
+ return -EIO;
+
+ for (i=0; i<GS_NUM_PORTS; i++) {
+- if ((port=(struct gs_port *)kmalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
++ if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
+ return -ENOMEM;
+
+- memset(port, 0, sizeof(struct gs_port));
+ port->port_dev = dev;
+ port->port_num = i;
+ port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
+--- gregkh-2.6.orig/drivers/usb/gadget/zero.c
++++ gregkh-2.6/drivers/usb/gadget/zero.c
+@@ -1188,10 +1188,9 @@ autoconf_fail:
+
+
+ /* ok, we made sense of the hardware ... */
+- dev = kmalloc (sizeof *dev, SLAB_KERNEL);
++ dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+- memset (dev, 0, sizeof *dev);
+ spin_lock_init (&dev->lock);
+ dev->gadget = gadget;
+ set_gadget_data (gadget, dev);
diff --git a/usb/usb-pl2303-and-tiocmiwait.patch b/usb/usb-pl2303-and-tiocmiwait.patch
new file mode 100644
index 0000000000000..5319796e1a8e5
--- /dev/null
+++ b/usb/usb-pl2303-and-tiocmiwait.patch
@@ -0,0 +1,39 @@
+From jcb@inf.ed.ac.uk Wed Mar 1 15:31:40 2006
+Message-ID: <17413.30016.470872.240977@palau.inf.ed.ac.uk>
+Date: Wed, 1 Mar 2006 10:19:44 +0000
+From: Julian Bradfield <jcb+luu@inf.ed.ac.uk>
+cc: Greg KH <greg@kroah.com>
+Subject: USB: PL2303 and TIOCMIWAIT
+
+A while ago, I posted about TIOCMIWAIT not working with the PL2303
+USB-serial adapter.
+
+
+After a brief exchange with Greg, I tracked this to a missing wake-up
+in the USB interrupt procedures. I got our systems staff to install
+the enclosed very simple patch to our 2.6.12 kernels, and it all works
+fine as expected. I guess this should also apply to the latest version
+and go into the mainstream.
+
+Apologies for the long delay in posting the result.
+
+The routine being patched is pl2303_update_line_status
+
+Signed-off-by: Julian Bradfield <jcb+luu@inf.ed.ac.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/pl2303.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
++++ gregkh-2.6/drivers/usb/serial/pl2303.c
+@@ -826,6 +826,7 @@ static void pl2303_update_line_status(st
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->line_status = data[status_idx];
+ spin_unlock_irqrestore(&priv->lock, flags);
++ wake_up_interruptible (&priv->delta_msr_wait);
+
+ exit:
+ return;
diff --git a/usb/usb-serial-dynamic-id.patch b/usb/usb-serial-dynamic-id.patch
index 7f0edeb3fcb2a..423f4924a27d8 100644
--- a/usb/usb-serial-dynamic-id.patch
+++ b/usb/usb-serial-dynamic-id.patch
@@ -261,7 +261,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
.name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
-@@ -578,6 +578,39 @@ static struct usb_serial * create_serial
+@@ -577,6 +577,39 @@ static struct usb_serial * create_serial
return serial;
}
@@ -301,7 +301,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
{
struct list_head *p;
-@@ -587,11 +620,9 @@ static struct usb_serial_driver *search_
+@@ -586,11 +619,9 @@ static struct usb_serial_driver *search_
/* Check if the usb id matches a known device */
list_for_each(p, &usb_serial_driver_list) {
t = list_entry(p, struct usb_serial_driver, driver_list);
@@ -315,7 +315,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
return NULL;
-@@ -643,7 +674,7 @@ int usb_serial_probe(struct usb_interfac
+@@ -642,7 +673,7 @@ int usb_serial_probe(struct usb_interfac
return -EIO;
}
diff --git a/usb/usb-sn9c10x-driver-updates.patch b/usb/usb-sn9c10x-driver-updates.patch
new file mode 100644
index 0000000000000..be6f03ab95963
--- /dev/null
+++ b/usb/usb-sn9c10x-driver-updates.patch
@@ -0,0 +1,1073 @@
+From luca.risolia@studio.unibo.it Fri Feb 24 21:49:15 2006
+Date: Sat, 25 Feb 2006 06:50:47 +0000
+From: Luca Risolia <luca.risolia@studio.unibo.it>
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB: SN9C10x driver updates
+Message-ID: <20060225065047.GA31623@studio.unibo.it>
+Content-Disposition: inline
+
+SN9C10x driver updates.
+
+Changes: + new, - removed, * cleanup, @ bugfix
+
+@ Fix stream_interrupt()
+@ Fix vidioc_enum_input() and split vidioc_gs_input()
+@ Need usb_get|put_dev() when disconnecting, if the device is open
+* Use wait_event_interruptible_timeout() instead of wait_event_interruptible()
+ when waiting for video frames
+* replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream)
+* Cleanups and updates in the documentation
++ Use per-device sensor structures
++ Add support for PAS202BCA image sensors
++ Add frame_timeout module parameter
+
+Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/sn9c102.txt | 11 +
+ drivers/usb/media/Makefile | 5
+ drivers/usb/media/sn9c102.h | 23 ++-
+ drivers/usb/media/sn9c102_core.c | 170 +++++++++++++----------
+ drivers/usb/media/sn9c102_ov7630.c | 33 ++--
+ drivers/usb/media/sn9c102_pas202bca.c | 238 +++++++++++++++++++++++++++++++++
+ drivers/usb/media/sn9c102_pas202bcb.c | 2
+ drivers/usb/media/sn9c102_sensor.h | 15 +-
+ drivers/usb/media/sn9c102_tas5110c1b.c | 14 +
+ drivers/usb/media/sn9c102_tas5130d1b.c | 12 +
+ 10 files changed, 416 insertions(+), 107 deletions(-)
+
+--- gregkh-2.6.orig/Documentation/usb/sn9c102.txt
++++ gregkh-2.6/Documentation/usb/sn9c102.txt
+@@ -196,6 +196,14 @@ Description: Force the application to
+ 1 = force memory unmapping (save memory)
+ Default: 0
+ -------------------------------------------------------------------------------
++Name: frame_timeout
++Type: uint array (min = 0, max = 64)
++Syntax: <n[,...]>
++Description: Timeout for a video frame in seconds. This parameter is
++ specific for each detected camera. This parameter can be
++ changed at runtime thanks to the /sys filesystem interface.
++Default: 2
++-------------------------------------------------------------------------------
+ Name: debug
+ Type: ushort
+ Syntax: <n>
+@@ -321,6 +329,7 @@ Vendor ID Product ID
+ --------- ----------
+ 0x0c45 0x6001
+ 0x0c45 0x6005
++0x0c45 0x6007
+ 0x0c45 0x6009
+ 0x0c45 0x600d
+ 0x0c45 0x6024
+@@ -370,6 +379,7 @@ HV7131D Hynix Semiconductor, Inc.
+ MI-0343 Micron Technology, Inc.
+ OV7630 OmniVision Technologies, Inc.
+ PAS106B PixArt Imaging, Inc.
++PAS202BCA PixArt Imaging, Inc.
+ PAS202BCB PixArt Imaging, Inc.
+ TAS5110C1B Taiwan Advanced Sensor Corporation
+ TAS5130D1B Taiwan Advanced Sensor Corporation
+@@ -493,6 +503,7 @@ Many thanks to following persons for the
+ order):
+
+ - Luca Capello for the donation of a webcam;
++- Philippe Coval for having helped testing the PAS202BCA image sensor;
+ - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
+ donation of a webcam;
+ - Jon Hollstrom for the donation of a webcam;
+--- gregkh-2.6.orig/drivers/usb/media/Makefile
++++ gregkh-2.6/drivers/usb/media/Makefile
+@@ -2,7 +2,10 @@
+ # Makefile for USB Media drivers
+ #
+
+-sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
++sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
++ sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
++ sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
++ sn9c102_tas5130d1b.o
+ et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
+ zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_core.c
++++ gregkh-2.6/drivers/usb/media/sn9c102_core.c
+@@ -25,11 +25,9 @@
+ #include <linux/moduleparam.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+-#include <linux/string.h>
+ #include <linux/device.h>
+ #include <linux/fs.h>
+ #include <linux/delay.h>
+-#include <linux/stddef.h>
+ #include <linux/compiler.h>
+ #include <linux/ioctl.h>
+ #include <linux/poll.h>
+@@ -49,8 +47,8 @@
+ #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
+ #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
+ #define SN9C102_MODULE_LICENSE "GPL"
+-#define SN9C102_MODULE_VERSION "1:1.26"
+-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26)
++#define SN9C102_MODULE_VERSION "1:1.27"
++#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27)
+
+ /*****************************************************************************/
+
+@@ -89,6 +87,15 @@ MODULE_PARM_DESC(force_munmap,
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
+
++static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
++ SN9C102_FRAME_TIMEOUT};
++module_param_array(frame_timeout, uint, NULL, 0644);
++MODULE_PARM_DESC(frame_timeout,
++ "\n<n[,...]> Timeout for a video frame in seconds."
++ "\nThis parameter is specific for each detected camera."
++ "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
++ "\n");
++
+ #ifdef SN9C102_DEBUG
+ static unsigned short debug = SN9C102_DEBUG_LEVEL;
+ module_param(debug, ushort, 0644);
+@@ -128,8 +135,8 @@ static u32
+ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
+ enum sn9c102_io_method io)
+ {
+- struct v4l2_pix_format* p = &(cam->sensor->pix_format);
+- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
++ struct v4l2_pix_format* p = &(cam->sensor.pix_format);
++ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
+ const size_t imagesize = cam->module_param.force_munmap ||
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+@@ -449,19 +456,13 @@ sn9c102_i2c_try_write(struct sn9c102_dev
+
+ int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
+ {
+- if (!cam->sensor)
+- return -1;
+-
+- return sn9c102_i2c_try_read(cam, cam->sensor, address);
++ return sn9c102_i2c_try_read(cam, &cam->sensor, address);
+ }
+
+
+ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
+ {
+- if (!cam->sensor)
+- return -1;
+-
+- return sn9c102_i2c_try_write(cam, cam->sensor, address, value);
++ return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
+ }
+
+ /*****************************************************************************/
+@@ -505,7 +506,7 @@ sn9c102_find_eof_header(struct sn9c102_d
+ size_t eoflen = sizeof(sn9c102_eof_header_t), i;
+ unsigned j, n = sizeof(sn9c102_eof_header) / eoflen;
+
+- if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
++ if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+ return NULL; /* EOF header does not exist in compressed data */
+
+ for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++)
+@@ -535,7 +536,7 @@ static void sn9c102_urb_complete(struct
+ if ((*f))
+ (*f)->state = F_QUEUED;
+ DBG(3, "Stream interrupted");
+- wake_up_interruptible(&cam->wait_stream);
++ wake_up(&cam->wait_stream);
+ }
+
+ if (cam->state & DEV_DISCONNECTED)
+@@ -553,9 +554,9 @@ static void sn9c102_urb_complete(struct
+ (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
+ frame);
+
+- imagesize = (cam->sensor->pix_format.width *
+- cam->sensor->pix_format.height *
+- cam->sensor->pix_format.priv) / 8;
++ imagesize = (cam->sensor.pix_format.width *
++ cam->sensor.pix_format.height *
++ cam->sensor.pix_format.priv) / 8;
+
+ soflen = (cam->bridge) == BRIDGE_SN9C103 ?
+ sizeof(sn9c103_sof_header_t) :
+@@ -579,7 +580,7 @@ static void sn9c102_urb_complete(struct
+
+ redo:
+ sof = sn9c102_find_sof_header(cam, pos, len);
+- if (!sof) {
++ if (likely(!sof)) {
+ eof = sn9c102_find_eof_header(cam, pos, len);
+ if ((*f)->state == F_GRABBING) {
+ end_of_frame:
+@@ -589,8 +590,9 @@ end_of_frame:
+ img = (eof > pos) ? eof - pos - 1 : 0;
+
+ if ((*f)->buf.bytesused+img > imagesize) {
+- u32 b = (*f)->buf.bytesused + img -
+- imagesize;
++ u32 b;
++ b = (*f)->buf.bytesused + img -
++ imagesize;
+ img = imagesize - (*f)->buf.bytesused;
+ DBG(3, "Expected EOF not found: "
+ "video frame cut");
+@@ -608,9 +610,10 @@ end_of_frame:
+ (*f)->buf.bytesused += img;
+
+ if ((*f)->buf.bytesused == imagesize ||
+- (cam->sensor->pix_format.pixelformat ==
++ (cam->sensor.pix_format.pixelformat ==
+ V4L2_PIX_FMT_SN9C10X && eof)) {
+- u32 b = (*f)->buf.bytesused;
++ u32 b;
++ b = (*f)->buf.bytesused;
+ (*f)->state = F_DONE;
+ (*f)->buf.sequence= ++cam->frame_count;
+ spin_lock(&cam->queue_lock);
+@@ -667,7 +670,7 @@ start_of_frame:
+ if (eof && eof < sof)
+ goto end_of_frame; /* (1) */
+ else {
+- if (cam->sensor->pix_format.pixelformat ==
++ if (cam->sensor.pix_format.pixelformat ==
+ V4L2_PIX_FMT_SN9C10X) {
+ eof = sof - soflen;
+ goto end_of_frame;
+@@ -808,20 +811,21 @@ static int sn9c102_stop_transfer(struct
+
+ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
+ {
+- int err = 0;
++ long timeout;
+
+ cam->stream = STREAM_INTERRUPT;
+- err = wait_event_timeout(cam->wait_stream,
+- (cam->stream == STREAM_OFF) ||
+- (cam->state & DEV_DISCONNECTED),
+- SN9C102_URB_TIMEOUT);
++ timeout = wait_event_timeout(cam->wait_stream,
++ (cam->stream == STREAM_OFF) ||
++ (cam->state & DEV_DISCONNECTED),
++ SN9C102_URB_TIMEOUT);
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+- else if (err) {
++ else if (cam->stream != STREAM_OFF) {
+ cam->state |= DEV_MISCONFIGURED;
+- DBG(1, "The camera is misconfigured. To use it, close and "
+- "open /dev/video%d again.", cam->v4ldev->minor);
+- return err;
++ DBG(1, "URB timeout reached. The camera is misconfigured. "
++ "To use it, close and open /dev/video%d again.",
++ cam->v4ldev->minor);
++ return -EIO;
+ }
+
+ return 0;
+@@ -1057,7 +1061,7 @@ static ssize_t sn9c102_show_i2c_val(stru
+ return -ENODEV;
+ }
+
+- if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) {
++ if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
+ mutex_unlock(&sn9c102_sysfs_lock);
+ return -ENOSYS;
+ }
+@@ -1094,7 +1098,7 @@ sn9c102_store_i2c_val(struct class_devic
+ return -ENODEV;
+ }
+
+- if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) {
++ if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
+ mutex_unlock(&sn9c102_sysfs_lock);
+ return -ENOSYS;
+ }
+@@ -1249,7 +1253,7 @@ static void sn9c102_create_sysfs(struct
+ video_device_create_file(v4ldev, &class_device_attr_blue);
+ video_device_create_file(v4ldev, &class_device_attr_red);
+ }
+- if (cam->sensor && cam->sensor->sysfs_ops) {
++ if (cam->sensor.sysfs_ops) {
+ video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+ video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+ }
+@@ -1312,7 +1316,7 @@ static int sn9c102_set_scale(struct sn9c
+
+ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
+ v_start = (u8)(rect->top - s->cropcap.bounds.top),
+ h_size = (u8)(rect->width / 16),
+@@ -1335,7 +1339,7 @@ static int sn9c102_set_crop(struct sn9c1
+
+ static int sn9c102_init(struct sn9c102_device* cam)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ struct v4l2_queryctrl *qctrl;
+ struct v4l2_rect* rect;
+@@ -1428,6 +1432,8 @@ static void sn9c102_release_resources(st
+ video_set_drvdata(cam->v4ldev, NULL);
+ video_unregister_device(cam->v4ldev);
+
++ usb_put_dev(cam->usbdev);
++
+ mutex_unlock(&sn9c102_sysfs_lock);
+
+ kfree(cam->control_buffer);
+@@ -1541,6 +1547,7 @@ sn9c102_read(struct file* filp, char __u
+ struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+ struct sn9c102_frame_t* f, * i;
+ unsigned long lock_flags;
++ long timeout;
+ int err = 0;
+
+ if (mutex_lock_interruptible(&cam->fileop_mutex))
+@@ -1592,20 +1599,22 @@ sn9c102_read(struct file* filp, char __u
+ mutex_unlock(&cam->fileop_mutex);
+ return -EAGAIN;
+ }
+- err = wait_event_interruptible
+- ( cam->wait_frame,
+- (!list_empty(&cam->outqueue)) ||
+- (cam->state & DEV_DISCONNECTED) ||
+- (cam->state & DEV_MISCONFIGURED) );
+- if (err) {
++ timeout = wait_event_interruptible_timeout
++ ( cam->wait_frame,
++ (!list_empty(&cam->outqueue)) ||
++ (cam->state & DEV_DISCONNECTED) ||
++ (cam->state & DEV_MISCONFIGURED),
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
++ if (timeout < 0) {
+ mutex_unlock(&cam->fileop_mutex);
+- return err;
++ return timeout;
+ }
+ if (cam->state & DEV_DISCONNECTED) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -ENODEV;
+ }
+- if (cam->state & DEV_MISCONFIGURED) {
++ if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -EIO;
+ }
+@@ -1816,6 +1825,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_
+
+ memset(&i, 0, sizeof(i));
+ strcpy(i.name, "Camera");
++ i.type = V4L2_INPUT_TYPE_CAMERA;
+
+ if (copy_to_user(arg, &i, sizeof(i)))
+ return -EFAULT;
+@@ -1825,7 +1835,19 @@ sn9c102_vidioc_enuminput(struct sn9c102_
+
+
+ static int
+-sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg)
++sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
++{
++ int index = 0;
++
++ if (copy_to_user(arg, &index, sizeof(index)))
++ return -EFAULT;
++
++ return 0;
++}
++
++
++static int
++sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
+ {
+ int index;
+
+@@ -1842,7 +1864,7 @@ sn9c102_vidioc_gs_input(struct sn9c102_d
+ static int
+ sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_queryctrl qc;
+ u8 i;
+
+@@ -1864,7 +1886,7 @@ sn9c102_vidioc_query_ctrl(struct sn9c102
+ static int
+ sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ int err = 0;
+ u8 i;
+@@ -1896,7 +1918,7 @@ exit:
+ static int
+ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ u8 i;
+ int err = 0;
+@@ -1909,6 +1931,8 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_dev
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
++ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
++ return -EINVAL;
+ if (ctrl.value < s->qctrl[i].minimum ||
+ ctrl.value > s->qctrl[i].maximum)
+ return -ERANGE;
+@@ -1931,7 +1955,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_dev
+ static int
+ sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
++ struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
+
+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cc->pixelaspect.numerator = 1;
+@@ -1947,7 +1971,7 @@ sn9c102_vidioc_cropcap(struct sn9c102_de
+ static int
+ sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_crop crop = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ };
+@@ -1964,7 +1988,7 @@ sn9c102_vidioc_g_crop(struct sn9c102_dev
+ static int
+ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_crop crop;
+ struct v4l2_rect* rect;
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+@@ -2105,7 +2129,7 @@ static int
+ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
+ {
+ struct v4l2_format format;
+- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
++ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
+
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
+@@ -2130,7 +2154,7 @@ static int
+ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
+ void __user * arg)
+ {
+- struct sn9c102_sensor* s = cam->sensor;
++ struct sn9c102_sensor* s = &cam->sensor;
+ struct v4l2_format format;
+ struct v4l2_pix_format* pix;
+ struct v4l2_pix_format* pfmt = &(s->pix_format);
+@@ -2417,7 +2441,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_devi
+ struct v4l2_buffer b;
+ struct sn9c102_frame_t *f;
+ unsigned long lock_flags;
+- int err = 0;
++ long timeout;
+
+ if (copy_from_user(&b, arg, sizeof(b)))
+ return -EFAULT;
+@@ -2430,16 +2454,18 @@ sn9c102_vidioc_dqbuf(struct sn9c102_devi
+ return -EINVAL;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+- err = wait_event_interruptible
+- ( cam->wait_frame,
+- (!list_empty(&cam->outqueue)) ||
+- (cam->state & DEV_DISCONNECTED) ||
+- (cam->state & DEV_MISCONFIGURED) );
+- if (err)
+- return err;
++ timeout = wait_event_interruptible_timeout
++ ( cam->wait_frame,
++ (!list_empty(&cam->outqueue)) ||
++ (cam->state & DEV_DISCONNECTED) ||
++ (cam->state & DEV_MISCONFIGURED),
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
++ if (timeout < 0)
++ return timeout;
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+- if (cam->state & DEV_MISCONFIGURED)
++ if (!timeout || (cam->state & DEV_MISCONFIGURED))
+ return -EIO;
+ }
+
+@@ -2571,8 +2597,10 @@ static int sn9c102_ioctl_v4l2(struct ino
+ return sn9c102_vidioc_enuminput(cam, arg);
+
+ case VIDIOC_G_INPUT:
++ return sn9c102_vidioc_g_input(cam, arg);
++
+ case VIDIOC_S_INPUT:
+- return sn9c102_vidioc_gs_input(cam, arg);
++ return sn9c102_vidioc_s_input(cam, arg);
+
+ case VIDIOC_QUERYCTRL:
+ return sn9c102_vidioc_query_ctrl(cam, arg);
+@@ -2752,10 +2780,10 @@ sn9c102_usb_probe(struct usb_interface*
+ break;
+ }
+
+- if (!err && cam->sensor) {
+- DBG(2, "%s image sensor detected", cam->sensor->name);
++ if (!err) {
++ DBG(2, "%s image sensor detected", cam->sensor.name);
+ DBG(3, "Support for %s maintained by %s",
+- cam->sensor->name, cam->sensor->maintainer);
++ cam->sensor.name, cam->sensor.maintainer);
+ } else {
+ DBG(1, "No supported image sensor detected");
+ err = -ENODEV;
+@@ -2793,6 +2821,7 @@ sn9c102_usb_probe(struct usb_interface*
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+
+ cam->module_param.force_munmap = force_munmap[dev_nr];
++ cam->module_param.frame_timeout = frame_timeout[dev_nr];
+
+ dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+@@ -2841,7 +2870,8 @@ static void sn9c102_usb_disconnect(struc
+ sn9c102_stop_transfer(cam);
+ cam->state |= DEV_DISCONNECTED;
+ wake_up_interruptible(&cam->wait_frame);
+- wake_up_interruptible(&cam->wait_stream);
++ wake_up(&cam->wait_stream);
++ usb_get_dev(cam->usbdev);
+ } else {
+ cam->state |= DEV_DISCONNECTED;
+ sn9c102_release_resources(cam);
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102.h
++++ gregkh-2.6/drivers/usb/media/sn9c102.h
+@@ -34,7 +34,8 @@
+ #include <linux/param.h>
+ #include <linux/rwsem.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
+
+ #include "sn9c102_sensor.h"
+
+@@ -51,6 +52,7 @@
+ #define SN9C102_ALTERNATE_SETTING 8
+ #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+ #define SN9C102_CTRL_TIMEOUT 300
++#define SN9C102_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr {
+
+ struct sn9c102_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+ static DEFINE_MUTEX(sn9c102_sysfs_lock);
+@@ -117,7 +120,7 @@ struct sn9c102_device {
+ struct video_device* v4ldev;
+
+ enum sn9c102_bridge bridge;
+- struct sn9c102_sensor* sensor;
++ struct sn9c102_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[SN9C102_URBS];
+@@ -149,12 +152,21 @@ struct sn9c102_device {
+
+ /*****************************************************************************/
+
++struct sn9c102_device*
++sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
++
+ void
+ sn9c102_attach_sensor(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
+ }
+
+ /*****************************************************************************/
+@@ -197,7 +209,8 @@ do {
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
++dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args)
+
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_ov7630.c
++++ gregkh-2.6/drivers/usb/media/sn9c102_ov7630.c
+@@ -34,8 +34,8 @@ static int ov7630_init(struct sn9c102_de
+ err += sn9c102_write_reg(cam, 0x0f, 0x18);
+ err += sn9c102_write_reg(cam, 0x50, 0x19);
+
+- err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+- err += sn9c102_i2c_write(cam, 0x11, 0x00);
++ err += sn9c102_i2c_write(cam, 0x12, 0x80);
++ err += sn9c102_i2c_write(cam, 0x11, 0x01);
+ err += sn9c102_i2c_write(cam, 0x15, 0x34);
+ err += sn9c102_i2c_write(cam, 0x16, 0x03);
+ err += sn9c102_i2c_write(cam, 0x17, 0x1c);
+@@ -43,12 +43,14 @@ static int ov7630_init(struct sn9c102_de
+ err += sn9c102_i2c_write(cam, 0x19, 0x06);
+ err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+ err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+- err += sn9c102_i2c_write(cam, 0x20, 0x44);
++ err += sn9c102_i2c_write(cam, 0x20, 0xf6);
+ err += sn9c102_i2c_write(cam, 0x23, 0xee);
+ err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+ err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+- err += sn9c102_i2c_write(cam, 0x28, 0x20);
++ err += sn9c102_i2c_write(cam, 0x28, 0xa0);
+ err += sn9c102_i2c_write(cam, 0x29, 0x30);
++ err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
++ err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
+ err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+ err += sn9c102_i2c_write(cam, 0x30, 0x24);
+ err += sn9c102_i2c_write(cam, 0x32, 0x86);
+@@ -80,7 +82,7 @@ static int ov7630_set_ctrl(struct sn9c10
+ err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+- err += sn9c102_i2c_write(cam, 0x03, ctrl->value);
++ err += sn9c102_i2c_write(cam, 0x01, ctrl->value);
+ break;
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+@@ -108,7 +110,7 @@ static int ov7630_set_ctrl(struct sn9c10
+ err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+- err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09);
++ err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
+ break;
+ case V4L2_CID_AUTOGAIN:
+ err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
+@@ -371,26 +373,29 @@ static struct sn9c102_sensor ov7630 = {
+
+ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
+ {
++ const struct usb_device_id ov7630_id_table[] = {
++ { USB_DEVICE(0x0c45, 0x602c), },
++ { USB_DEVICE(0x0c45, 0x602d), },
++ { USB_DEVICE(0x0c45, 0x608f), },
++ { USB_DEVICE(0x0c45, 0x60b0), },
++ { }
++ };
+ int err = 0;
+
+- sn9c102_attach_sensor(cam, &ov7630);
+-
+- if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c &&
+- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d &&
+- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f &&
+- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0)
++ if (!sn9c102_match_id(cam, ov7630_id_table))
+ return -ENODEV;
+
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x00, 0x01);
+ err += sn9c102_write_reg(cam, 0x28, 0x17);
+-
+ if (err)
+ return -EIO;
+
+- err += sn9c102_i2c_write(cam, 0x0b, 0);
++ err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0);
+ if (err)
+ return -ENODEV;
+
++ sn9c102_attach_sensor(cam, &ov7630);
++
+ return 0;
+ }
+--- /dev/null
++++ gregkh-2.6/drivers/usb/media/sn9c102_pas202bca.c
+@@ -0,0 +1,238 @@
++/***************************************************************************
++ * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera *
++ * Controllers *
++ * *
++ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
++ * *
++ * This program is free software; you can redistribute it and/or modify *
++ * it under the terms of the GNU General Public License as published by *
++ * the Free Software Foundation; either version 2 of the License, or *
++ * (at your option) any later version. *
++ * *
++ * This program is distributed in the hope that it will be useful, *
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
++ * GNU General Public License for more details. *
++ * *
++ * You should have received a copy of the GNU General Public License *
++ * along with this program; if not, write to the Free Software *
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
++ ***************************************************************************/
++
++#include <linux/delay.h>
++#include "sn9c102_sensor.h"
++
++
++static struct sn9c102_sensor pas202bca;
++
++
++static int pas202bca_init(struct sn9c102_device* cam)
++{
++ int err = 0;
++
++ err += sn9c102_write_reg(cam, 0x00, 0x10);
++ err += sn9c102_write_reg(cam, 0x00, 0x11);
++ err += sn9c102_write_reg(cam, 0x00, 0x14);
++ err += sn9c102_write_reg(cam, 0x20, 0x17);
++ err += sn9c102_write_reg(cam, 0x30, 0x19);
++ err += sn9c102_write_reg(cam, 0x09, 0x18);
++
++ err += sn9c102_i2c_write(cam, 0x02, 0x14);
++ err += sn9c102_i2c_write(cam, 0x03, 0x40);
++ err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
++ err += sn9c102_i2c_write(cam, 0x0e, 0x01);
++ err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
++ err += sn9c102_i2c_write(cam, 0x10, 0x08);
++ err += sn9c102_i2c_write(cam, 0x13, 0x63);
++ err += sn9c102_i2c_write(cam, 0x15, 0x70);
++ err += sn9c102_i2c_write(cam, 0x11, 0x01);
++
++ msleep(400);
++
++ return err;
++}
++
++
++static int pas202bca_set_pix_format(struct sn9c102_device* cam,
++ const struct v4l2_pix_format* pix)
++{
++ int err = 0;
++
++ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
++ err += sn9c102_write_reg(cam, 0x24, 0x17);
++ else
++ err += sn9c102_write_reg(cam, 0x20, 0x17);
++
++ return err;
++}
++
++
++static int pas202bca_set_ctrl(struct sn9c102_device* cam,
++ const struct v4l2_control* ctrl)
++{
++ int err = 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_EXPOSURE:
++ err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
++ err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
++ break;
++ case V4L2_CID_RED_BALANCE:
++ err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
++ break;
++ case V4L2_CID_BLUE_BALANCE:
++ err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
++ break;
++ case V4L2_CID_GAIN:
++ err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
++ break;
++ case SN9C102_V4L2_CID_GREEN_BALANCE:
++ err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
++ break;
++ case SN9C102_V4L2_CID_DAC_MAGNITUDE:
++ err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
++ break;
++ default:
++ return -EINVAL;
++ }
++ err += sn9c102_i2c_write(cam, 0x11, 0x01);
++
++ return err ? -EIO : 0;
++}
++
++
++static int pas202bca_set_crop(struct sn9c102_device* cam,
++ const struct v4l2_rect* rect)
++{
++ struct sn9c102_sensor* s = &pas202bca;
++ int err = 0;
++ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3,
++ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
++
++ err += sn9c102_write_reg(cam, h_start, 0x12);
++ err += sn9c102_write_reg(cam, v_start, 0x13);
++
++ return err;
++}
++
++
++static struct sn9c102_sensor pas202bca = {
++ .name = "PAS202BCA",
++ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
++ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
++ .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
++ .interface = SN9C102_I2C_2WIRES,
++ .i2c_slave_id = 0x40,
++ .init = &pas202bca_init,
++ .qctrl = {
++ {
++ .id = V4L2_CID_EXPOSURE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "exposure",
++ .minimum = 0x01e5,
++ .maximum = 0x3fff,
++ .step = 0x0001,
++ .default_value = 0x01e5,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_GAIN,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "global gain",
++ .minimum = 0x00,
++ .maximum = 0x1f,
++ .step = 0x01,
++ .default_value = 0x0c,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_RED_BALANCE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "red balance",
++ .minimum = 0x00,
++ .maximum = 0x0f,
++ .step = 0x01,
++ .default_value = 0x01,
++ .flags = 0,
++ },
++ {
++ .id = V4L2_CID_BLUE_BALANCE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "blue balance",
++ .minimum = 0x00,
++ .maximum = 0x0f,
++ .step = 0x01,
++ .default_value = 0x05,
++ .flags = 0,
++ },
++ {
++ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "green balance",
++ .minimum = 0x00,
++ .maximum = 0x0f,
++ .step = 0x01,
++ .default_value = 0x00,
++ .flags = 0,
++ },
++ {
++ .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "DAC magnitude",
++ .minimum = 0x00,
++ .maximum = 0xff,
++ .step = 0x01,
++ .default_value = 0x04,
++ .flags = 0,
++ },
++ },
++ .set_ctrl = &pas202bca_set_ctrl,
++ .cropcap = {
++ .bounds = {
++ .left = 0,
++ .top = 0,
++ .width = 640,
++ .height = 480,
++ },
++ .defrect = {
++ .left = 0,
++ .top = 0,
++ .width = 640,
++ .height = 480,
++ },
++ },
++ .set_crop = &pas202bca_set_crop,
++ .pix_format = {
++ .width = 640,
++ .height = 480,
++ .pixelformat = V4L2_PIX_FMT_SBGGR8,
++ .priv = 8,
++ },
++ .set_pix_format = &pas202bca_set_pix_format
++};
++
++
++int sn9c102_probe_pas202bca(struct sn9c102_device* cam)
++{
++ const struct usb_device_id pas202bca_id_table[] = {
++ { USB_DEVICE(0x0c45, 0x60af), },
++ { }
++ };
++ int err = 0;
++
++ if (!sn9c102_match_id(cam,pas202bca_id_table))
++ return -ENODEV;
++
++ err += sn9c102_write_reg(cam, 0x01, 0x01);
++ err += sn9c102_write_reg(cam, 0x40, 0x01);
++ err += sn9c102_write_reg(cam, 0x28, 0x17);
++ if (err)
++ return -EIO;
++
++ if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */
++ return -ENODEV;
++
++ sn9c102_attach_sensor(cam, &pas202bca);
++
++ return 0;
++}
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_pas202bcb.c
++++ gregkh-2.6/drivers/usb/media/sn9c102_pas202bcb.c
+@@ -263,7 +263,7 @@ static struct sn9c102_sensor pas202bcb =
+
+
+ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
+-{
++{
+ int r0 = 0, r1 = 0, err = 0;
+ unsigned int pid = 0;
+
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_sensor.h
++++ gregkh-2.6/drivers/usb/media/sn9c102_sensor.h
+@@ -66,6 +66,7 @@ extern int sn9c102_probe_hv7131d(struct
+ extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+ extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
+ extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
++extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
+ extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
+ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
+ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
+@@ -81,12 +82,17 @@ static int (*sn9c102_sensor_table[])(str
+ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
+ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \
+ &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \
++ &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \
+ &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \
+ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
+ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
+ NULL, \
+ };
+
++/* Device identification */
++extern struct sn9c102_device*
++sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
++
+ /* Attach a probed sensor to the camera. */
+ extern void
+ sn9c102_attach_sensor(struct sn9c102_device* cam,
+@@ -108,6 +114,7 @@ sn9c102_attach_sensor(struct sn9c102_dev
+ static const struct usb_device_id sn9c102_id_table[] = { \
+ { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \
+ { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \
++ { USB_DEVICE(0x0c45, 0x6007), }, \
+ { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \
+ { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \
+ { USB_DEVICE(0x0c45, 0x6024), }, \
+@@ -126,7 +133,7 @@ static const struct usb_device_id sn9c10
+ { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \
+- { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \
++ { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \
+ { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \
+@@ -359,12 +366,6 @@ struct sn9c102_sensor {
+ error code without rolling back.
+ */
+
+- const struct usb_device* usbdev;
+- /*
+- Points to the usb_device struct after the sensor is attached.
+- Do not touch unless you know what you are doing.
+- */
+-
+ /*
+ Do NOT write to the data below, it's READ ONLY. It is used by the
+ core module to store successfully updated values of the above
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_tas5110c1b.c
++++ gregkh-2.6/drivers/usb/media/sn9c102_tas5110c1b.c
+@@ -142,14 +142,18 @@ static struct sn9c102_sensor tas5110c1b
+
+ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
+ {
+- /* This sensor has no identifiers, so let's attach it anyway */
+- sn9c102_attach_sensor(cam, &tas5110c1b);
++ const struct usb_device_id tas5110c1b_id_table[] = {
++ { USB_DEVICE(0x0c45, 0x6001), },
++ { USB_DEVICE(0x0c45, 0x6005), },
++ { USB_DEVICE(0x0c45, 0x60ab), },
++ { }
++ };
+
+ /* Sensor detection is based on USB pid/vid */
+- if (le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6001 &&
+- le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6005 &&
+- le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x60ab)
++ if (!sn9c102_match_id(cam, tas5110c1b_id_table))
+ return -ENODEV;
+
++ sn9c102_attach_sensor(cam, &tas5110c1b);
++
+ return 0;
+ }
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102_tas5130d1b.c
++++ gregkh-2.6/drivers/usb/media/sn9c102_tas5130d1b.c
+@@ -153,13 +153,17 @@ static struct sn9c102_sensor tas5130d1b
+
+ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
+ {
+- /* This sensor has no identifiers, so let's attach it anyway */
+- sn9c102_attach_sensor(cam, &tas5130d1b);
++ const struct usb_device_id tas5130d1b_id_table[] = {
++ { USB_DEVICE(0x0c45, 0x6025), },
++ { USB_DEVICE(0x0c45, 0x60aa), },
++ { }
++ };
+
+ /* Sensor detection is based on USB pid/vid */
+- if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6025 &&
+- le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x60aa)
++ if (!sn9c102_match_id(cam, tas5130d1b_id_table))
+ return -ENODEV;
+
++ sn9c102_attach_sensor(cam, &tas5130d1b);
++
+ return 0;
+ }
diff --git a/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch b/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch
new file mode 100644
index 0000000000000..043b322d58df9
--- /dev/null
+++ b/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch
@@ -0,0 +1,42 @@
+From akpm@osdl.org Wed Mar 1 15:57:52 2006
+Message-Id: <200603010854.k218sepU024122@shell0.pdx.osdl.net>
+Subject: USB: support for USB-to-serial cable from Speed Dragon Multimedia
+To: dick@streefland.net, greg@kroah.com, mm-commits@vger.kernel.org
+From: akpm@osdl.org
+Date: Wed, 01 Mar 2006 00:53:33 -0800
+
+From: Dick Streefland <dick@streefland.net>
+
+The USB data cable for my Samsung GSM phone contains the USB-to-serial
+converter chip MS3303H from Speed Dragon Multimedia, Inc. that appears to
+be compatible with the PL2303 chip. The following patch adds support for
+this chip to the pl2303 driver.
+
+Signed-off-by: Dick Streefland <dick@streefland.net>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/serial/pl2303.c | 1 +
+ drivers/usb/serial/pl2303.h | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
++++ gregkh-2.6/drivers/usb/serial/pl2303.c
+@@ -77,6 +77,7 @@ static struct usb_device_id id_table []
+ { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
+ { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
+ { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
++ { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
+ { } /* Terminating entry */
+ };
+
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.h
++++ gregkh-2.6/drivers/usb/serial/pl2303.h
+@@ -75,3 +75,7 @@
+ /* Leadtek GPS 9531 (ID 0413:2101) */
+ #define LEADTEK_VENDOR_ID 0x0413
+ #define LEADTEK_9531_PRODUCT_ID 0x2101
++
++/* USB GSM cable from Speed Dragon Multimedia, Ltd */
++#define SPEEDDRAGON_VENDOR_ID 0x0e55
++#define SPEEDDRAGON_PRODUCT_ID 0x110b
diff --git a/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch b/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch
new file mode 100644
index 0000000000000..5058539a7913f
--- /dev/null
+++ b/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch
@@ -0,0 +1,59 @@
+From stern@rowland.harvard.edu Wed Mar 1 15:58:26 2006
+Date: Tue, 28 Feb 2006 10:16:12 -0500 (EST)
+From: Alan Stern <stern@rowland.harvard.edu>
+To: Greg KH <greg@kroah.com>
+cc: "Frantz, Chris" <Chris.Frantz@hp.com>, Brian Baker <brian.b@hp.com>, Pete Zaitcev <zaitcev@redhat.com>
+Subject: USB: UHCI: Increase port-reset completion delay for HP controllers
+Message-ID: <Pine.LNX.4.44L0.0602281011040.4987-100000@iolanthe.rowland.org>
+
+This patch (as657) increases the port-reset completion delay in uhci-hcd
+for HP's embedded controllers. Unlike other UHCI controllers, the HP
+chips can take as long as 250 us to carry out the processing associated
+with finishing a port reset.
+
+This fixes Novell bug #148761.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/uhci-hub.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/host/uhci-hub.c
++++ gregkh-2.6/drivers/usb/host/uhci-hub.c
+@@ -99,6 +99,21 @@ static void uhci_finish_suspend(struct u
+ }
+ }
+
++/* Wait for the UHCI controller in HP's iLO2 server management chip.
++ * It can take up to 250 us to finish a reset and set the CSC bit.
++ */
++static void wait_for_HP(unsigned long port_addr)
++{
++ int i;
++
++ for (i = 10; i < 250; i += 10) {
++ if (inw(port_addr) & USBPORTSC_CSC)
++ return;
++ udelay(10);
++ }
++ /* Log a warning? */
++}
++
+ static void uhci_check_ports(struct uhci_hcd *uhci)
+ {
+ unsigned int port;
+@@ -113,6 +128,12 @@ static void uhci_check_ports(struct uhci
+ CLR_RH_PORTSTAT(USBPORTSC_PR);
+ udelay(10);
+
++ /* HP's server management chip requires
++ * a longer delay. */
++ if (to_pci_dev(uhci_dev(uhci))->vendor ==
++ PCI_VENDOR_ID_HP)
++ wait_for_HP(port_addr);
++
+ /* If the port was enabled before, turning
+ * reset on caused a port enable change.
+ * Turning reset off causes a port connect
diff --git a/usb/usb-zc0301-driver-updates-2.patch b/usb/usb-zc0301-driver-updates-2.patch
new file mode 100644
index 0000000000000..8ae04c03d3cd0
--- /dev/null
+++ b/usb/usb-zc0301-driver-updates-2.patch
@@ -0,0 +1,496 @@
+From luca.risolia@studio.unibo.it Fri Feb 24 21:56:12 2006
+Date: Sat, 25 Feb 2006 06:57:49 +0000
+From: Luca Risolia <luca.risolia@studio.unibo.it>
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB: ZC0301 driver updates
+Message-ID: <20060225065749.GC31623@studio.unibo.it>
+Content-Disposition: inline
+
+ZC0301 driver updates.
+
+Changes: + new, - removed, * cleanup, @ bugfix
+
+@ Need usb_get|put_dev() when disconnecting, if the device is open
+* Cleanups and updates in the documentation
++ Use per-device sensor structures
++ Add frame_timeout module parameter
+
+Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/zc0301.txt | 29 +++++++++++------
+ drivers/usb/media/zc0301.h | 20 +++++++++---
+ drivers/usb/media/zc0301_core.c | 58 +++++++++++++++++++++--------------
+ drivers/usb/media/zc0301_pas202bcb.c | 38 +++++++++++++---------
+ drivers/usb/media/zc0301_sensor.h | 25 +++++++++------
+ 5 files changed, 108 insertions(+), 62 deletions(-)
+
+--- gregkh-2.6.orig/Documentation/usb/zc0301.txt
++++ gregkh-2.6/Documentation/usb/zc0301.txt
+@@ -68,11 +68,6 @@ Some of the features of the driver are:
+ data transfers;
+ - automatic detection of image sensor;
+ - video format is standard JPEG;
+-- full support for the capabilities of every possible image sensors that can
+- be connected to the ZC0301 bridges, including, for istance, red, green,
+- blue and global gain adjustments and exposure control (see "Supported
+- devices" paragraph for details);
+-- use of default color settings for sunlight conditions;
+ - dynamic driver control thanks to various module parameters (see "Module
+ parameters" paragraph);
+ - up to 64 cameras can be handled at the same time; they can be connected and
+@@ -171,6 +166,14 @@ Description: Force the application to
+ 1 = force memory unmapping (save memory)
+ Default: 0
+ -------------------------------------------------------------------------------
++Name: frame_timeout
++Type: uint array (min = 0, max = 64)
++Syntax: <n[,...]>
++Description: Timeout for a video frame in seconds. This parameter is
++ specific for each detected camera. This parameter can be
++ changed at runtime thanks to the /sys filesystem interface.
++Default: 2
++-------------------------------------------------------------------------------
+ Name: debug
+ Type: ushort
+ Syntax: <n>
+@@ -198,17 +201,23 @@ devices mounting the ZC0301 Image Proces
+
+ Vendor ID Product ID
+ --------- ----------
++0x10fd 0x8050
++0x041e 0x0417
++0x041e 0x041e
++0x041e 0x081c
++0x041e 0x0834
++0x041e 0x0835
+ 0x046d 0x08ae
++0x0ac8 0x0301
+
+-The following image sensors are supported:
++The list above does not imply that all those devices work with this driver: up
++until now only the ones that mount the following image sensors are supported;
++kernel messages will always tell you whether this is the case:
+
+ Model Manufacturer
+ ----- ------------
+ PAS202BCB PixArt Imaging, Inc.
+
+-All the available control settings of each image sensor are supported through
+-the V4L2 interface.
+-
+
+ 9. Notes for V4L2 application developers
+ ========================================
+@@ -240,6 +249,6 @@ the fingerprint is: '88E8 F32F 7244 68BA
+ - Informations about the chip internals needed to enable the I2C protocol have
+ been taken from the documentation of the ZC030x Video4Linux1 driver written
+ by Andrew Birkett <andy@nobugs.org>;
+-- Initialization values of the ZC0301 controller connected to the PAS202BCB
++- The initialization values of the ZC0301 controller connected to the PAS202BCB
+ image sensor have been taken from the SPCA5XX driver maintained by
+ Michel Xhaard <mxhaard@magic.fr>.
+--- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c
++++ gregkh-2.6/drivers/usb/media/zc0301_core.c
+@@ -29,11 +29,9 @@
+ #include <linux/moduleparam.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+-#include <linux/string.h>
+ #include <linux/device.h>
+ #include <linux/fs.h>
+ #include <linux/delay.h>
+-#include <linux/stddef.h>
+ #include <linux/compiler.h>
+ #include <linux/ioctl.h>
+ #include <linux/poll.h>
+@@ -54,8 +52,8 @@
+ #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia"
+ #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
+ #define ZC0301_MODULE_LICENSE "GPL"
+-#define ZC0301_MODULE_VERSION "1:1.01"
+-#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1)
++#define ZC0301_MODULE_VERSION "1:1.02"
++#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2)
+
+ /*****************************************************************************/
+
+@@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap,
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
+
++static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
++ ZC0301_FRAME_TIMEOUT};
++module_param_array(frame_timeout, uint, NULL, 0644);
++MODULE_PARM_DESC(frame_timeout,
++ "\n<n[,...]> Timeout for a video frame in seconds."
++ "\nThis parameter is specific for each detected camera."
++ "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
++ "\n");
++
+ #ifdef ZC0301_DEBUG
+ static unsigned short debug = ZC0301_DEBUG_LEVEL;
+ module_param(debug, ushort, 0644);
+@@ -115,8 +122,8 @@ static u32
+ zc0301_request_buffers(struct zc0301_device* cam, u32 count,
+ enum zc0301_io_method io)
+ {
+- struct v4l2_pix_format* p = &(cam->sensor->pix_format);
+- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
++ struct v4l2_pix_format* p = &(cam->sensor.pix_format);
++ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
+ const size_t imagesize = cam->module_param.force_munmap ||
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+@@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct u
+ (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
+ frame);
+
+- imagesize = (cam->sensor->pix_format.width *
+- cam->sensor->pix_format.height *
+- cam->sensor->pix_format.priv) / 8;
++ imagesize = (cam->sensor.pix_format.width *
++ cam->sensor.pix_format.height *
++ cam->sensor.pix_format.priv) / 8;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ unsigned int len, status;
+@@ -555,7 +562,7 @@ zc0301_set_compression(struct zc0301_dev
+
+ static int zc0301_init(struct zc0301_device* cam)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ struct v4l2_queryctrl *qctrl;
+ struct v4l2_rect* rect;
+@@ -630,6 +637,7 @@ static void zc0301_release_resources(str
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ video_set_drvdata(cam->v4ldev, NULL);
+ video_unregister_device(cam->v4ldev);
++ usb_put_dev(cam->usbdev);
+ kfree(cam->control_buffer);
+ }
+
+@@ -798,7 +806,8 @@ zc0301_read(struct file* filp, char __us
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+- ZC0301_FRAME_TIMEOUT );
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0) {
+ mutex_unlock(&cam->fileop_mutex);
+ return timeout;
+@@ -1056,7 +1065,7 @@ zc0301_vidioc_s_input(struct zc0301_devi
+ static int
+ zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_queryctrl qc;
+ u8 i;
+
+@@ -1078,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_d
+ static int
+ zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ int err = 0;
+ u8 i;
+@@ -1110,7 +1119,7 @@ exit:
+ static int
+ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_control ctrl;
+ u8 i;
+ int err = 0;
+@@ -1123,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_devic
+
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (ctrl.id == s->qctrl[i].id) {
++ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
++ return -EINVAL;
+ if (ctrl.value < s->qctrl[i].minimum ||
+ ctrl.value > s->qctrl[i].maximum)
+ return -ERANGE;
+@@ -1142,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_devic
+ static int
+ zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
+ {
+- struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
++ struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
+
+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cc->pixelaspect.numerator = 1;
+@@ -1158,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_devi
+ static int
+ zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_crop crop = {
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ };
+@@ -1175,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_devic
+ static int
+ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_crop crop;
+ struct v4l2_rect* rect;
+ struct v4l2_rect* bounds = &(s->cropcap.bounds);
+@@ -1304,7 +1315,7 @@ static int
+ zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
+ {
+ struct v4l2_format format;
+- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
++ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
+
+ if (copy_from_user(&format, arg, sizeof(format)))
+ return -EFAULT;
+@@ -1328,7 +1339,7 @@ static int
+ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
+ void __user * arg)
+ {
+- struct zc0301_sensor* s = cam->sensor;
++ struct zc0301_sensor* s = &cam->sensor;
+ struct v4l2_format format;
+ struct v4l2_pix_format* pix;
+ struct v4l2_pix_format* pfmt = &(s->pix_format);
+@@ -1612,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+- ZC0301_FRAME_TIMEOUT );
++ cam->module_param.frame_timeout *
++ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0)
+ return timeout;
+ if (cam->state & DEV_DISCONNECTED)
+@@ -1911,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* i
+ break;
+ }
+
+- if (!err && cam->sensor)
+- DBG(2, "%s image sensor detected", cam->sensor->name);
++ if (!err)
++ DBG(2, "%s image sensor detected", cam->sensor.name);
+ else {
+ DBG(1, "No supported image sensor detected");
+ err = -ENODEV;
+@@ -1950,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* i
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+
+ cam->module_param.force_munmap = force_munmap[dev_nr];
++ cam->module_param.frame_timeout = frame_timeout[dev_nr];
+
+ dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+@@ -1994,6 +2007,7 @@ static void zc0301_usb_disconnect(struct
+ cam->state |= DEV_DISCONNECTED;
+ wake_up_interruptible(&cam->wait_frame);
+ wake_up(&cam->wait_stream);
++ usb_get_dev(cam->usbdev);
+ } else {
+ cam->state |= DEV_DISCONNECTED;
+ zc0301_release_resources(cam);
+--- gregkh-2.6.orig/drivers/usb/media/zc0301.h
++++ gregkh-2.6/drivers/usb/media/zc0301.h
+@@ -34,7 +34,8 @@
+ #include <linux/param.h>
+ #include <linux/mutex.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/stddef.h>
++#include <linux/string.h>
+
+ #include "zc0301_sensor.h"
+
+@@ -51,7 +52,7 @@
+ #define ZC0301_ALTERNATE_SETTING 7
+ #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
+ #define ZC0301_CTRL_TIMEOUT 100
+-#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
++#define ZC0301_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -94,6 +95,7 @@ enum zc0301_stream_state {
+
+ struct zc0301_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+ static DECLARE_RWSEM(zc0301_disconnect);
+@@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect);
+ struct zc0301_device {
+ struct video_device* v4ldev;
+
+- struct zc0301_sensor* sensor;
++ struct zc0301_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[ZC0301_URBS];
+@@ -129,11 +131,19 @@ struct zc0301_device {
+
+ /*****************************************************************************/
+
++struct zc0301_device*
++zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
+ void
+ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor));
+ }
+
+ /*****************************************************************************/
+--- gregkh-2.6.orig/drivers/usb/media/zc0301_pas202bcb.c
++++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c
+@@ -22,6 +22,14 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
++/*
++ NOTE: Sensor controls are disabled for now, becouse changing them while
++ streaming sometimes results in out-of-sync video frames. We'll use
++ the default initialization, until we know how to stop and start video
++ in the chip. However, the image quality still looks good under various
++ light conditions.
++*/
++
+ #include <linux/delay.h>
+ #include "zc0301_sensor.h"
+
+@@ -245,7 +253,7 @@ static struct zc0301_sensor pas202bcb =
+ .maximum = 0x3fff,
+ .step = 0x0001,
+ .default_value = 0x01e5,
+- .flags = 0,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_GAIN,
+@@ -255,7 +263,17 @@ static struct zc0301_sensor pas202bcb =
+ .maximum = 0x1f,
+ .step = 0x01,
+ .default_value = 0x0c,
+- .flags = 0,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
++ },
++ {
++ .id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "DAC magnitude",
++ .minimum = 0x00,
++ .maximum = 0xff,
++ .step = 0x01,
++ .default_value = 0x00,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+@@ -265,7 +283,7 @@ static struct zc0301_sensor pas202bcb =
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x01,
+- .flags = 0,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+@@ -275,7 +293,7 @@ static struct zc0301_sensor pas202bcb =
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x05,
+- .flags = 0,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = ZC0301_V4L2_CID_GREEN_BALANCE,
+@@ -285,17 +303,7 @@ static struct zc0301_sensor pas202bcb =
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x00,
+- .flags = 0,
+- },
+- {
+- .id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
+- .type = V4L2_CTRL_TYPE_INTEGER,
+- .name = "DAC magnitude",
+- .minimum = 0x00,
+- .maximum = 0xff,
+- .step = 0x01,
+- .default_value = 0x04,
+- .flags = 0,
++ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ },
+ .get_ctrl = &pas202bcb_get_ctrl,
+--- gregkh-2.6.orig/drivers/usb/media/zc0301_sensor.h
++++ gregkh-2.6/drivers/usb/media/zc0301_sensor.h
+@@ -43,9 +43,11 @@ static int (*zc0301_sensor_table[])(stru
+ NULL, \
+ };
+
++extern struct zc0301_device*
++zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id);
++
+ extern void
+-zc0301_attach_sensor(struct zc0301_device* cam,
+- struct zc0301_sensor* sensor);
++zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
+
+ #define ZC0301_USB_DEVICE(vend, prod, intclass) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+@@ -56,7 +58,14 @@ zc0301_attach_sensor(struct zc0301_devic
+
+ #define ZC0301_ID_TABLE \
+ static const struct usb_device_id zc0301_id_table[] = { \
++ { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \
++ { ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \
++ { ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \
++ { ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \
++ { ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \
++ { ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \
+ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \
++ { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \
+ { } \
+ };
+
+@@ -80,15 +89,11 @@ struct zc0301_sensor {
+ struct v4l2_cropcap cropcap;
+ struct v4l2_pix_format pix_format;
+
+- int (*init)(struct zc0301_device* cam);
+- int (*get_ctrl)(struct zc0301_device* cam,
+- struct v4l2_control* ctrl);
+- int (*set_ctrl)(struct zc0301_device* cam,
++ int (*init)(struct zc0301_device*);
++ int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl);
++ int (*set_ctrl)(struct zc0301_device*,
+ const struct v4l2_control* ctrl);
+- int (*set_crop)(struct zc0301_device* cam,
+- const struct v4l2_rect* rect);
+-
+- const struct usb_device* usbdev;
++ int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect);
+
+ /* Private */
+ struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS];