
From: Helge Deller <deller@gmx.de>

Adds the missing sysfs support to the CPiA driver by adding the needed
remove() function.  This avoids the current kernel warnings: videodev:
"CPiA Camera" has no release callback.  Please fix your driver for proper
sysfs support, see http://lwn.net/Articles/36850/

Tested with a CPiA USB webcam. 

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/media/video/cpia.c |   39 +++++++++++++++++++++++++++----------
 25-akpm/drivers/media/video/cpia.h |    2 -
 2 files changed, 30 insertions(+), 11 deletions(-)

diff -puN drivers/media/video/cpia.c~add-missing-sysfs-support-to-cpia-webcam-video-driver drivers/media/video/cpia.c
--- 25/drivers/media/video/cpia.c~add-missing-sysfs-support-to-cpia-webcam-video-driver	Thu Jul  8 16:04:30 2004
+++ 25-akpm/drivers/media/video/cpia.c	Thu Jul  8 16:04:30 2004
@@ -1368,7 +1368,7 @@ static void create_proc_cpia_cam(struct 
 	if (!cpia_proc_root || !cam)
 		return;
 
-	sprintf(name, "video%d", cam->vdev.minor);
+	sprintf(name, "video%d", cam->vdev->minor);
 	
 	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
 	if (!ent)
@@ -1393,7 +1393,7 @@ static void destroy_proc_cpia_cam(struct
 	if (!cam || !cam->proc_entry)
 		return;
 	
-	sprintf(name, "video%d", cam->vdev.minor);
+	sprintf(name, "video%d", cam->vdev->minor);
 	remove_proc_entry(name, cpia_proc_root);
 	cam->proc_entry = NULL;
 }
@@ -3710,7 +3710,7 @@ static int cpia_do_ioctl(struct inode *i
 
 		DBG("VIDIOCGUNIT\n");
 
-		vu->video    = cam->vdev.minor;
+		vu->video    = cam->vdev->minor;
 		vu->vbi      = VIDEO_NO_UNIT;
 		vu->radio    = VIDEO_NO_UNIT;
 		vu->audio    = VIDEO_NO_UNIT;
@@ -3804,6 +3804,14 @@ static int cpia_mmap(struct file *file, 
 	return 0;
 }
 
+
+void cpia_video_release(struct video_device *vfd)
+{
+	struct cam_data *cam = vfd->priv;
+	down(&cam->busy_lock);
+	video_device_release(vfd);
+}
+
 static struct file_operations cpia_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cpia_open,
@@ -3820,6 +3828,8 @@ static struct video_device cpia_template
 	.type		= VID_TYPE_CAPTURE,
 	.hardware	= VID_HARDWARE_CPIA,
 	.fops           = &cpia_fops,
+	.release	= cpia_video_release,
+	.minor		= -1,
 };
 
 /* initialise cam_data structure  */
@@ -3930,7 +3940,7 @@ static void reset_camera_struct(struct c
 }
 
 /* initialize cam_data structure  */
-static void init_camera_struct(struct cam_data *cam,
+static int init_camera_struct(struct cam_data *cam,
                                struct cpia_camera_ops *ops )
 {
 	int i;
@@ -3946,8 +3956,13 @@ static void init_camera_struct(struct ca
 
 	cam->proc_entry = NULL;
 
-	memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
-	cam->vdev.priv = cam;
+	cam->vdev = video_device_alloc();
+	if (!cam->vdev) {
+		printk(KERN_ERR "cpia: video_device_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	memcpy(cam->vdev, &cpia_template, sizeof(cpia_template));
+	cam->vdev->priv = cam;
 	
 	cam->curframe = 0;
 	for (i = 0; i < FRAME_NUM; i++) {
@@ -3960,6 +3975,7 @@ static void init_camera_struct(struct ca
 	cam->decompressed_frame.height = 0;
 	cam->decompressed_frame.state = FRAME_UNUSED;
 	cam->decompressed_frame.data = NULL;
+	return 0;
 }
 
 struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
@@ -3970,11 +3986,14 @@ struct cam_data *cpia_register_camera(st
 		return NULL;
 
 	
-	init_camera_struct( camera, ops );
+	if (init_camera_struct( camera, ops )) {
+		kfree(camera);
+		return NULL;
+	}
 	camera->lowlevel_data = lowlevel;
 	
 	/* register v4l device */
-	if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+	if (video_register_device(camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
 		kfree(camera);
 		printk(KERN_DEBUG "video_register_device failed\n");
 		return NULL;
@@ -4019,7 +4038,7 @@ struct cam_data *cpia_register_camera(st
 void cpia_unregister_camera(struct cam_data *cam)
 {
 	DBG("unregistering video\n");
-	video_unregister_device(&cam->vdev);
+	video_unregister_device(cam->vdev);
 	if (cam->open_count) {
 		put_cam(cam->ops);
 		DBG("camera open -- setting ops to NULL\n");
@@ -4027,7 +4046,7 @@ void cpia_unregister_camera(struct cam_d
 	}
 	
 #ifdef CONFIG_PROC_FS
-	DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
+	DBG("destroying /proc/cpia/video%d\n", cam->vdev->minor);
 	destroy_proc_cpia_cam(cam);
 #endif	
 	if (!cam->open_count) {
diff -puN drivers/media/video/cpia.h~add-missing-sysfs-support-to-cpia-webcam-video-driver drivers/media/video/cpia.h
--- 25/drivers/media/video/cpia.h~add-missing-sysfs-support-to-cpia-webcam-video-driver	Thu Jul  8 16:04:30 2004
+++ 25-akpm/drivers/media/video/cpia.h	Thu Jul  8 16:04:30 2004
@@ -268,7 +268,7 @@ struct cam_data {
 					/* v4l */
 	int video_size;			/* VIDEO_SIZE_ */
 	volatile enum v4l_camstates camstate;	/* v4l layer status */
-	struct video_device vdev;	/* v4l videodev */
+	struct video_device *vdev;	/* v4l videodev */
 	struct video_picture vp;	/* v4l camera settings */
 	struct video_window vw;		/* v4l capture area */
 	struct video_capture vc;       	/* v4l subcapture area */
_
