Am Sonntag, den 06.03.2011, 12:47 +0100 schrieb Laurent Pinchart: > Hi Alexey, > > On Sunday 06 March 2011 11:57:15 Alexey Fisher wrote: > > A description of how you're making it more robust would be nice. > > > Signed-off-by: Alexey Fisher <bug-tr...@fisher-privat.net> > > --- > > drivers/media/video/uvc/uvc_video.c | 59 > > ++++++++++++++++++++++++++++++----- 1 files changed, 51 insertions(+), 8 > > deletions(-) > > > > diff --git a/drivers/media/video/uvc/uvc_video.c > > b/drivers/media/video/uvc/uvc_video.c index 64bd1d6..5380189 100644 > > --- a/drivers/media/video/uvc/uvc_video.c > > +++ b/drivers/media/video/uvc/uvc_video.c > > @@ -92,10 +92,9 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming > > *stream, { > > struct uvc_format *format; > > struct uvc_frame *frame = NULL; > > + struct usb_host_endpoint *ep; > > unsigned int i; > > > > - pr_debug("%s", __func__); > > - > > if (ctrl->bFormatIndex <= 0 || > > ctrl->bFormatIndex > stream->nformats) > > return; > > @@ -112,6 +111,9 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming > > *stream, if (frame == NULL) > > return; > > > > + pr_debug("%s: %s %ux%u", __func__, > > + format->name, frame->wWidth, frame->wHeight); > > + > > if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || > > (ctrl->dwMaxVideoFrameSize == 0 && > > stream->dev->uvc_version < 0x0110) || > > @@ -123,11 +125,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming > > *stream, frame->dwMaxVideoFrameBufferSize; > > } > > > > - if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) && > > + if ((!(format->flags & UVC_FMT_FLAG_COMPRESSED) || > > + format->fcc == V4L2_PIX_FMT_MJPEG ) && > > stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && > > stream->intf->num_altsetting > 1) { > > u32 interval; > > u32 bandwidth; > > + unsigned int best_psize = 3 * 1024; > > > > interval = (ctrl->dwFrameInterval > 100000) > > ? ctrl->dwFrameInterval > > @@ -139,13 +143,17 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming > > *stream, * high-speed devices) per second and add the UVC header size > > * (assumed to be 12 bytes long). > > */ > > - bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; > > + bandwidth = frame->dwMaxVideoFrameBufferSize; > > + //bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; > > Why ? The whole point of your patch set is to work around untrusted > dwMaxVideoFrameBufferSize values. > > > bandwidth *= 10000000 / interval + 1; > > bandwidth /= 1000; > > if (stream->dev->udev->speed == USB_SPEED_HIGH) > > bandwidth /= 8; > > bandwidth += 12; > > > > + /* add 20% more, in some cases it is still not enough */ > > + bandwidth *= 1.2; > > + > > That's not the kind of things I can accept with very very good arguments. I > don't want to break some cameras just to lower the size of the V4L2 buffers > allocated by the driver. > > > /* The bandwidth estimate is too low for many cameras. Don't use > > * maximum packet sizes lower than 1024 bytes to try and work > > * around the problem. According to measurements done on two > > @@ -153,12 +161,39 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming > > *stream, * resolutions working while not preventing two simultaneous > > * VGA streams at 15 fps. > > */ > > + pr_debug("%s: calculated bandwidth: %u for %u(fps); (before 1024 > > workaround).", + __func__, bandwidth, > > 10000000/interval); > > bandwidth = max_t(u32, bandwidth, 1024); > > > > + i = 0; > > + for (i = 0; i < stream->intf->num_altsetting; ++i) { > > + struct usb_host_interface *alts; > > + struct usb_host_endpoint *ep; > > + unsigned int psize; > > + > > + alts = &stream->intf->altsetting[i]; > > + ep = uvc_find_endpoint(alts, > > + stream->header.bEndpointAddress); > > + if (ep == NULL) > > + continue; > > + > > + psize = le16_to_cpu(ep->desc.wMaxPacketSize); > > + psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); > > + if ((psize >= bandwidth && psize <= best_psize) || > > + (i == stream->intf->num_altsetting - 1)) { > > + if (bandwidth > psize) > > + pr_debug("%s: trying psize=%u even if " > > + "bandwidth=%u", __func__, > > + psize, bandwidth); > > + best_psize = psize; > > + break; > > + } > > + } > > + > > pr_debug("%s: rewrite dwMaxPayloadTransferSize=%u to %u.", > > - __func__, ctrl->dwMaxPayloadTransferSize, bandwidth); > > + __func__, ctrl->dwMaxPayloadTransferSize, best_psize); > > > > - ctrl->dwMaxPayloadTransferSize = bandwidth; > > + ctrl->dwMaxPayloadTransferSize = best_psize; > > Is this needed ? uvc_init_video() already selects the best endpoint alternate > setting based on the requested bandwidth. This looks like duplicate code, > what's the point ?
Becouse we do uvc_set_video_ctrl with one bandwidth and uvc_video_init with other. I do not know if it is good in case we recalculate the value. > > > } > > } > > > > @@ -1099,11 +1134,19 @@ static int uvc_init_video(struct uvc_streaming > > *stream, gfp_t gfp_flags) /* Check if the bandwidth is high enough. */ > > psize = le16_to_cpu(ep->desc.wMaxPacketSize); > > psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); > > - if (psize >= bandwidth && psize <= best_psize) { > > + pr_debug("%s: bandwidth: %u; psize: %u; best_psize: %u", > > + __func__, bandwidth, psize, best_psize); > > + if ((psize >= bandwidth && psize <= best_psize) || > > + (i == intf->num_altsetting - 1)) { > > + if (bandwidth > psize) > > + pr_debug("%s: trying psize=%u even if " > > + "bandwidth=%u", __func__, > > + psize, bandwidth); And here we can just fail, or try the luck (and may be fail). So this part independet of all other changes. > > altsetting = i; > > best_psize = psize; > > best_ep = ep; > > - } > > + break; > > + } > > } here we make too match loops, so it is nice to have here a break > > if (best_ep == NULL) { > _______________________________________________ Linux-uvc-devel mailing list Linux-uvc-devel@lists.berlios.de https://lists.berlios.de/mailman/listinfo/linux-uvc-devel