linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / usb / media / sn9c102_core.c
similarity index 84%
rename from drivers/media/video/sn9c102/sn9c102_core.c
rename to drivers/usb/media/sn9c102_core.c
index ea4394d..c81397e 100644 (file)
 #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>
@@ -47,8 +49,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.27"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 27)
+#define SN9C102_MODULE_VERSION  "1:1.26"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 26)
 
 /*****************************************************************************/
 
@@ -62,53 +64,44 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE);
 static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
 module_param_array(video_nr, short, NULL, 0444);
 MODULE_PARM_DESC(video_nr,
-                "\n<-1|n[,...]> Specify V4L2 minor mode number."
-                "\n -1 = use next available (default)"
-                "\n  n = use minor number n (integer >= 0)"
-                "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
-                " cameras this way."
-                "\nFor example:"
-                "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
-                "\nthe second camera and use auto for the first"
-                "\none and for every other camera."
-                "\n");
-
-static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
-                              SN9C102_FORCE_MUNMAP};
+                 "\n<-1|n[,...]> Specify V4L2 minor mode number."
+                 "\n -1 = use next available (default)"
+                 "\n  n = use minor number n (integer >= 0)"
+                 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
+                 " cameras this way."
+                 "\nFor example:"
+                 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+                 "\nthe second camera and use auto for the first"
+                 "\none and for every other camera."
+                 "\n");
+
+static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = 
+                               SN9C102_FORCE_MUNMAP};
 module_param_array(force_munmap, bool, NULL, 0444);
 MODULE_PARM_DESC(force_munmap,
-                "\n<0|1[,...]> Force the application to unmap previously"
-                "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
-                "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
-                "\nthis feature. This parameter is specific for each"
-                "\ndetected camera."
-                "\n 0 = do not force memory unmapping"
-                "\n 1 = force memory unmapping (save memory)"
-                "\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");
+                 "\n<0|1[,...]> Force the application to unmap previously"
+                 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+                 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+                 "\nthis feature. This parameter is specific for each"
+                 "\ndetected camera."
+                 "\n 0 = do not force memory unmapping"
+                 "\n 1 = force memory unmapping (save memory)"
+                 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+                 "\n");
 
 #ifdef SN9C102_DEBUG
 static unsigned short debug = SN9C102_DEBUG_LEVEL;
 module_param(debug, ushort, 0644);
 MODULE_PARM_DESC(debug,
-                "\n<n> Debugging information level, from 0 to 3:"
-                "\n0 = none (use carefully)"
-                "\n1 = critical errors"
-                "\n2 = significant informations"
-                "\n3 = more verbose messages"
-                "\nLevel 3 is useful for testing only, when only "
-                "one device is used."
-                "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
-                "\n");
+                 "\n<n> Debugging information level, from 0 to 3:"
+                 "\n0 = none (use carefully)"
+                 "\n1 = critical errors"
+                 "\n2 = significant informations"
+                 "\n3 = more verbose messages"
+                 "\nLevel 3 is useful for testing only, when only "
+                 "one device is used."
+                 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
+                 "\n");
 #endif
 
 /*****************************************************************************/
@@ -131,16 +124,16 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = {
 
 /*****************************************************************************/
 
-static u32
-sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
-                       enum sn9c102_io_method io)
+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 :
-                                (r->width * r->height * p->priv) / 8;
+                                io == IO_READ ?
+                                (p->width * p->height * p->priv) / 8 :
+                                (r->width * r->height * p->priv) / 8;
        void* buff = NULL;
        u32 i;
 
@@ -232,8 +225,8 @@ int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
                return -1;
 
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             index, 0, buff, sizeof(buff),
-                             SN9C102_CTRL_TIMEOUT*sizeof(buff));
+                             index, 0, buff, sizeof(buff),
+                             SN9C102_CTRL_TIMEOUT*sizeof(buff));
        if (res < 0) {
                DBG(3, "Failed to write registers (index 0x%02X, error %d)",
                    index, res);
@@ -259,7 +252,7 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
        *buff = value;
 
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
        if (res < 0) {
                DBG(3, "Failed to write a register (value 0x%02X, index "
                       "0x%02X, error %d)", value, index, res);
@@ -280,7 +273,7 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
        int res;
 
        res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
                DBG(3, "Failed to read a register (index 0x%02X, error %d)",
                    index, res);
@@ -319,8 +312,8 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
 
 
 static int
-sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
-                             struct sn9c102_sensor* sensor)
+sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, 
+                              struct sn9c102_sensor* sensor)
 {
        int r;
        r = sn9c102_read_reg(cam, 0x08);
@@ -329,8 +322,8 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
 
 
 static int
-sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
-                              struct sn9c102_sensor* sensor)
+sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, 
+                               struct sn9c102_sensor* sensor)
 {
        int r;
        r = sn9c102_read_reg(cam, 0x08);
@@ -338,10 +331,10 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
 }
 
 
-int
+int 
 sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
-                        struct sn9c102_sensor* sensor, u8 data0, u8 data1,
-                        u8 n, u8 buffer[])
+                         struct sn9c102_sensor* sensor, u8 data0, u8 data1,
+                         u8 n, u8 buffer[])
 {
        struct usb_device* udev = cam->usbdev;
        u8* data = cam->control_buffer;
@@ -349,12 +342,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 
        /* Write cycle */
        data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
        data[1] = data0; /* I2C slave id */
        data[2] = data1; /* address */
        data[7] = 0x10;
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
                err += res;
 
@@ -362,12 +355,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 
        /* Read cycle - n bytes */
        data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
-                 (n << 4) | 0x02;
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
+                 (n << 4) | 0x02;
        data[1] = data0;
        data[7] = 0x10;
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
                err += res;
 
@@ -375,7 +368,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 
        /* The first read byte will be placed in data[4] */
        res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-                             0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
+                             0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
                err += res;
 
@@ -396,10 +389,10 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 }
 
 
-int
+int 
 sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
-                         struct sn9c102_sensor* sensor, u8 n, u8 data0,
-                         u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
+                          struct sn9c102_sensor* sensor, u8 n, u8 data0,
+                          u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
 {
        struct usb_device* udev = cam->usbdev;
        u8* data = cam->control_buffer;
@@ -407,8 +400,8 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
 
        /* Write cycle. It usually is address + value */
        data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
-                 | ((n - 1) << 4);
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
+                 | ((n - 1) << 4);
        data[1] = data0;
        data[2] = data1;
        data[3] = data2;
@@ -417,7 +410,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
        data[6] = data5;
        data[7] = 0x14;
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
                err += res;
 
@@ -437,32 +430,38 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
 
 int
 sn9c102_i2c_try_read(struct sn9c102_device* cam,
-                    struct sn9c102_sensor* sensor, u8 address)
+                     struct sn9c102_sensor* sensor, u8 address)
 {
        return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
-                                       address, 1, NULL);
+                                       address, 1, NULL);
 }
 
 
 int
 sn9c102_i2c_try_write(struct sn9c102_device* cam,
-                     struct sn9c102_sensor* sensor, u8 address, u8 value)
+                      struct sn9c102_sensor* sensor, u8 address, u8 value)
 {
-       return sn9c102_i2c_try_raw_write(cam, sensor, 3,
-                                        sensor->i2c_slave_id, address,
-                                        value, 0, 0, 0);
+       return sn9c102_i2c_try_raw_write(cam, sensor, 3, 
+                                        sensor->i2c_slave_id, address,
+                                        value, 0, 0, 0);
 }
 
 
 int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
 {
-       return sn9c102_i2c_try_read(cam, &cam->sensor, address);
+       if (!cam->sensor)
+               return -1;
+
+       return sn9c102_i2c_try_read(cam, cam->sensor, address);
 }
 
 
 int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
 {
-       return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
+       if (!cam->sensor)
+               return -1;
+
+       return sn9c102_i2c_try_write(cam, cam->sensor, address, value);
 }
 
 /*****************************************************************************/
