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;