ChangeSet 1.872.3.1, 2002/11/18 16:54:24-08:00, [EMAIL PROTECTED]

[PATCH] vicam.c

Included in this patch:

- (From John Tyner) Move allocation of memory out of send_control_msg. With
the allocation moved to open, control messages are less expensive since
they don't allocate and free memory every time.
- (From John Tyner) Change the behaviour of send_control_msg to return 0 on
success instead of the number of bytes transferred.
- Clean up of a couple down_interruptible() calls that weren't checking for
failure
- Rewrite of proc fs entries to use one file per value instead of parsing
in the kernel


diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c Wed Nov 20 01:01:26 2002
+++ b/drivers/usb/media/vicam.c Wed Nov 20 01:01:26 2002
@@ -1,6 +1,7 @@
 /*
  * USB ViCam WebCam driver
- * Copyright (c) 2002 Joe Burks ([EMAIL PROTECTED])
+ * Copyright (c) 2002 Joe Burks ([EMAIL PROTECTED]),
+ *                    John Tyner (fill in email address)
  *
  * Supports 3COM HomeConnect PC Digital WebCam
  *
@@ -403,13 +404,14 @@
        }
        vfree(mem);
 }
-       
+
 struct vicam_camera {
        u16 shutter_speed;      // capture shutter speed
        u16 gain;               // capture gain
 
        u8 *raw_image;          // raw data captured from the camera
        u8 *framebuf;           // processed data in RGB24 format
+       u8 *cntrlbuf;           // area used to send control msgs
 
        struct video_device vdev;       // v4l video device
        struct usb_device *udev;        // usb device
@@ -421,8 +423,8 @@
        u8 bulkEndpoint;
        bool needsDummyRead;
 
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *proc_entry;
+#if defined(CONFIG_VIDEO_PROC_FS)
+       struct proc_dir_entry *proc_dir;
 #endif
 
 };
@@ -437,22 +439,16 @@
 {
        int status;
 
-       // for reasons not yet known to me, you can't send USB control messages
-       // with data in the module (if you are compiled as a module).  Whatever
-       // the reason, copying it to memory allocated as kernel memory then
-       // doing the usb control message fixes the problem.
-
-       unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
-       memcpy(transfer_buffer, cp, size);
+       /* cp must be memory that has been allocated by kmalloc */
 
        status = usb_control_msg(udev,
                                 usb_sndctrlpipe(udev, 0),
                                 request,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_DEVICE, value, index,
-                                transfer_buffer, size, HZ);
+                                cp, size, HZ);
 
-       kfree(transfer_buffer);
+       status = min(status, 0);
 
        if (status < 0) {
                printk(KERN_INFO "Failed sending control message, error %d.\n",
@@ -465,29 +461,30 @@
 static int
 initialize_camera(struct vicam_camera *cam)
 {
+       const struct {
+               u8 *data;
+               u32 size;
+       } firmware[] = {
+               { .data = setup1, .size = sizeof(setup1) },
+               { .data = setup2, .size = sizeof(setup2) },
+               { .data = setup3, .size = sizeof(setup3) },
+               { .data = setup4, .size = sizeof(setup4) },
+               { .data = setup5, .size = sizeof(setup5) },
+               { .data = setup3, .size = sizeof(setup3) },
+               { .data = NULL, .size = 0 }
+       };
+       
        struct usb_device *udev = cam->udev;
-       int status;
+       int err, i;
 
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0)
-               return status;
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0)
-               return status;
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
-               return status;
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0)
-               return status;
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0)
-               return status;
-       if ((status =
-            send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
-               return status;
+       for (i = 0, err = 0; firmware[i].data && !err; i++) {
+               memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
 
-       return 0;
+               err = send_control_msg(udev, 0xff, 0, 0,
+                                      cam->cntrlbuf, firmware[i].size);
+       }
+
+       return err;
 }
 
 static int
@@ -752,7 +749,8 @@
                       "vicam video_device improperly initialized");
        }
 
-       down_interruptible(&cam->busy_lock);
+       if ( down_interruptible(&cam->busy_lock) )
+               return -EINTR;
 
        if (cam->open_count > 0) {
                printk(KERN_INFO
@@ -774,6 +772,14 @@
                return -ENOMEM;
        }
 
+       cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!cam->cntrlbuf) {
+               kfree(cam->raw_image);
+               rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+               up(&cam->busy_lock);
+               return -ENOMEM;
+       }
+
        // First upload firmware, then turn the camera on
 
        if (!cam->is_initialized) {
@@ -803,6 +809,7 @@
 
        kfree(cam->raw_image);
        rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+       kfree(cam->cntrlbuf);
 
        cam->open_count--;
 
@@ -915,7 +922,7 @@
 static void
 read_frame(struct vicam_camera *cam, int framenum)
 {
-       unsigned char request[16];
+       unsigned char *request = cam->cntrlbuf;
        int realShutter;
        int n;
        int actual_length;
@@ -984,7 +991,8 @@
 
        DBG("read %d bytes.\n", (int) count);
 
-       down_interruptible(&cam->busy_lock);
+       if ( down_interruptible(&cam->busy_lock) )
+               return -EINTR;
 
        if (*ppos >= VICAM_MAX_FRAME_SIZE) {
                *ppos = 0;
@@ -1057,24 +1065,17 @@
        return 0;
 }
 
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_VIDEO_PROC_FS)
 
 static struct proc_dir_entry *vicam_proc_root = NULL;
 
-static int
-vicam_read_proc(char *page, char **start, off_t off,
-                     int count, int *eof, void *data)
+int vicam_read_helper(char *page, char **start, off_t off,
+                               int count, int *eof, int value)
 {
        char *out = page;
        int len;
-       struct vicam_camera *cam = (struct vicam_camera *) data;
 
-       out +=
-           sprintf(out, "Vicam-based WebCam Linux Driver.\n");
-       out += sprintf(out, "(c) 2002 Joe Burks ([EMAIL PROTECTED])\n");
-       out += sprintf(out, "vicam stats:\n");
-       out += sprintf(out, "    Shutter Speed: 1/%d\n", cam->shutter_speed);
-       out += sprintf(out, "             Gain: %d\n", cam->gain);
+       out += sprintf(out, "%d",value);
 
        len = out - page;
        len -= off;
@@ -1089,37 +1090,42 @@
        return len;
 }
 
-static int
-vicam_write_proc(struct file *file, const char *buffer,
-                      unsigned long count, void *data)
+int vicam_read_proc_shutter(char *page, char **start, off_t off,
+                               int count, int *eof, void *data)
 {
-       char *in;
-       char *start;
-       struct vicam_camera *cam = (struct vicam_camera *) data;
+       return vicam_read_helper(page,start,off,count,eof,
+                               ((struct vicam_camera *)data)->shutter_speed);
+}
 
-       in = kmalloc(count + 1, GFP_KERNEL);
-       if (!in)
-               return -ENOMEM;
+int vicam_read_proc_gain(char *page, char **start, off_t off,
+                               int count, int *eof, void *data)
+{
+       return vicam_read_helper(page,start,off,count,eof,
+                               ((struct vicam_camera *)data)->gain);
+}
 
-       in[count] = 0;          // I'm not sure buffer is gauranteed to be null 
terminated
-       // so I do this to make sure I have a null in there.
+int vicam_write_proc_shutter(struct file *file, const char *buffer,
+                               unsigned long count, void *data)
+{
+       struct vicam_camera *cam = (struct vicam_camera *)data;
+       
+       cam->shutter_speed = simple_strtoul(buffer, NULL, 10);
 
-       strncpy(in, buffer, count);
+       return count;
+}
 
-       start = strstr(in, "gain=");
-       if (start
-           && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
-               cam->gain = simple_strtoul(start + 5, NULL, 10);
-
-       start = strstr(in, "shutter=");
-       if (start
-           && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
-               cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
+int vicam_write_proc_gain(struct file *file, const char *buffer,
+                               unsigned long count, void *data)
+{
+       struct vicam_camera *cam = (struct vicam_camera *)data;
+       
+       cam->gain = simple_strtoul(buffer, NULL, 10);
 
-       kfree(in);
        return count;
 }
 
+
+
 void
 vicam_create_proc_root(void)
 {
@@ -1140,11 +1146,9 @@
 }
 
 void
-vicam_create_proc_entry(void *ptr)
+vicam_create_proc_entry(struct vicam_camera *cam)
 {
-       struct vicam_camera *cam = (struct vicam_camera *) ptr;
-
-       char name[7];
+       char name[64];
        struct proc_dir_entry *ent;
 
        DBG(KERN_INFO "vicam: creating proc entry\n");
@@ -1158,46 +1162,49 @@
 
        sprintf(name, "video%d", cam->vdev.minor);
 
-       ent =
-           create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-                             vicam_proc_root);
-       if (!ent)
-               return;
+       cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
 
-       ent->data = cam;
-       ent->read_proc = vicam_read_proc;
-       ent->write_proc = vicam_write_proc;
-       ent->size = 512;
-       cam->proc_entry = ent;
+       if ( !cam->proc_dir ) return; // We should probably return an error here
+       
+       ent =
+           create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
+                             cam->proc_dir);
+       if (ent) {
+               ent->data = cam;
+               ent->read_proc = vicam_read_proc_shutter;
+               ent->write_proc = vicam_write_proc_shutter;
+               ent->size = 64;
+       }
+
+       ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
+                                       cam->proc_dir);
+       if ( ent ) {
+               ent->data = cam;
+               ent->read_proc = vicam_read_proc_gain;
+               ent->write_proc = vicam_write_proc_gain;
+               ent->size = 64;
+       }
 }
 
 void
 vicam_destroy_proc_entry(void *ptr)
 {
        struct vicam_camera *cam = (struct vicam_camera *) ptr;
-       char name[7];
+       char name[16];
 
-       if (!cam || !cam->proc_entry)
+       if ( !cam->proc_dir )
                return;
 
        sprintf(name, "video%d", cam->vdev.minor);
-       remove_proc_entry(name, vicam_proc_root);
-       cam->proc_entry = NULL;
+       remove_proc_entry("shutter", cam->proc_dir);
+       remove_proc_entry("gain", cam->proc_dir);
+       remove_proc_entry(name,vicam_proc_root);
+       cam->proc_dir = NULL;
 
 }
 
 #endif
 
-int
-vicam_video_init(struct video_device *vdev)
-{
-       // This would normally create the proc entry for this camera
-#ifdef CONFIG_PROC_FS
-       vicam_create_proc_entry(vdev->priv);
-#endif
-       return 0;
-}
-
 static struct file_operations vicam_fops = {
        .owner          = THIS_MODULE,
        .open           = vicam_open,
@@ -1296,6 +1303,8 @@
                return -EIO;
        }
 
+       vicam_create_proc_entry(cam);
+
        printk(KERN_INFO "ViCam webcam driver now controlling video device 
%d\n",cam->vdev.minor);
 
        dev_set_drvdata(&intf->dev, cam);
@@ -1314,7 +1323,7 @@
        
        video_unregister_device(&cam->vdev);
 
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_VIDEO_PROC_FS)
        vicam_destroy_proc_entry(cam);
 #endif
 
@@ -1329,7 +1338,7 @@
 usb_vicam_init(void)
 {
        DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_VIDEO_PROC_FS)
        vicam_create_proc_root();
 #endif
        if (usb_register(&vicam_driver) != 0)
@@ -1344,7 +1353,7 @@
               "ViCam-based WebCam driver shutdown\n");
 
        usb_deregister(&vicam_driver);
-#ifdef CONFIG_PROC_FS
+#if defined(CONFIG_VIDEO_PROC_FS)
        vicam_destroy_proc_root();
 #endif
 }


-------------------------------------------------------
This sf.net email is sponsored by: To learn the basics of securing 
your web site with SSL, click here to get a FREE TRIAL of a Thawte 
Server Certificate: http://www.gothawte.com/rd524.html
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to