@@ -484,7 +483,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
                n = sizeof(sn9c103_sof_header) / soflen;
        }
 
-       for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
+       for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
                for (j = 0; j < n; j++)
                        /* The invariable part of the header is 6 bytes long */
                        if ((cam->bridge != BRIDGE_SN9C103 &&
@@ -506,7 +505,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
        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++)
@@ -536,7 +535,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
                if ((*f))
                        (*f)->state = F_QUEUED;
                DBG(3, "Stream interrupted");
-               wake_up(&cam->wait_stream);
+               wake_up_interruptible(&cam->wait_stream);
        }
 
        if (cam->state & DEV_DISCONNECTED)
@@ -552,15 +551,15 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
 
        if (!(*f))
                (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
-                                 frame);
+                                 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) :
-                                 sizeof(sn9c102_sof_header_t);
+                                 sizeof(sn9c103_sof_header_t) :
+                                 sizeof(sn9c102_sof_header_t);
 
        for (i = 0; i < urb->number_of_packets; i++) {
                unsigned int img, len, status;
@@ -580,7 +579,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
 
 redo:
                sof = sn9c102_find_sof_header(cam, pos, len);
-               if (likely(!sof)) {
+               if (!sof) {
                        eof = sn9c102_find_eof_header(cam, pos, len);
                        if ((*f)->state == F_GRABBING) {
 end_of_frame:
@@ -590,9 +589,8 @@ end_of_frame:
                                        img = (eof > pos) ? eof - pos - 1 : 0;
 
                                if ((*f)->buf.bytesused+img > imagesize) {
-                                       u32 b;
-                                       b = (*f)->buf.bytesused + img -
-                                           imagesize;
+                                       u32 b = (*f)->buf.bytesused + img -
+                                               imagesize;
                                        img = imagesize - (*f)->buf.bytesused;
                                        DBG(3, "Expected EOF not found: "
                                               "video frame cut");
@@ -610,20 +608,19 @@ end_of_frame:
                                (*f)->buf.bytesused += img;
 
                                if ((*f)->buf.bytesused == imagesize ||
-                                   (cam->sensor.pix_format.pixelformat ==
-                                               V4L2_PIX_FMT_SN9C10X && eof)) {
-                                       u32 b;
-                                       b = (*f)->buf.bytesused;
+                                   (cam->sensor->pix_format.pixelformat ==
+                                               V4L2_PIX_FMT_SN9C10X && eof)) {
+                                       u32 b = (*f)->buf.bytesused;
                                        (*f)->state = F_DONE;
                                        (*f)->buf.sequence= ++cam->frame_count;
                                        spin_lock(&cam->queue_lock);
                                        list_move_tail(&(*f)->frame,
-                                                      &cam->outqueue);
+                                                      &cam->outqueue);
                                        if (!list_empty(&cam->inqueue))
                                                (*f) = list_entry(
-                                                       cam->inqueue.next,
-                                                       struct sn9c102_frame_t,
-                                                       frame );
+                                                       cam->inqueue.next,
+                                                       struct sn9c102_frame_t,
+                                                       frame );
                                        else
                                                (*f) = NULL;
                                        spin_unlock(&cam->queue_lock);
@@ -638,7 +635,7 @@ end_of_frame:
                                } else if (eof) {
                                        (*f)->state = F_ERROR;
                                        DBG(3, "Not expected EOF after %lu "
-                                              "bytes of image data",
+                                              "bytes of image data", 
                                            (unsigned long)
                                            ((*f)->buf.bytesused));
                                }
@@ -670,13 +667,13 @@ 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;
                                } else {
                                        DBG(3, "SOF before expected EOF after "
-                                              "%lu bytes of image data",
+                                              "%lu bytes of image data", 
                                            (unsigned long)
                                            ((*f)->buf.bytesused));
                                        goto start_of_frame;
@@ -702,18 +699,18 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
        struct usb_device *udev = cam->usbdev;
        struct urb* urb;
        const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-                                                      680, 800, 900, 1023};
+                                                      680, 800, 900, 1023};
        const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
-                                                      680, 800, 900, 1003};
+                                                      680, 800, 900, 1003};
        const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
