[PATCH] USB: ZC0301 driver updates

ZC0301 driver updates.

Changes: + new, - removed, * cleanup, @ bugfix

@ Need usb_get|put_dev() when disconnecting, if the device is open
* Cleanups and updates in the documentation
+ Use per-device sensor structures
+ Add frame_timeout module parameter

Signed-off-by: Luca Risolia <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
Luca Risolia 2006-02-25 06:57:49 +00:00 • committed by Greg Kroah-Hartman
commit a847423905
5 changed files with 108 additions and 62 deletions

View file

@ -34,7 +34,8 @@
#include <linux/param.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <asm/semaphore.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include "zc0301_sensor.h"
@ -51,7 +52,7 @@
#define ZC0301_ALTERNATE_SETTING 7
#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
#define ZC0301_CTRL_TIMEOUT 100
#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
#define ZC0301_FRAME_TIMEOUT 2
/*****************************************************************************/
@ -94,6 +95,7 @@ enum zc0301_stream_state {
struct zc0301_module_param {
u8 force_munmap;
u16 frame_timeout;
};
static DECLARE_RWSEM(zc0301_disconnect);
@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect);
struct zc0301_device {
struct video_device* v4ldev;
struct zc0301_sensor* sensor;
struct zc0301_sensor sensor;
struct usb_device* usbdev;
struct urb* urb[ZC0301_URBS];
@ -129,11 +131,19 @@ struct zc0301_device {
/*****************************************************************************/
struct zc0301_device*
zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id)
{
if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
return cam;
return NULL;
}
void
zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
{
cam->sensor = sensor;
cam->sensor->usbdev = cam->usbdev;
memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor));
}
/*****************************************************************************/

View file

