diff -urN spca5xx-20060501.orig/drivers/usb/spca5xx.c spca5xx-20060501/drivers/usb/spca5xx.c --- spca5xx-20060501.orig/drivers/usb/spca5xx.c 2006-04-29 11:38:07.000000000 -0400 +++ spca5xx-20060501/drivers/usb/spca5xx.c 2006-09-05 13:19:04.000000000 -0400 @@ -1574,6 +1574,66 @@ spca50x->funct.stopN(spca50x); } + +/********************************************************************** +* spcaReducePacketSize +* Function Fixes the bandwidth problem that occurs +* when other USB devices are on the same host controller bus as the +* camera by gradually lowering the bandwidth requirements of the driver. +* It works even when other USB devices are present on the same +* host controller bus as the camera. +* +* Problem +* When other USB devices are present on the same host controller +* bus as the camera, the bandwidth requirements of the spca5xx driver +* are not being met. The spca5xx driver is asking for more bandwidth +* than is available which results in the following error messages: +* +* No space left on device +* can't open /dev/video0: No space left on device. +* usb_submit_urb(0) ret -28 +* +* +* Many thanks to all the wonderful people contributing to this project. +* +* Great work! +* vodunvibe [AT] NO@SPAM.PLEASE yahoo DOT com +* 2006-08-27 +* +***********************************************************************/ +static int spcaReducePacketSize(struct usb_spca50x *spca50x, int n, int err) +{ + int size=896, fx, i; + err("spcaReducePacketSize: vodunvibe - The usb_submit_urb(%d) transfer request submission failed - You probably have another device sharing the same USB Host Controller Bus as your camera. Try using another USB port, on a different host controller bus.", n); + while (err == -ENOSPC && size >= 0) { + err("spcaReducePacketSize: vodunvibe - Lowering the bandwidth requirements - New packet size (%d) ", size); + spca50x_set_packet_size(spca50x, size); + spca50x->sbuf[n].urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + spca50x->sbuf[n].urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx; + spca50x->sbuf[n].urb->iso_frame_desc[fx].length = spca50x->packet_size; + } + size-=128; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) + err = usb_submit_urb(spca50x->sbuf[n].urb, GFP_KERNEL); +#else + err = usb_submit_urb(spca50x->sbuf[n].urb); +#endif + } + + if (!err) { + for (i = 0; i < SPCA50X_NUMSBUF; i++) { + spca50x->sbuf[i].urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + spca50x->sbuf[i].urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx; + spca50x->sbuf[i].urb->iso_frame_desc[fx].length = spca50x->packet_size; + } + } + } + return err; +} + + static int spca50x_init_isoc(struct usb_spca50x *spca50x) { @@ -1649,7 +1709,15 @@ #endif if (err) { err("init isoc: usb_submit_urb(%d) ret %d", n, err); - return err; + if (err == -ENOSPC) { + err = spcaReducePacketSize(spca50x, n, err); + if (err) { + err("init isoc: After spcaReducePacketSize - usb_submit_urb(%d) ret %d", n, err); + return err; + } + }else{ + return err; + } } }