-                           sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
-                           sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+                           sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
+                           sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
        s8 i, j;
        int err = 0;
 
        for (i = 0; i < SN9C102_URBS; i++) {
                cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
-                                                 GFP_KERNEL);
+                                                 GFP_KERNEL);
                if (!cam->transfer_buffer[i]) {
                        err = -ENOMEM;
                        DBG(1, "Not enough memory");
@@ -811,21 +808,20 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam)
 
 static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
 {
-       long timeout;
+       int err = 0;
 
        cam->stream = STREAM_INTERRUPT;
-       timeout = wait_event_timeout(cam->wait_stream,
-                                    (cam->stream == STREAM_OFF) ||
-                                    (cam->state & DEV_DISCONNECTED),
-                                    SN9C102_URB_TIMEOUT);
+       err = 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 (cam->stream != STREAM_OFF) {
+       else if (err) {
                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 -EIO;
+               DBG(1, "The camera is misconfigured. To use it, close and "
+                      "open /dev/video%d again.", cam->v4ldev->minor);
+               return err;
        }
 
        return 0;
@@ -861,7 +857,7 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
 
 /*
    NOTE 1: being inside one of the following methods implies that the v4l
-          device exists for sure (see kobjects and reference counters)
+           device exists for sure (see kobjects and reference counters)
    NOTE 2: buffers are PAGE_SIZE long
 */
 
@@ -870,42 +866,42 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
        struct sn9c102_device* cam;
        ssize_t count;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        count = sprintf(buf, "%u\n", cam->sysfs.reg);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
-}
+} 
 
 
-static ssize_t
+static ssize_t 
 sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
        u8 index;
        ssize_t count;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        index = sn9c102_strtou8(buf, len, &count);
        if (index > 0x1f || !count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EINVAL;
        }
 
@@ -914,7 +910,7 @@ sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
        DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
        DBG(3, "Written bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
 }
@@ -926,17 +922,17 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
        ssize_t count;
        int val;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EIO;
        }
 
@@ -944,10 +940,10 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
 
        DBG(3, "Read bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
-}
+} 
 
 
 static ssize_t
@@ -958,24 +954,24 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
        ssize_t count;
        int err;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        value = sn9c102_strtou8(buf, len, &count);
        if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EINVAL;
        }
 
        err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
        if (err) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EIO;
        }
 
@@ -983,7 +979,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
            cam->sysfs.reg, value);
        DBG(3, "Written bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
 }
@@ -994,12 +990,12 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
        struct sn9c102_device* cam;
        ssize_t count;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
@@ -1007,31 +1003,31 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
 
        DBG(3, "Read bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
 }
 
 
-static ssize_t
+static ssize_t 
 sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
 {
        struct sn9c102_device* cam;
        u8 index;
        ssize_t count;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        index = sn9c102_strtou8(buf, len, &count);
        if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EINVAL;
        }
 
@@ -1040,7 +1036,7 @@ sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
        DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
        DBG(3, "Written bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
 }
@@ -1052,22 +1048,22 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
        ssize_t count;
        int val;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
-       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+       if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) {
+               up(&sn9c102_sysfs_lock);
                return -ENOSYS;
        }
 
        if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EIO;
        }
 
@@ -1075,10 +1071,10 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
 
        DBG(3, "Read bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
-}
+} 
 
 
 static ssize_t
@@ -1089,29 +1085,29 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
        ssize_t count;
        int err;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
-       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+       if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) {
+               up(&sn9c102_sysfs_lock);
                return -ENOSYS;
        }
 
        value = sn9c102_strtou8(buf, len, &count);
        if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EINVAL;
        }
 
        err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
        if (err) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -EIO;
        }
 
@@ -1119,7 +1115,7 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
            cam->sysfs.i2c_reg, value);
        DBG(3, "Written bytes: %zd", count);
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        return count;
 }
@@ -1134,18 +1130,18 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
        u8 value;
        ssize_t count;
 
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+       if (down_interruptible(&sn9c102_sysfs_lock))
                return -ERESTARTSYS;
 
        cam = video_get_drvdata(to_video_device(cd));
        if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
