X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fsn9c102%2Fsn9c102_core.c;fp=drivers%2Fusb%2Fmedia%2Fsn9c102_core.c;h=18458d46c0ffde99ddd64c7a25bd0531d653bb18;hb=a2f44b27303a5353859d77a3e96a1d3f33f56ab7;hp=c81397e4714ba42791c11dc9642e1b9634106dea;hpb=134734d875a0a48d994ef20b9905209b4b8b6f75;p=linux-2.6.git diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c similarity index 82% rename from drivers/usb/media/sn9c102_core.c rename to drivers/media/video/sn9c102/sn9c102_core.c index c81397e47..18458d46c 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -25,11 +25,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -49,8 +47,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "" #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) /*****************************************************************************/ @@ -64,44 +62,53 @@ 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"); + "\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 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); MODULE_PARM_DESC(debug, - "\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 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 /*****************************************************************************/ @@ -124,16 +131,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; @@ -225,8 +232,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); @@ -252,7 +259,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); @@ -273,7 +280,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); @@ -312,8 +319,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); @@ -322,8 +329,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); @@ -331,10 +338,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; @@ -342,12 +349,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; @@ -355,12 +362,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; @@ -368,7 +375,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; @@ -389,10 +396,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; @@ -400,8 +407,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; @@ -410,7 +417,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; @@ -430,38 +437,32 @@ 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) { - 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); } /*****************************************************************************/ @@ -483,7 +484,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 && @@ -505,7 +506,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++) @@ -517,7 +518,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) } -static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) +static void sn9c102_urb_complete(struct urb *urb) { struct sn9c102_device* cam = urb->context; struct sn9c102_frame_t** f; @@ -535,7 +536,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_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); } if (cam->state & DEV_DISCONNECTED) @@ -551,15 +552,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; @@ -579,7 +580,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) 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,19 +610,20 @@ end_of_frame: (*f)->buf.bytesused += img; if ((*f)->buf.bytesused == imagesize || - (cam->sensor->pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X && eof)) { - u32 b = (*f)->buf.bytesused; + (cam->sensor.pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X && eof)) { + u32 b; + 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); @@ -635,7 +638,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)); } @@ -667,13 +670,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; @@ -699,18 +702,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"); @@ -772,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) return 0; free_urbs: - for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) + for (i = 0; i < SN9C102_URBS; i++) usb_free_urb(cam->urb[i]); free_buffers: @@ -808,20 +811,21 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam) 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; @@ -857,7 +861,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 */ @@ -866,42 +870,42 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) struct sn9c102_device* cam; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.reg); - up(&sn9c102_sysfs_lock); + mutex_unlock(&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 (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou8(buf, len, &count); if (index > 0x1f || !count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } @@ -910,7 +914,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); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -922,17 +926,17 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -940,10 +944,10 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; -} +} static ssize_t @@ -954,24 +958,24 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } value = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_write_reg(cam, value, cam->sysfs.reg); if (err) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -979,7 +983,7 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) cam->sysfs.reg, value); DBG(3, "Written bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -990,12 +994,12 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) struct sn9c102_device* cam; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } @@ -1003,31 +1007,31 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&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 (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } @@ -1036,7 +1040,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); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1048,22 +1052,22 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) ssize_t count; int val; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { - up(&sn9c102_sysfs_lock); + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { + mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -1071,10 +1075,10 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) DBG(3, "Read bytes: %zd", count); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; -} +} static ssize_t @@ -1085,29 +1089,29 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) ssize_t count; int err; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { - up(&sn9c102_sysfs_lock); + if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { + mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } value = sn9c102_strtou8(buf, len, &count); if (!count) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); if (err) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } @@ -1115,7 +1119,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); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return count; } @@ -1130,18 +1134,18 @@ sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) u8 value; ssize_t count; - if (down_interruptible(&sn9c102_sysfs_lock)) + if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } bridge = cam->bridge; - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); value = sn9c102_strtou8(buf, len, &count); if (!count) @@ -1218,41 +1222,71 @@ 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) +static int sn9c102_create_sysfs(struct sn9c102_device* cam) { struct video_device *v4ldev = cam->v4ldev; + int rc; - video_device_create_file(v4ldev, &class_device_attr_reg); - video_device_create_file(v4ldev, &class_device_attr_val); - video_device_create_file(v4ldev, &class_device_attr_frame_header); - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - video_device_create_file(v4ldev, &class_device_attr_green); - else if (cam->bridge == BRIDGE_SN9C103) { - video_device_create_file(v4ldev, &class_device_attr_blue); - video_device_create_file(v4ldev, &class_device_attr_red); + rc = video_device_create_file(v4ldev, &class_device_attr_reg); + if (rc) goto err; + rc = video_device_create_file(v4ldev, &class_device_attr_val); + if (rc) goto err_reg; + rc = video_device_create_file(v4ldev, &class_device_attr_frame_header); + if (rc) goto err_val; + + if (cam->sensor.sysfs_ops) { + rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); + if (rc) goto err_frhead; + rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); + if (rc) goto err_i2c_reg; } - 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); + + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { + rc = video_device_create_file(v4ldev, &class_device_attr_green); + if (rc) goto err_i2c_val; + } else if (cam->bridge == BRIDGE_SN9C103) { + rc = video_device_create_file(v4ldev, &class_device_attr_blue); + if (rc) goto err_i2c_val; + rc = video_device_create_file(v4ldev, &class_device_attr_red); + if (rc) goto err_blue; } + + return 0; + +err_blue: + video_device_remove_file(v4ldev, &class_device_attr_blue); +err_i2c_val: + if (cam->sensor.sysfs_ops) + video_device_remove_file(v4ldev, &class_device_attr_i2c_val); +err_i2c_reg: + if (cam->sensor.sysfs_ops) + video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); +err_frhead: + video_device_remove_file(v4ldev, &class_device_attr_frame_header); +err_val: + video_device_remove_file(v4ldev, &class_device_attr_val); +err_reg: + video_device_remove_file(v4ldev, &class_device_attr_reg); +err: + return rc; } #endif /* CONFIG_VIDEO_ADV_DEBUG */ @@ -1274,7 +1308,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; @@ -1312,7 +1346,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), @@ -1335,7 +1369,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; @@ -1404,7 +1438,7 @@ static int sn9c102_init(struct sn9c102_device* cam) } 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); @@ -1422,13 +1456,13 @@ static int sn9c102_init(struct sn9c102_device* cam) static void sn9c102_release_resources(struct sn9c102_device* cam) { - down(&sn9c102_sysfs_lock); + mutex_lock(&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); - up(&sn9c102_sysfs_lock); + mutex_unlock(&sn9c102_sysfs_lock); kfree(cam->control_buffer); } @@ -1449,7 +1483,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) cam = video_get_drvdata(video_devdata(filp)); - if (down_interruptible(&cam->dev_sem)) { + if (mutex_lock_interruptible(&cam->dev_mutex)) { up_read(&sn9c102_disconnect); return -ERESTARTSYS; } @@ -1461,10 +1495,10 @@ static int sn9c102_open(struct inode* inode, struct file* filp) 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); + cam->state & DEV_DISCONNECTED + || !cam->users); if (err) { up_read(&sn9c102_disconnect); return err; @@ -1473,7 +1507,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) up_read(&sn9c102_disconnect); return -ENODEV; } - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); } @@ -1501,7 +1535,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); up_read(&sn9c102_disconnect); return err; } @@ -1511,7 +1545,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) { struct sn9c102_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 */ sn9c102_stop_transfer(cam); @@ -1519,7 +1553,8 @@ static int sn9c102_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { sn9c102_release_resources(cam); - up(&cam->dev_sem); + usb_put_dev(cam->usbdev); + mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; } @@ -1529,7 +1564,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; } @@ -1541,35 +1576,36 @@ 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 (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; } if (cam->io == IO_NONE) { if (!sn9c102_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; @@ -1583,30 +1619,32 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) } 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; } } @@ -1634,7 +1672,7 @@ exit: PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index, count); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return count; } @@ -1647,7 +1685,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) 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) { @@ -1663,7 +1701,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; } @@ -1685,12 +1723,12 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) 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; } @@ -1720,29 +1758,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 (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; } @@ -1751,7 +1789,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) break; } if (i == cam->nbuffers) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EINVAL; } @@ -1761,7 +1799,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))) { - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return -EAGAIN; } start += PAGE_SIZE; @@ -1774,7 +1812,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) sn9c102_vm_open(vma); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return 0; } @@ -1788,13 +1826,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; @@ -1816,6 +1854,7 @@ 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; @@ -1825,7 +1864,19 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) 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 +1893,7 @@ sn9c102_vidioc_gs_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; @@ -1864,7 +1915,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; @@ -1896,7 +1947,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 +1960,8 @@ 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; @@ -1931,7 +1984,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; @@ -1947,7 +2000,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, }; @@ -1964,7 +2017,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); @@ -2105,7 +2158,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; @@ -2114,7 +2167,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)); @@ -2128,9 +2181,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); @@ -2190,7 +2243,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; @@ -2263,7 +2316,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; @@ -2412,12 +2465,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; - int err = 0; + long timeout; if (copy_from_user(&b, arg, sizeof(b))) return -EFAULT; @@ -2430,16 +2483,18 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, 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; } @@ -2558,7 +2613,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)); @@ -2571,8 +2626,10 @@ 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_gs_input(cam, arg); + return sn9c102_vidioc_s_input(cam, arg); case VIDIOC_QUERYCTRL: return sn9c102_vidioc_query_ctrl(cam, arg); @@ -2580,11 +2637,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, case VIDIOC_G_CTRL: return sn9c102_vidioc_g_ctrl(cam, arg); - case VIDIOC_S_CTRL_OLD: case VIDIOC_S_CTRL: return sn9c102_vidioc_s_ctrl(cam, arg); - case VIDIOC_CROPCAP_OLD: case VIDIOC_CROPCAP: return sn9c102_vidioc_cropcap(cam, arg); @@ -2631,7 +2686,6 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, case VIDIOC_G_PARM: return sn9c102_vidioc_g_parm(cam, arg); - case VIDIOC_S_PARM_OLD: case VIDIOC_S_PARM: return sn9c102_vidioc_s_parm(cam, arg); @@ -2650,24 +2704,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 (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; } @@ -2675,7 +2729,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - up(&cam->fileop_sem); + mutex_unlock(&cam->fileop_mutex); return err; } @@ -2722,7 +2776,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - init_MUTEX(&cam->dev_sem); + mutex_init(&cam->dev_mutex); r = sn9c102_read_reg(cam, 0x00); if (r < 0 || r != 0x10) { @@ -2733,7 +2787,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: @@ -2752,10 +2806,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) 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; @@ -2776,37 +2830,45 @@ 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); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); 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; - up(&cam->dev_sem); - goto fail; + goto fail2; } 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; #ifdef CONFIG_VIDEO_ADV_DEBUG - sn9c102_create_sysfs(cam); + err = sn9c102_create_sysfs(cam); + if (err) + goto fail3; DBG(2, "Optional device control through 'sysfs' interface ready"); #endif usb_set_intfdata(intf, cam); - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); return 0; +#ifdef CONFIG_VIDEO_ADV_DEBUG +fail3: + video_unregister_device(cam->v4ldev); +#endif +fail2: + video_nr[dev_nr] = -1; + dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; + mutex_unlock(&cam->dev_mutex); fail: if (cam) { kfree(cam->control_buffer); @@ -2827,7 +2889,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) down_write(&sn9c102_disconnect); - down(&cam->dev_sem); + mutex_lock(&cam->dev_mutex); DBG(2, "Disconnecting %s...", cam->v4ldev->name); @@ -2841,13 +2903,14 @@ 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_interruptible(&cam->wait_stream); + wake_up(&cam->wait_stream); + usb_get_dev(cam->usbdev); } else { cam->state |= DEV_DISCONNECTED; sn9c102_release_resources(cam); } - up(&cam->dev_sem); + mutex_unlock(&cam->dev_mutex); if (!cam->users) kfree(cam);