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;