+               up(&sn9c102_sysfs_lock);
                return -ENODEV;
        }
 
        bridge = cam->bridge;
 
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        value = sn9c102_strtou8(buf, len, &count);
        if (!count)
@@ -1222,22 +1218,22 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
        DBG(3, "Frame header, read bytes: %zd", count);
 
        return count;
-}
+} 
 
 
 static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
-                        sn9c102_show_reg, sn9c102_store_reg);
+                         sn9c102_show_reg, sn9c102_store_reg);
 static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
-                        sn9c102_show_val, sn9c102_store_val);
+                         sn9c102_show_val, sn9c102_store_val);
 static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
-                        sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
+                         sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
-                        sn9c102_show_i2c_val, sn9c102_store_i2c_val);
+                         sn9c102_show_i2c_val, sn9c102_store_i2c_val);
 static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
 static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
 static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
 static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
-                        sn9c102_show_frame_header, NULL);
+                         sn9c102_show_frame_header, NULL);
 
 
 static void sn9c102_create_sysfs(struct sn9c102_device* cam)
@@ -1253,7 +1249,7 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
                video_device_create_file(v4ldev, &class_device_attr_blue);
                video_device_create_file(v4ldev, &class_device_attr_red);
        }
-       if (cam->sensor.sysfs_ops) {
+       if (cam->sensor && cam->sensor->sysfs_ops) {
                video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
                video_device_create_file(v4ldev, &class_device_attr_i2c_val);
        }
@@ -1278,7 +1274,7 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
 
 static int
 sn9c102_set_compression(struct sn9c102_device* cam,
-                       struct v4l2_jpegcompression* compression)
+                        struct v4l2_jpegcompression* compression)
 {
        int err = 0;
 
@@ -1316,7 +1312,7 @@ static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
 
 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),
@@ -1339,7 +1335,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
 
 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;
@@ -1408,7 +1404,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
        }
 
        if (!(cam->state & DEV_INITIALIZED)) {
-               mutex_init(&cam->fileop_mutex);
+               init_MUTEX(&cam->fileop_sem);
                spin_lock_init(&cam->queue_lock);
                init_waitqueue_head(&cam->wait_frame);
                init_waitqueue_head(&cam->wait_stream);
@@ -1426,15 +1422,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
 
 static void sn9c102_release_resources(struct sn9c102_device* cam)
 {
-       mutex_lock(&sn9c102_sysfs_lock);
+       down(&sn9c102_sysfs_lock);
 
        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);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
+       up(&sn9c102_sysfs_lock);
 
        kfree(cam->control_buffer);
 }
@@ -1455,7 +1449,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
 
        cam = video_get_drvdata(video_devdata(filp));
 
-       if (mutex_lock_interruptible(&cam->dev_mutex)) {
+       if (down_interruptible(&cam->dev_sem)) {
                up_read(&sn9c102_disconnect);
                return -ERESTARTSYS;
        }
@@ -1467,10 +1461,10 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
                        err = -EWOULDBLOCK;
                        goto out;
                }
-               mutex_unlock(&cam->dev_mutex);
+               up(&cam->dev_sem);
                err = wait_event_interruptible_exclusive(cam->open,
-                                                 cam->state & DEV_DISCONNECTED
-                                                        || !cam->users);
+                                                 cam->state & DEV_DISCONNECTED
+                                                        || !cam->users);
                if (err) {
                        up_read(&sn9c102_disconnect);
                        return err;
@@ -1479,7 +1473,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
                        up_read(&sn9c102_disconnect);
                        return -ENODEV;
                }
-               mutex_lock(&cam->dev_mutex);
+               down(&cam->dev_sem);
        }
 
 
@@ -1507,7 +1501,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
        DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
 
 out:
-       mutex_unlock(&cam->dev_mutex);
+       up(&cam->dev_sem);
        up_read(&sn9c102_disconnect);
        return err;
 }
@@ -1517,7 +1511,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 {
        struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
 
-       mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
+       down(&cam->dev_sem); /* prevent disconnect() to be called */
 
        sn9c102_stop_transfer(cam);
 
@@ -1525,7 +1519,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 
        if (cam->state & DEV_DISCONNECTED) {
                sn9c102_release_resources(cam);
-               mutex_unlock(&cam->dev_mutex);
+               up(&cam->dev_sem);
                kfree(cam);
                return 0;
        }
@@ -1535,7 +1529,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 
        DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
 
-       mutex_unlock(&cam->dev_mutex);
+       up(&cam->dev_sem);
 
        return 0;
 }
@@ -1547,36 +1541,35 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
        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))
+       if (down_interruptible(&cam->fileop_sem))
                return -ERESTARTSYS;
 
        if (cam->state & DEV_DISCONNECTED) {
                DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -ENODEV;
        }
 
        if (cam->state & DEV_MISCONFIGURED) {
                DBG(1, "The camera is misconfigured. Close and open it "
                       "again.");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EIO;
        }
 
        if (cam->io == IO_MMAP) {
                DBG(3, "Close and open the device again to choose "
                       "the read method");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EINVAL;
        }
 
        if (cam->io == IO_NONE) {
                if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
                        DBG(1, "read() failed, not enough memory");
-                       mutex_unlock(&cam->fileop_mutex);
+                       up(&cam->fileop_sem);
                        return -ENOMEM;
                }
                cam->io = IO_READ;
@@ -1590,32 +1583,30 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
        }
 
        if (!count) {
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return 0;
        }
 
        if (list_empty(&cam->outqueue)) {
                if (filp->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&cam->fileop_mutex);
+                       up(&cam->fileop_sem);
                        return -EAGAIN;
                }
-               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;
+               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;
                }
                if (cam->state & DEV_DISCONNECTED) {
-                       mutex_unlock(&cam->fileop_mutex);
+                       up(&cam->fileop_sem);
                        return -ENODEV;
                }
-               if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
-                       mutex_unlock(&cam->fileop_mutex);
+               if (cam->state & DEV_MISCONFIGURED) {
+                       up(&cam->fileop_sem);
                        return -EIO;
                }
        }
@@ -1643,7 +1634,7 @@ exit:
        PDBGG("Frame #%lu, bytes read: %zu",
              (unsigned long)f->buf.index, count);
 
-       mutex_unlock(&cam->fileop_mutex);
+       up(&cam->fileop_sem);
 
        return count;
 }
@@ -1656,7 +1647,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
        unsigned long lock_flags;
        unsigned int mask = 0;
 
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
+       if (down_interruptible(&cam->fileop_sem))
                return POLLERR;
 
        if (cam->state & DEV_DISCONNECTED) {
@@ -1672,7 +1663,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
 
        if (cam->io == IO_NONE) {
                if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
-                                            IO_READ)) {
+                                            IO_READ)) {
                        DBG(1, "poll() failed, not enough memory");
                        goto error;
                }
@@ -1694,12 +1685,12 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
        if (!list_empty(&cam->outqueue))
                mask |= POLLIN | POLLRDNORM;
 
-       mutex_unlock(&cam->fileop_mutex);
+       up(&cam->fileop_sem);
 
        return mask;
 
 error:
-       mutex_unlock(&cam->fileop_mutex);
+       up(&cam->fileop_sem);
        return POLLERR;
 }
 
@@ -1729,29 +1720,29 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
 {
        struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
        unsigned long size = vma->vm_end - vma->vm_start,
-                     start = vma->vm_start;
+                     start = vma->vm_start;
        void *pos;
        u32 i;
 
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
+       if (down_interruptible(&cam->fileop_sem))
                return -ERESTARTSYS;
 
        if (cam->state & DEV_DISCONNECTED) {
                DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -ENODEV;
        }
 
        if (cam->state & DEV_MISCONFIGURED) {
                DBG(1, "The camera is misconfigured. Close and open it "
                       "again.");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EIO;
        }
 
        if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
            size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EINVAL;
        }
 
@@ -1760,7 +1751,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
                        break;
        }
        if (i == cam->nbuffers) {
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EINVAL;
        }
 
@@ -1770,7 +1761,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
        pos = cam->frame[i].bufmem;
        while (size > 0) { /* size is page-aligned */
                if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-                       mutex_unlock(&cam->fileop_mutex);
+                       up(&cam->fileop_sem);
                        return -EAGAIN;
                }
                start += PAGE_SIZE;
@@ -1783,7 +1774,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
 
        sn9c102_vm_open(vma);
 
-       mutex_unlock(&cam->fileop_mutex);
+       up(&cam->fileop_sem);
 
        return 0;
 }
@@ -1797,13 +1788,13 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
                .driver = "sn9c102",
                .version = SN9C102_MODULE_VERSION_CODE,
                .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-                               V4L2_CAP_STREAMING,
+                               V4L2_CAP_STREAMING,
        };
 
        strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
        if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
                strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
-                       sizeof(cap.bus_info));
+                       sizeof(cap.bus_info));
 
        if (copy_to_user(arg, &cap, sizeof(cap)))
                return -EFAULT;
@@ -1825,7 +1816,6 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
 
        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;
@@ -1835,19 +1825,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
 
 
 static int
-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)
+sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg)
 {
        int index;
 
@@ -1864,7 +1842,7 @@ sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
 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;
 
@@ -1886,7 +1864,7 @@ sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
 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;
@@ -1918,7 +1896,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;
@@ -1931,8 +1909,6 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
 
        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;
@@ -1955,7 +1931,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
 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;
@@ -1971,7 +1947,7 @@ sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
 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,
        };
@@ -1988,7 +1964,7 @@ sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
 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);
@@ -2129,7 +2105,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;
@@ -2138,7 +2114,7 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
                return -EINVAL;
 
        pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
-                            ? 0 : (pfmt->width * pfmt->priv) / 8;
+                            ? 0 : (pfmt->width * pfmt->priv) / 8;
        pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
        pfmt->field = V4L2_FIELD_NONE;
        memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
@@ -2152,9 +2128,9 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
 
 static int
 sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
-                        void __user * arg)
+                         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);
@@ -2214,7 +2190,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
        pix->priv = pfmt->priv; /* bpp */
        pix->colorspace = pfmt->colorspace;
        pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-                           ? 0 : (pix->width * pix->priv) / 8;
+                           ? 0 : (pix->width * pix->priv) / 8;
        pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
        pix->field = V4L2_FIELD_NONE;
 
@@ -2287,7 +2263,7 @@ static int
 sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
 {
        if (copy_to_user(arg, &cam->compression,
-                        sizeof(cam->compression)))
+                        sizeof(cam->compression)))
                return -EFAULT;
 
        return 0;
@@ -2436,12 +2412,12 @@ sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
 
 static int
 sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
-                    void __user * arg)
+                     void __user * arg)
 {
        struct v4l2_buffer b;
        struct sn9c102_frame_t *f;
        unsigned long lock_flags;
-       long timeout;
+       int err = 0;
 
        if (copy_from_user(&b, arg, sizeof(b)))
                return -EFAULT;
@@ -2454,18 +2430,16 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
                        return -EINVAL;
                if (filp->f_flags & O_NONBLOCK)
                        return -EAGAIN;
-               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;
+               err = wait_event_interruptible
+                     ( cam->wait_frame,
+                       (!list_empty(&cam->outqueue)) ||
+                       (cam->state & DEV_DISCONNECTED) ||
+                       (cam->state & DEV_MISCONFIGURED) );
+               if (err)
+                       return err;
                if (cam->state & DEV_DISCONNECTED)
                        return -ENODEV;
-               if (!timeout || (cam->state & DEV_MISCONFIGURED))
+               if (cam->state & DEV_MISCONFIGURED)
                        return -EIO;
        }
 
@@ -2584,7 +2558,7 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
 
 
 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
-                             unsigned int cmd, void __user * arg)
+                              unsigned int cmd, void __user * arg)
 {
        struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
 
@@ -2597,10 +2571,8 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
                return sn9c102_vidioc_enuminput(cam, arg);
 
        case VIDIOC_G_INPUT:
-               return sn9c102_vidioc_g_input(cam, arg);
-
        case VIDIOC_S_INPUT:
-               return sn9c102_vidioc_s_input(cam, arg);
+               return sn9c102_vidioc_gs_input(cam, arg);
 
        case VIDIOC_QUERYCTRL:
                return sn9c102_vidioc_query_ctrl(cam, arg);
@@ -2678,24 +2650,24 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 
 
 static int sn9c102_ioctl(struct inode* inode, struct file* filp,
-                        unsigned int cmd, unsigned long arg)
+                         unsigned int cmd, unsigned long arg)
 {
        struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
        int err = 0;
 
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
+       if (down_interruptible(&cam->fileop_sem))
                return -ERESTARTSYS;
 
        if (cam->state & DEV_DISCONNECTED) {
                DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -ENODEV;
        }
 
        if (cam->state & DEV_MISCONFIGURED) {
                DBG(1, "The camera is misconfigured. Close and open it "
                       "again.");
-               mutex_unlock(&cam->fileop_mutex);
+               up(&cam->fileop_sem);
                return -EIO;
        }
 
@@ -2703,7 +2675,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
 
        err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
 
-       mutex_unlock(&cam->fileop_mutex);
+       up(&cam->fileop_sem);
 
        return err;
 }
@@ -2750,7 +2722,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                goto fail;
        }
 
-       mutex_init(&cam->dev_mutex);
+       init_MUTEX(&cam->dev_sem);
 
        r = sn9c102_read_reg(cam, 0x00);
        if (r < 0 || r != 0x10) {
@@ -2761,7 +2733,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        }
 
        cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
-                     BRIDGE_SN9C103 : BRIDGE_SN9C102;
+                     BRIDGE_SN9C103 : BRIDGE_SN9C102;
        switch (cam->bridge) {
        case BRIDGE_SN9C101:
        case BRIDGE_SN9C102:
@@ -2780,10 +2752,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                        break;
        }
 
-       if (!err) {
-               DBG(2, "%s image sensor detected", cam->sensor.name);
+       if (!err && cam->sensor) {
+               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;
@@ -2804,24 +2776,23 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        cam->v4ldev->release = video_device_release;
        video_set_drvdata(cam->v4ldev, cam);
 
-       mutex_lock(&cam->dev_mutex);
+       down(&cam->dev_sem);
 
        err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
-                                   video_nr[dev_nr]);
+                                   video_nr[dev_nr]);
        if (err) {
                DBG(1, "V4L2 device registration failed");
                if (err == -ENFILE && video_nr[dev_nr] == -1)
                        DBG(1, "Free /dev/videoX node not found");
                video_nr[dev_nr] = -1;
                dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-               mutex_unlock(&cam->dev_mutex);
+               up(&cam->dev_sem);
                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 < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
@@ -2832,7 +2803,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
        usb_set_intfdata(intf, cam);
 
-       mutex_unlock(&cam->dev_mutex);
+       up(&cam->dev_sem);
 
        return 0;
 
@@ -2856,7 +2827,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
 
        down_write(&sn9c102_disconnect);
 
-       mutex_lock(&cam->dev_mutex);
+       down(&cam->dev_sem); 
 
        DBG(2, "Disconnecting %s...", cam->v4ldev->name);
 
@@ -2870,14 +2841,13 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
                sn9c102_stop_transfer(cam);
                cam->state |= DEV_DISCONNECTED;
                wake_up_interruptible(&cam->wait_frame);
-               wake_up(&cam->wait_stream);
-               usb_get_dev(cam->usbdev);
+               wake_up_interruptible(&cam->wait_stream);
        } else {
                cam->state |= DEV_DISCONNECTED;
                sn9c102_release_resources(cam);
        }
 
-       mutex_unlock(&cam->dev_mutex);
+       up(&cam->dev_sem);
 
        if (!cam->users)
                kfree(cam);