@ -29,11 +29,9 @@
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/stddef.h>
#include <linux/compiler.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
@ -54,8 +52,8 @@
#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia"
#define ZC0301_AUTHOR_EMAIL "<[email protected]>"
#define ZC0301_MODULE_LICENSE "GPL"
#define ZC0301_MODULE_VERSION "1:1.01"
#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1)
#define ZC0301_MODULE_VERSION "1:1.02"
#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2)
/*****************************************************************************/
@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap,
"\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
"\n");
static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
ZC0301_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout,
"\n<n[,...]> Timeout for a video frame in seconds."
"\nThis parameter is specific for each detected camera."
"\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
"\n");
#ifdef ZC0301_DEBUG
static unsigned short debug = ZC0301_DEBUG_LEVEL;
module_param(debug, ushort, 0644);
@ -115,8 +122,8 @@ static u32
zc0301_request_buffers(struct zc0301_device* cam, u32 count,
enum zc0301_io_method io)
{
struct v4l2_pix_format* p = &(cam->sensor->pix_format);
struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap ||
io == IO_READ ?
(p->width * p->height * p->priv) / 8 :
@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
(*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
frame);
imagesize = (cam->sensor->pix_format.width *
cam->sensor->pix_format.height *
cam->sensor->pix_format.priv) / 8;
imagesize = (cam->sensor.pix_format.width *
cam->sensor.pix_format.height *
cam->sensor.pix_format.priv) / 8;
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int len, status;
@ -555,7 +562,7 @@ zc0301_set_compression(struct zc0301_device* cam,
static int zc0301_init(struct zc0301_device* cam)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_control ctrl;
struct v4l2_queryctrl *qctrl;
struct v4l2_rect* rect;
@ -630,6 +637,7 @@ static void zc0301_release_resources(struct zc0301_device* cam)
DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
kfree(cam->control_buffer);
}
@ -798,7 +806,8 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
(!list_empty(&cam->outqueue)) ||
(cam->state & DEV_DISCONNECTED) ||
(cam->state & DEV_MISCONFIGURED),
ZC0301_FRAME_TIMEOUT );
cam->module_param.frame_timeout *
1000 * msecs_to_jiffies(1) );
if (timeout < 0) {
mutex_unlock(&cam->fileop_mutex);
return timeout;
@ -1056,7 +1065,7 @@ zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_queryctrl qc;
u8 i;
@ -1078,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_control ctrl;
int err = 0;
u8 i;
@ -1110,7 +1119,7 @@ exit:
static int
zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_control ctrl;
u8 i;
int err = 0;
@ -1123,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_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;
@ -1142,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
{
struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
cc->pixelaspect.numerator = 1;
@ -1158,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_crop crop = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
};
@ -1175,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_crop crop;
struct v4l2_rect* rect;
struct v4l2_rect* bounds = &(s->cropcap.bounds);
@ -1304,7 +1315,7 @@ static int
zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
{
struct v4l2_format format;
struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
if (copy_from_user(&format, arg, sizeof(format)))
return -EFAULT;
@ -1328,7 +1339,7 @@ static int
zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
void __user * arg)
{
struct zc0301_sensor* s = cam->sensor;
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_format format;
struct v4l2_pix_format* pix;
struct v4l2_pix_format* pfmt = &(s->pix_format);
@ -1612,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp,
(!list_empty(&cam->outqueue)) ||
(cam->state & DEV_DISCONNECTED) ||
(cam->state & DEV_MISCONFIGURED),
ZC0301_FRAME_TIMEOUT );
cam->module_param.frame_timeout *
1000 * msecs_to_jiffies(1) );
if (timeout < 0)
return timeout;
if (cam->state & DEV_DISCONNECTED)
@ -1911,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* 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);
else {
DBG(1, "No supported image sensor detected");
err = -ENODEV;
@ -1950,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
cam->module_param.force_munmap = force_munmap[dev_nr];
cam->module_param.frame_timeout = frame_timeout[dev_nr];
dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
@ -1994,6 +2007,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf)
cam->state |= DEV_DISCONNECTED;
wake_up_interruptible(&cam->wait_frame);
wake_up(&cam->wait_stream);
usb_get_dev(cam->usbdev);
} else {
cam->state |= DEV_DISCONNECTED;
zc0301_release_resources(cam);

View file

@ -22,6 +22,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
/*
NOTE: Sensor controls are disabled for now, becouse changing them while
streaming sometimes results in out-of-sync video frames. We'll use
the default initialization, until we know how to stop and start video
in the chip. However, the image quality still looks good under various
light conditions.
*/
#include <linux/delay.h>
#include "zc0301_sensor.h"
@ -245,7 +253,7 @@ static struct zc0301_sensor pas202bcb = {
.maximum = 0x3fff,
.step = 0x0001,
.default_value = 0x01e5,
.flags = 0,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
{
.id = V4L2_CID_GAIN,
@ -255,7 +263,17 @@ static struct zc0301_sensor pas202bcb = {
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x0c,
.flags = 0,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
{
.id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "DAC magnitude",
.minimum = 0x00,
.maximum = 0xff,
.step = 0x01,
.default_value = 0x00,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
{
.id = V4L2_CID_RED_BALANCE,
@ -265,7 +283,7 @@ static struct zc0301_sensor pas202bcb = {
.maximum = 0x0f,
.step = 0x01,
.default_value = 0x01,
.flags = 0,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
{
.id = V4L2_CID_BLUE_BALANCE,
@ -275,7 +293,7 @@ static struct zc0301_sensor pas202bcb = {
.maximum = 0x0f,
.step = 0x01,
.default_value = 0x05,
.flags = 0,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
{
.id = ZC0301_V4L2_CID_GREEN_BALANCE,
@ -285,17 +303,7 @@ static struct zc0301_sensor pas202bcb = {
.maximum = 0x0f,
.step = 0x01,
.default_value = 0x00,
.flags = 0,
},
{
.id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "DAC magnitude",
.minimum = 0x00,
.maximum = 0xff,
.step = 0x01,
.default_value = 0x04,
.flags = 0,
.flags = V4L2_CTRL_FLAG_DISABLED,
},
},
.get_ctrl = &pas202bcb_get_ctrl,

View file

@ -43,9 +43,11 @@ static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \
NULL, \
};
extern struct zc0301_device*
zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id);
extern void
zc0301_attach_sensor(struct zc0301_device* cam,
struct zc0301_sensor* sensor);
zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
#define ZC0301_USB_DEVICE(vend, prod, intclass) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
@ -56,7 +58,14 @@ zc0301_attach_sensor(struct zc0301_device* cam,
#define ZC0301_ID_TABLE \
static const struct usb_device_id zc0301_id_table[] = { \
{ ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \
{ ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \
{ ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \
{ ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \
{ ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \
{ ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \
{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \
{ ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \
{ } \
};
@ -80,15 +89,11 @@ struct zc0301_sensor {
struct v4l2_cropcap cropcap;
struct v4l2_pix_format pix_format;
int (*init)(struct zc0301_device* cam);
int (*get_ctrl)(struct zc0301_device* cam,
struct v4l2_control* ctrl);
int (*set_ctrl)(struct zc0301_device* cam,
int (*init)(struct zc0301_device*);
int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl);
int (*set_ctrl)(struct zc0301_device*,
const struct v4l2_control* ctrl);
int (*set_crop)(struct zc0301_device* cam,
const struct v4l2_rect* rect);
const struct usb_device* usbdev;
int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect);
/* Private */
struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS];