patch-2.4.21 linux-2.4.21/drivers/media/video/cpia.c
Next file: linux-2.4.21/drivers/media/video/cpia.h
Previous file: linux-2.4.21/drivers/media/video/bttvp.h
Back to the patch index
Back to the overall index
- Lines: 827
- Date:
2003-06-13 07:51:34.000000000 -0700
- Orig file:
linux-2.4.20/drivers/media/video/cpia.c
- Orig date:
2002-11-28 15:53:13.000000000 -0800
diff -urN linux-2.4.20/drivers/media/video/cpia.c linux-2.4.21/drivers/media/video/cpia.c
@@ -6,6 +6,7 @@
* (C) Copyright 1999-2000 Peter Pregler
* (C) Copyright 1999-2000 Scott J. Bertin
* (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
+ * (C) Copyright 2000 STMicroelectronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,7 +23,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* #define _CPIA_DEBUG_ define for verbose debug output */
+/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
+/* #define _CPIA_DEBUG_ 1 */
+
#include <linux/config.h>
#include <linux/module.h>
@@ -512,6 +515,46 @@
return len;
}
+static int match(char *checkstr, char **buffer, unsigned long *count,
+ int *find_colon, int *err)
+{
+ int ret, colon_found = 1;
+ int len = strlen(checkstr);
+ ret = (len <= *count && strncmp(*buffer, checkstr, len) == 0);
+ if (ret) {
+ *buffer += len;
+ *count -= len;
+ if (*find_colon) {
+ colon_found = 0;
+ while (*count && (**buffer == ' ' || **buffer == '\t' ||
+ (!colon_found && **buffer == ':'))) {
+ if (**buffer == ':')
+ colon_found = 1;
+ --*count;
+ ++*buffer;
+ }
+ if (!*count || !colon_found)
+ *err = -EINVAL;
+ *find_colon = 0;
+ }
+ }
+ return ret;
+}
+
+static unsigned long int value(char **buffer, unsigned long *count, int *err)
+{
+ char *p;
+ unsigned long int ret;
+ ret = simple_strtoul(*buffer, &p, 0);
+ if (p == *buffer)
+ *err = -EINVAL;
+ else {
+ *count -= p - *buffer;
+ *buffer = p;
+ }
+ return ret;
+}
+
static int cpia_write_proc(struct file *file, const char *buf,
unsigned long count, void *data)
{
@@ -566,44 +609,11 @@
memcpy(&new_params, &cam->params, sizeof(struct cam_params));
new_mains = cam->mainsFreq;
-#define MATCH(x) \
- ({ \
- int _len = strlen(x), _ret, _colon_found; \
- _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
- if (_ret) { \
- buffer += _len; \
- count -= _len; \
- if (find_colon) { \
- _colon_found = 0; \
- while (count && (*buffer == ' ' || *buffer == '\t' || \
- (!_colon_found && *buffer == ':'))) { \
- if (*buffer == ':') \
- _colon_found = 1; \
- --count; \
- ++buffer; \
- } \
- if (!count || !_colon_found) \
- retval = -EINVAL; \
- find_colon = 0; \
- } \
- } \
- _ret; \
- })
+#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval))
+#define VALUE (value(&buffer,&count, &retval))
#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
new_params.version.firmwareRevision == (y))
-#define VALUE \
- ({ \
- char *_p; \
- unsigned long int _ret; \
- _ret = simple_strtoul(buffer, &_p, 0); \
- if (_p == buffer) \
- retval = -EINVAL; \
- else { \
- count -= _p - buffer; \
- buffer = _p; \
- } \
- _ret; \
- })
+
retval = 0;
while (count && !retval) {
@@ -1248,10 +1258,9 @@
}
}
#undef MATCH
-#undef FIRMWARE_VERSION
#undef VALUE
-#undef FIND_VALUE
-#undef FIND_END
+#undef FIRMWARE_VERSION
+
if (!retval) {
if (command_flags & COMMAND_SETCOLOURPARAMS) {
/* Adjust cam->vp to reflect these changes */
@@ -1560,7 +1569,7 @@
}
-static void inline free_frames(struct cpia_frame frame[FRAME_NUM])
+static inline void free_frames(struct cpia_frame frame[FRAME_NUM])
{
int i;
@@ -1745,7 +1754,7 @@
retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
if (retval)
- LOG("%x - failed\n", command);
+ DBG("%x - failed\n", command);
return retval;
}
@@ -1970,7 +1979,7 @@
while (size > 0) {
size -= (ll+2);
if (size < 0) {
- LOG("Insufficient data in buffer\n");
+ DBG("Insufficient data in buffer\n");
return -1;
}
@@ -1985,7 +1994,7 @@
int skipsize = skipcount(*ibuf >> 1, out_fmt);
obuf += skipsize;
if (obuf > end_obuf) {
- LOG("Insufficient data in buffer\n");
+ DBG("Insufficient data in buffer\n");
return -1;
}
++ibuf;
@@ -1994,7 +2003,7 @@
}
if (ll == 1) {
if (*ibuf != EOL) {
- LOG("EOL not found giving up after %d/%d"
+ DBG("EOL not found giving up after %d/%d"
" bytes\n", origsize-size, origsize);
return -1;
}
@@ -2012,7 +2021,7 @@
ibuf += 2; /* skip over line length */
}
} else {
- LOG("line length was not 1 but %d after %d/%d bytes\n",
+ DBG("line length was not 1 but %d after %d/%d bytes\n",
ll, origsize-size, origsize);
return -1;
}
@@ -2501,54 +2510,56 @@
return 0;
}
+static void put_cam(struct cpia_camera_ops* ops)
+{
+ if (ops->owner)
+ __MOD_DEC_USE_COUNT(ops->owner);
+}
+
/* ------------------------- V4L interface --------------------- */
-static int cpia_open(struct video_device *dev, int flags)
+static int cpia_open(struct inode *inode, struct file *file)
{
- int i;
+ struct video_device *dev = video_devdata(file);
struct cam_data *cam = dev->priv;
+ int err;
if (!cam) {
DBG("Internal error, cam_data not found!\n");
- return -EBUSY;
+ return -ENODEV;
}
-
+
if (cam->open_count > 0) {
DBG("Camera already open\n");
return -EBUSY;
}
-
+
+ if (!try_inc_mod_count(cam->ops->owner))
+ return -ENODEV;
+
+ down(&cam->busy_lock);
+
+ err = -ENOMEM;
if (!cam->raw_image) {
cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
if (!cam->raw_image)
- return -ENOMEM;
+ goto oops;
}
if (!cam->decompressed_frame.data) {
cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
- if (!cam->decompressed_frame.data) {
- rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
- cam->raw_image = NULL;
- return -ENOMEM;
- }
+ if (!cam->decompressed_frame.data)
+ goto oops;
}
/* open cpia */
- if (cam->ops->open(cam->lowlevel_data)) {
- rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
- cam->decompressed_frame.data = NULL;
- rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
- cam->raw_image = NULL;
- return -ENODEV;
- }
+ err = -ENODEV;
+ if (cam->ops->open(cam->lowlevel_data))
+ goto oops;
/* reset the camera */
- if ((i = reset_camera(cam)) != 0) {
+ if ((err = reset_camera(cam)) != 0) {
cam->ops->close(cam->lowlevel_data);
- rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
- cam->decompressed_frame.data = NULL;
- rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
- cam->raw_image = NULL;
- return i;
+ goto oops;
}
/* Set ownership of /proc/cpia/videoX to current user */
@@ -2562,14 +2573,28 @@
cam->mmap_kludge = 0;
++cam->open_count;
+ file->private_data = dev;
+ up(&cam->busy_lock);
return 0;
+
+ oops:
+ if (cam->decompressed_frame.data) {
+ rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
+ cam->decompressed_frame.data = NULL;
+ }
+ if (cam->raw_image) {
+ rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
+ cam->raw_image = NULL;
+ }
+ up(&cam->busy_lock);
+ put_cam(cam->ops);
+ return err;
}
-static void cpia_close(struct video_device *dev)
+static int cpia_close(struct inode *inode, struct file *file)
{
- struct cam_data *cam;
-
- cam = dev->priv;
+ struct video_device *dev = file->private_data;
+ struct cam_data *cam = dev->priv;
if (cam->ops) {
/* Return ownership of /proc/cpia/videoX to root */
@@ -2590,6 +2615,7 @@
/* close cpia */
cam->ops->close(cam->lowlevel_data);
+ put_cam(cam->ops);
}
if (--cam->open_count == 0) {
@@ -2607,20 +2633,20 @@
if (cam->frame_buf)
free_frame_buf(cam);
- if (!cam->ops) {
- video_unregister_device(dev);
+ if (!cam->ops)
kfree(cam);
- }
}
+ file->private_data = NULL;
- return;
+ return 0;
}
-static long cpia_read(struct video_device *dev, char *buf,
- unsigned long count, int noblock)
+static int cpia_read(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
{
- struct cam_data *cam = dev->priv;
+ struct video_device *dev = file->private_data;
+ struct cam_data *cam = dev->priv;
/* make this _really_ smp and multithread-safe */
if (down_interruptible(&cam->busy_lock))
@@ -2659,7 +2685,7 @@
/* copy data to user space */
if (cam->decompressed_frame.count > count) {
DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count,
- count);
+ (unsigned long) count);
up(&cam->busy_lock);
return -EFAULT;
}
@@ -2674,8 +2700,10 @@
return cam->decompressed_frame.count;
}
-static int cpia_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg)
+static int cpia_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int ioctlnr, void *arg)
{
+ struct video_device *dev = file->private_data;
struct cam_data *cam = dev->priv;
int retval = 0;
@@ -2692,20 +2720,17 @@
/* query capabilites */
case VIDIOCGCAP:
{
- struct video_capability b;
+ struct video_capability *b = arg;
DBG("VIDIOCGCAP\n");
- strcpy(b.name, "CPiA Camera");
- b.type = VID_TYPE_CAPTURE;
- b.channels = 1;
- b.audios = 0;
- b.maxwidth = 352; /* VIDEOSIZE_CIF */
- b.maxheight = 288;
- b.minwidth = 48; /* VIDEOSIZE_48_48 */
- b.minheight = 48;
-
- if (copy_to_user(arg, &b, sizeof(b)))
- retval = -EFAULT;
+ strcpy(b->name, "CPiA Camera");
+ b->type = VID_TYPE_CAPTURE;
+ b->channels = 1;
+ b->audios = 0;
+ b->maxwidth = 352; /* VIDEOSIZE_CIF */
+ b->maxheight = 288;
+ b->minwidth = 48; /* VIDEOSIZE_48_48 */
+ b->minheight = 48;
break;
}
@@ -2713,39 +2738,30 @@
/* get/set video source - we are a camera and nothing else */
case VIDIOCGCHAN:
{
- struct video_channel v;
+ struct video_channel *v = arg;
DBG("VIDIOCGCHAN\n");
- if (copy_from_user(&v, arg, sizeof(v))) {
- retval = -EFAULT;
- break;
- }
- if (v.channel != 0) {
+ if (v->channel != 0) {
retval = -EINVAL;
break;
}
- v.channel = 0;
- strcpy(v.name, "Camera");
- v.tuners = 0;
- v.flags = 0;
- v.type = VIDEO_TYPE_CAMERA;
- v.norm = 0;
+ v->channel = 0;
+ strcpy(v->name, "Camera");
+ v->tuners = 0;
+ v->flags = 0;
+ v->type = VIDEO_TYPE_CAMERA;
+ v->norm = 0;
- if (copy_to_user(arg, &v, sizeof(v)))
- retval = -EFAULT;
break;
}
case VIDIOCSCHAN:
{
- int v;
+ struct video_channel *v = arg;
DBG("VIDIOCSCHAN\n");
- if (copy_from_user(&v, arg, sizeof(v)))
- retval = -EFAULT;
-
- if (retval == 0 && v != 0)
+ if (v->channel != 0)
retval = -EINVAL;
break;
@@ -2753,38 +2769,35 @@
/* image properties */
case VIDIOCGPICT:
+ {
+ struct video_picture *pic = arg;
+
DBG("VIDIOCGPICT\n");
- if (copy_to_user(arg, &cam->vp, sizeof(struct video_picture)))
- retval = -EFAULT;
+ *pic = cam->vp;
break;
-
+ }
+
case VIDIOCSPICT:
{
- struct video_picture vp;
+ struct video_picture *vp = arg;
DBG("VIDIOCSPICT\n");
- /* copy_from_user */
- if (copy_from_user(&vp, arg, sizeof(vp))) {
- retval = -EFAULT;
- break;
- }
-
/* check validity */
- DBG("palette: %d\n", vp.palette);
- DBG("depth: %d\n", vp.depth);
- if (!valid_mode(vp.palette, vp.depth)) {
+ DBG("palette: %d\n", vp->palette);
+ DBG("depth: %d\n", vp->depth);
+ if (!valid_mode(vp->palette, vp->depth)) {
retval = -EINVAL;
break;
}
down(&cam->param_lock);
/* brightness, colour, contrast need no check 0-65535 */
- memcpy( &cam->vp, &vp, sizeof(vp) );
+ cam->vp = *vp;
/* update cam->params.colourParams */
- cam->params.colourParams.brightness = vp.brightness*100/65535;
- cam->params.colourParams.contrast = vp.contrast*100/65535;
- cam->params.colourParams.saturation = vp.colour*100/65535;
+ cam->params.colourParams.brightness = vp->brightness*100/65535;
+ cam->params.colourParams.contrast = vp->contrast*100/65535;
+ cam->params.colourParams.saturation = vp->colour*100/65535;
/* contrast is in steps of 8, so round */
cam->params.colourParams.contrast =
((cam->params.colourParams.contrast + 3) / 8) * 8;
@@ -2799,34 +2812,33 @@
cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
up(&cam->param_lock);
DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
- vp.depth, vp.palette, vp.brightness, vp.hue, vp.colour,
- vp.contrast);
+ vp->depth, vp->palette, vp->brightness, vp->hue,
+ vp->colour, vp->contrast);
break;
}
/* get/set capture window */
case VIDIOCGWIN:
+ {
+ struct video_window *vw = arg;
+
DBG("VIDIOCGWIN\n");
- if (copy_to_user(arg, &cam->vw, sizeof(struct video_window)))
- retval = -EFAULT;
+ *vw = cam->vw;
break;
-
+ }
+
case VIDIOCSWIN:
{
/* copy_from_user, check validity, copy to internal structure */
- struct video_window vw;
+ struct video_window *vw = arg;
DBG("VIDIOCSWIN\n");
- if (copy_from_user(&vw, arg, sizeof(vw))) {
- retval = -EFAULT;
- break;
- }
- if (vw.clipcount != 0) { /* clipping not supported */
+ if (vw->clipcount != 0) { /* clipping not supported */
retval = -EINVAL;
break;
}
- if (vw.clips != NULL) { /* clipping not supported */
+ if (vw->clips != NULL) { /* clipping not supported */
retval = -EINVAL;
break;
}
@@ -2835,8 +2847,8 @@
* is requested by the user???
*/
down(&cam->param_lock);
- if (vw.width != cam->vw.width || vw.height != cam->vw.height) {
- int video_size = match_videosize(vw.width, vw.height);
+ if (vw->width != cam->vw.width || vw->height != cam->vw.height) {
+ int video_size = match_videosize(vw->width, vw->height);
if (video_size < 0) {
retval = -EINVAL;
@@ -2865,41 +2877,34 @@
/* mmap interface */
case VIDIOCGMBUF:
{
- struct video_mbuf vm;
+ struct video_mbuf *vm = arg;
int i;
DBG("VIDIOCGMBUF\n");
- memset(&vm, 0, sizeof(vm));
- vm.size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
- vm.frames = FRAME_NUM;
+ memset(vm, 0, sizeof(*vm));
+ vm->size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
+ vm->frames = FRAME_NUM;
for (i = 0; i < FRAME_NUM; i++)
- vm.offsets[i] = CPIA_MAX_FRAME_SIZE * i;
-
- if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
- retval = -EFAULT;
+ vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i;
break;
}
case VIDIOCMCAPTURE:
{
- struct video_mmap vm;
+ struct video_mmap *vm = arg;
int video_size;
- if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) {
- retval = -EFAULT;
- break;
- }
- DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame,
- vm.width, vm.height);
- if (vm.frame<0||vm.frame>=FRAME_NUM) {
+ DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm->format, vm->frame,
+ vm->width, vm->height);
+ if (vm->frame<0||vm->frame>=FRAME_NUM) {
retval = -EINVAL;
break;
}
/* set video format */
- cam->vp.palette = vm.format;
- switch(vm.format) {
+ cam->vp.palette = vm->format;
+ switch(vm->format) {
case VIDEO_PALETTE_GREY:
cam->vp.depth=8;
break;
@@ -2924,7 +2929,7 @@
break;
/* set video size */
- video_size = match_videosize(vm.width, vm.height);
+ video_size = match_videosize(vm->width, vm->height);
if (video_size < 0) {
retval = -EINVAL;
break;
@@ -2937,37 +2942,33 @@
}
/* according to v4l-spec we must start streaming here */
cam->mmap_kludge = 1;
- retval = capture_frame(cam, &vm);
+ retval = capture_frame(cam, vm);
break;
}
case VIDIOCSYNC:
{
- int frame;
+ int *frame = arg;
- if (copy_from_user((void *)&frame, arg, sizeof(int))) {
- retval = -EFAULT;
- break;
- }
- //DBG("VIDIOCSYNC: %d\n", frame);
+ //DBG("VIDIOCSYNC: %d\n", *frame);
- if (frame<0 || frame >= FRAME_NUM) {
+ if (*frame<0 || *frame >= FRAME_NUM) {
retval = -EINVAL;
break;
}
- switch (cam->frame[frame].state) {
+ switch (cam->frame[*frame].state) {
case FRAME_UNUSED:
case FRAME_READY:
case FRAME_GRABBING:
- DBG("sync to unused frame %d\n", frame);
+ DBG("sync to unused frame %d\n", *frame);
retval = -EINVAL;
break;
case FRAME_DONE:
- cam->frame[frame].state = FRAME_UNUSED;
- //DBG("VIDIOCSYNC: %d synced\n", frame);
+ cam->frame[*frame].state = FRAME_UNUSED;
+ //DBG("VIDIOCSYNC: %d synced\n", *frame);
break;
}
if (retval == -EINTR) {
@@ -2979,36 +2980,22 @@
/* pointless to implement overlay with this camera */
case VIDIOCCAPTURE:
- retval = -EINVAL;
- break;
case VIDIOCGFBUF:
- retval = -EINVAL;
- break;
case VIDIOCSFBUF:
- retval = -EINVAL;
- break;
case VIDIOCKEY:
retval = -EINVAL;
break;
/* tuner interface - we have none */
case VIDIOCGTUNER:
- retval = -EINVAL;
- break;
case VIDIOCSTUNER:
- retval = -EINVAL;
- break;
case VIDIOCGFREQ:
- retval = -EINVAL;
- break;
case VIDIOCSFREQ:
retval = -EINVAL;
break;
/* audio interface - we have none */
case VIDIOCGAUDIO:
- retval = -EINVAL;
- break;
case VIDIOCSAUDIO:
retval = -EINVAL;
break;
@@ -3017,16 +3004,23 @@
break;
}
- up(&cam->param_lock);
up(&cam->busy_lock);
return retval;
}
+static int cpia_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
+}
+
+
/* FIXME */
-static int cpia_mmap(struct video_device *dev, const char *adr,
- unsigned long size)
+static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
{
- unsigned long start = (unsigned long)adr;
+ struct video_device *dev = file->private_data;
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
unsigned long page, pos;
struct cam_data *cam = dev->priv;
int retval;
@@ -3074,25 +3068,22 @@
return 0;
}
-int cpia_video_init(struct video_device *vdev)
-{
-#ifdef CONFIG_PROC_FS
- create_proc_cpia_cam(vdev->priv);
-#endif
- return 0;
-}
+static struct file_operations cpia_fops = {
+ owner: THIS_MODULE,
+ open: cpia_open,
+ release: cpia_close,
+ read: cpia_read,
+ mmap: cpia_mmap,
+ ioctl: cpia_ioctl,
+ llseek: no_llseek,
+};
static struct video_device cpia_template = {
owner: THIS_MODULE,
name: "CPiA Camera",
type: VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_CPIA,
- open: cpia_open,
- close: cpia_close,
- read: cpia_read,
- ioctl: cpia_ioctl,
- mmap: cpia_mmap,
- initialize: cpia_video_init,
+ fops: &cpia_fops,
minor: -1,
};
@@ -3229,16 +3220,10 @@
struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
{
- struct cam_data *camera;
-
- /* Need a lock when adding/removing cameras. This doesn't happen
- * often and doesn't take very long, so grabbing the kernel lock
- * should be OK. */
+ struct cam_data *camera;
- if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) {
- unlock_kernel();
+ if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL)
return NULL;
- }
init_camera_struct( camera, ops );
camera->lowlevel_data = lowlevel;
@@ -3246,7 +3231,6 @@
/* register v4l device */
if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
kfree(camera);
- unlock_kernel();
printk(KERN_DEBUG "video_register_device failed\n");
return NULL;
}
@@ -3266,6 +3250,10 @@
/* close cpia */
camera->ops->close(camera->lowlevel_data);
+#ifdef CONFIG_PROC_FS
+ create_proc_cpia_cam(camera);
+#endif
+
printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
camera->params.version.firmwareVersion,
camera->params.version.firmwareRevision,
@@ -3285,12 +3273,10 @@
void cpia_unregister_camera(struct cam_data *cam)
{
- if (!cam->open_count) {
- DBG("unregistering video\n");
- video_unregister_device(&cam->vdev);
- } else {
- LOG("/dev/video%d removed while open, "
- "deferring video_unregister_device\n", cam->vdev.minor);
+ DBG("unregistering video\n");
+ video_unregister_device(&cam->vdev);
+ if (cam->open_count) {
+ put_cam(cam->ops);
DBG("camera open -- setting ops to NULL\n");
cam->ops = NULL;
}
@@ -3313,9 +3299,6 @@
proc_cpia_create();
#endif
-#ifdef CONFIG_VIDEO_CPIA_PP
- cpia_pp_init();
-#endif
#ifdef CONFIG_KMOD
#ifdef CONFIG_VIDEO_CPIA_PP_MODULE
request_module("cpia_pp");
@@ -3325,6 +3308,10 @@
request_module("cpia_usb");
#endif
#endif /* CONFIG_KMOD */
+
+#ifdef CONFIG_VIDEO_CPIA_PP
+ cpia_pp_init();
+#endif
#ifdef CONFIG_VIDEO_CPIA_USB
cpia_usb_init();
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)