Hi,

Included in this patch:
        - 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.
        - Change the behaviour of send_control_msg to return 0 on
          success instead of the number of bytes transferred.
        - simplify the initialize camera function

Patch needs testing; please review and test (Joe this means you :)).

Patch is against Greg's current USB tree.

Thanks,
John
--- linux-a/drivers/usb/media/vicam.c   2002-11-08 11:04:15.000000000 -0800
+++ linux-b/drivers/usb/media/vicam.c   2002-11-08 11:24:32.000000000 -0800
@@ -403,13 +403,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
@@ -437,22 +438,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 +460,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
@@ -774,6 +770,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 +807,7 @@
 
        kfree(cam->raw_image);
        rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+       kfree(cam->cntrlbuf);
 
        cam->open_count--;
 
@@ -915,7 +920,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;

Reply via email to