Commit 97b49ed5 authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] v4l: vicam usb camera update

This patch updates the vicam usb camera driver.  videodev adaptions are
there, and the unplug race fix.  I also did plenty of other small
cleanups and fixes, lots of forgotten breaks in the big ioctl switch for
example.  I wouldn't be surprised if the driver didn't work at all ...
parent 92f3a11c
...@@ -413,34 +413,37 @@ static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm) ...@@ -413,34 +413,37 @@ static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
* *
*****************************************************************************/ *****************************************************************************/
static int vicam_v4l_open(struct video_device *vdev, int flags) static int vicam_v4l_open(struct inode *inode, struct file *file)
{ {
struct video_device *vdev = video_devdata(file);
struct usb_vicam *vicam = (struct usb_vicam *)vdev; struct usb_vicam *vicam = (struct usb_vicam *)vdev;
int err = 0; int err = 0;
dbg("vicam_v4l_open"); dbg("vicam_v4l_open");
down(&vicam->sem); down(&vicam->sem);
vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES); vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
if (!vicam->fbuf) if (vicam->open_count) {
err=-ENOMEM; err = -EBUSY;
else { } else if (!vicam->fbuf) {
vicam->open_count = 1; err =- ENOMEM;
} } else {
#ifdef BLINKING #ifdef BLINKING
vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
info ("led on"); info ("led on");
vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
#endif #endif
vicam->open_count++;
file->private_data = vdev;
}
up(&vicam->sem); up(&vicam->sem);
return err; return err;
} }
static void vicam_v4l_close(struct video_device *vdev) static int vicam_v4l_close(struct inode *inode, struct file *file)
{ {
struct video_device *vdev = file->private_data;
struct usb_vicam *vicam = (struct usb_vicam *)vdev; struct usb_vicam *vicam = (struct usb_vicam *)vdev;
dbg("vicam_v4l_close"); dbg("vicam_v4l_close");
...@@ -456,17 +459,21 @@ static void vicam_v4l_close(struct video_device *vdev) ...@@ -456,17 +459,21 @@ static void vicam_v4l_close(struct video_device *vdev)
rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES); rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
vicam->fbuf = 0; vicam->fbuf = 0;
vicam->open_count=0; vicam->open_count=0;
file->private_data = NULL;
up(&vicam->sem); up(&vicam->sem);
/* Why does se401.c have a usbdevice check here? */ /* Why does se401.c have a usbdevice check here? */
/* If device is unplugged while open, I guess we only may unregister now */ /* If device is unplugged while open, I guess we only may unregister now */
return 0;
} }
static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock) static int vicam_v4l_read(struct file *file, char *user_buf,
size_t buflen, loff_t *ppos)
{ {
struct video_device *vdev = file->private_data;
//struct usb_vicam *vicam = (struct usb_vicam *)vdev; //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
dbg("vicam_v4l_read(%ld)", buflen); dbg("vicam_v4l_read(%d)", buflen);
if (!vdev || !buf) if (!vdev || !buf)
return -EFAULT; return -EFAULT;
...@@ -476,14 +483,10 @@ static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned l ...@@ -476,14 +483,10 @@ static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned l
return buflen; return buflen;
} }
static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) static int vicam_v4l_ioctl(struct inode *inode, struct file *file,
{ unsigned int cmd, void *arg)
info("vicam_v4l_write");
return -EINVAL;
}
static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{ {
struct video_device *vdev = file->private_data;
struct usb_vicam *vicam = (struct usb_vicam *)vdev; struct usb_vicam *vicam = (struct usb_vicam *)vdev;
int ret = -EL3RST; int ret = -EL3RST;
...@@ -495,98 +498,74 @@ static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar ...@@ -495,98 +498,74 @@ static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
switch (cmd) { switch (cmd) {
case VIDIOCGCAP: case VIDIOCGCAP:
{ {
struct video_capability b; struct video_capability *b = arg;
ret = vicam_get_capability(vicam,&b); ret = vicam_get_capability(vicam,b);
dbg("name %s",b.name); dbg("name %s",b->name);
if (copy_to_user(arg, &b, sizeof(b))) break;
ret = -EFAULT;
} }
case VIDIOCGFBUF: case VIDIOCGFBUF:
{ {
struct video_buffer vb; struct video_buffer *vb = arg;
info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param"); info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
/* frame buffer not supported, not used */ /* frame buffer not supported, not used */
memset(&vb, 0, sizeof(vb)); memset(vb, 0, sizeof(*vb));
vb.base = NULL;
/* FIXME - VIDIOCGFBUF - why the void */
if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
ret = -EFAULT;
ret = 0; ret = 0;
break;
} }
case VIDIOCGWIN: case VIDIOCGWIN:
{ {
struct video_window vw; struct video_window *vw = arg;
ret = vicam_get_window(vicam, &vw); ret = vicam_get_window(vicam, vw);
if (copy_to_user(arg, &vw, sizeof(vw))) break;
ret = -EFAULT;
} }
case VIDIOCSWIN: case VIDIOCSWIN:
{ {
struct video_window vw; struct video_window *vw = arg;
if (copy_from_user(&vw, arg, sizeof(vw))) ret = vicam_set_window(vicam, vw);
ret = -EFAULT; break;
else
ret = vicam_set_window(vicam, &vw);
return ret;
} }
case VIDIOCGCHAN: case VIDIOCGCHAN:
{ {
struct video_channel v; struct video_channel *v = arg;
if (copy_from_user(&v, arg, sizeof(v))) ret = vicam_get_channel(vicam,v);
ret = -EFAULT; break;
else {
ret = vicam_get_channel(vicam,&v);
if (copy_to_user(arg, &v, sizeof(v)))
ret = -EFAULT;
}
} }
case VIDIOCSCHAN: case VIDIOCSCHAN:
{ {
struct video_channel v; struct video_channel *v = arg;
if (copy_from_user(&v, arg, sizeof(v))) ret = vicam_set_channel(vicam,v);
ret = -EFAULT; break;
else
ret = vicam_set_channel(vicam,&v);
} }
case VIDIOCGPICT: case VIDIOCGPICT:
{ {
struct video_picture p; struct video_picture *p = arg;
ret = vicam_get_picture(vicam, &p); ret = vicam_get_picture(vicam,p);
if (copy_to_user(arg, &p, sizeof(p))) break;
ret = -EFAULT;
} }
case VIDIOCSPICT: case VIDIOCSPICT:
{ {
struct video_picture p; struct video_picture *p = arg;
if (copy_from_user(&p, arg, sizeof(p))) ret = vicam_set_picture(vicam,p);
ret = -EFAULT; break;
else
ret = vicam_set_picture(vicam, &p);
} }
case VIDIOCGMBUF: case VIDIOCGMBUF:
{ {
struct video_mbuf vm; struct video_mbuf *vm = arg;
ret = vicam_get_mmapbuffer(vicam,&vm); ret = vicam_get_mmapbuffer(vicam,vm);
/* FIXME - VIDIOCGMBUF - why the void */ break;
if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
ret = -EFAULT;
} }
case VIDIOCMCAPTURE: case VIDIOCMCAPTURE:
{ {
struct video_mmap vm; struct video_mmap *vm = arg;
ret = vicam_mmap_capture(vicam, &vm); ret = vicam_mmap_capture(vicam,vm);
/* FIXME: This is probably not right */ break;
} }
case VIDIOCSYNC: case VIDIOCSYNC:
{ {
int frame; int *frame = arg;
/* FIXME - VIDIOCSYNC - why the void */ ret = vicam_sync_frame(vicam,*frame);
if (copy_from_user((void *)&frame, arg, sizeof(int))) break;
ret = -EFAULT;
else
ret = vicam_sync_frame(vicam,frame);
} }
case VIDIOCKEY: case VIDIOCKEY:
...@@ -614,10 +593,12 @@ static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar ...@@ -614,10 +593,12 @@ static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
return ret; return ret;
} }
static int vicam_v4l_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size) static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct usb_vicam *vicam = (struct usb_vicam *)dev; struct video_device *vdev = file->private_data;
unsigned long start = (unsigned long)adr; struct usb_vicam *vicam = (struct usb_vicam *)vdev;
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end-vma->vm_start;
unsigned long page, pos; unsigned long page, pos;
down(&vicam->sem); down(&vicam->sem);
...@@ -651,27 +632,23 @@ static int vicam_v4l_mmap(struct vm_area_struct *vma, struct video_device *dev, ...@@ -651,27 +632,23 @@ static int vicam_v4l_mmap(struct vm_area_struct *vma, struct video_device *dev,
return 0; return 0;
} }
/* FIXME - vicam_v4l_init */
static int vicam_v4l_init(struct video_device *dev)
{
/* stick proc fs stuff in here if wanted */
dbg("vicam_v4l_init");
return 0;
}
/* FIXME - vicam_template - important */ /* FIXME - vicam_template - important */
static struct file_operations vicam_fops = {
owner: THIS_MODULE,
open: vicam_v4l_open,
release: vicam_v4l_close,
read: vicam_v4l_read,
mmap: vicam_v4l_mmap,
ioctl: video_generic_ioctl,
llseek: no_llseek,
};
static struct video_device vicam_template = { static struct video_device vicam_template = {
owner: THIS_MODULE, owner: THIS_MODULE,
name: "vicam USB camera", name: "vicam USB camera",
type: VID_TYPE_CAPTURE, type: VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_SE401, /* need to ask for own id */ hardware: VID_HARDWARE_SE401, /* need to ask for own id */
open: vicam_v4l_open, fops: &vicam_fops,
close: vicam_v4l_close, kernel_ioctl: vicam_v4l_ioctl,
read: vicam_v4l_read,
write: vicam_v4l_write,
ioctl: vicam_v4l_ioctl,
mmap: vicam_v4l_mmap,
initialize: vicam_v4l_init,
}; };
/****************************************************************************** /******************************************************************************
...@@ -872,7 +849,6 @@ static void vicam_disconnect(struct usb_device *udev, void *ptr) ...@@ -872,7 +849,6 @@ static void vicam_disconnect(struct usb_device *udev, void *ptr)
vicam = (struct usb_vicam *) ptr; vicam = (struct usb_vicam *) ptr;
if (!vicam->open_count)
video_unregister_device(&vicam->vdev); video_unregister_device(&vicam->vdev);
vicam->udev = NULL; vicam->udev = NULL;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment