diff options
author | Laurent Pinchart <laurent.pinchart@skynet.be> | 2008-11-08 16:53:49 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 14:53:30 -0500 |
commit | c9535db3d23c56db50fe4e65542bf1c7f0a4681c (patch) | |
tree | 92312dbe1558a2a0b2b6e5bbf9b70573f18012b6 /drivers/media/video/uvc | |
parent | 2f38483bc45e11dc138cedce72135f57819f57c4 (diff) |
V4L/DVB (9569): uvcvideo: Sort the frame descriptors during parsing
The UVC specification does not require frame descriptors to be sorted by
bFrameIndex. At least one camera (145f:013e) is known not to sort the
descriptors properly, so they need to be sorted during parsing as the driver
then accesses them by index.
Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 07cf9517bb4e..11398ee66320 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -288,8 +288,10 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
288 | struct uvc_format_desc *fmtdesc; | 288 | struct uvc_format_desc *fmtdesc; |
289 | struct uvc_frame *frame; | 289 | struct uvc_frame *frame; |
290 | const unsigned char *start = buffer; | 290 | const unsigned char *start = buffer; |
291 | unsigned char *_buffer; | ||
291 | unsigned int interval; | 292 | unsigned int interval; |
292 | unsigned int i, n; | 293 | unsigned int i, n; |
294 | int _buflen; | ||
293 | __u8 ftype; | 295 | __u8 ftype; |
294 | 296 | ||
295 | format->type = buffer[2]; | 297 | format->type = buffer[2]; |
@@ -410,12 +412,20 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
410 | buflen -= buffer[0]; | 412 | buflen -= buffer[0]; |
411 | buffer += buffer[0]; | 413 | buffer += buffer[0]; |
412 | 414 | ||
415 | /* Count the number of frame descriptors to test the bFrameIndex | ||
416 | * field when parsing the descriptors. We can't rely on the | ||
417 | * bNumFrameDescriptors field as some cameras don't initialize it | ||
418 | * properly. | ||
419 | */ | ||
420 | for (_buflen = buflen, _buffer = buffer; | ||
421 | _buflen > 2 && _buffer[2] == ftype; | ||
422 | _buflen -= _buffer[0], _buffer += _buffer[0]) | ||
423 | format->nframes++; | ||
424 | |||
413 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | 425 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame |
414 | * based formats have frame descriptors. | 426 | * based formats have frame descriptors. |
415 | */ | 427 | */ |
416 | while (buflen > 2 && buffer[2] == ftype) { | 428 | while (buflen > 2 && buffer[2] == ftype) { |
417 | frame = &format->frame[format->nframes]; | ||
418 | |||
419 | if (ftype != VS_FRAME_FRAME_BASED) | 429 | if (ftype != VS_FRAME_FRAME_BASED) |
420 | n = buflen > 25 ? buffer[25] : 0; | 430 | n = buflen > 25 ? buffer[25] : 0; |
421 | else | 431 | else |
@@ -430,6 +440,16 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
430 | return -EINVAL; | 440 | return -EINVAL; |
431 | } | 441 | } |
432 | 442 | ||
443 | if (buffer[3] - 1 >= format->nframes) { | ||
444 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
445 | "interface %d frame index %u out of range\n", | ||
446 | dev->udev->devnum, alts->desc.bInterfaceNumber, | ||
447 | buffer[3]); | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | |||
451 | frame = &format->frame[buffer[3] - 1]; | ||
452 | |||
433 | frame->bFrameIndex = buffer[3]; | 453 | frame->bFrameIndex = buffer[3]; |
434 | frame->bmCapabilities = buffer[4]; | 454 | frame->bmCapabilities = buffer[4]; |
435 | frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]); | 455 | frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]); |
@@ -486,7 +506,6 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
486 | 10000000/frame->dwDefaultFrameInterval, | 506 | 10000000/frame->dwDefaultFrameInterval, |
487 | (100000000/frame->dwDefaultFrameInterval)%10); | 507 | (100000000/frame->dwDefaultFrameInterval)%10); |
488 | 508 | ||
489 | format->nframes++; | ||
490 | buflen -= buffer[0]; | 509 | buflen -= buffer[0]; |
491 | buffer += buffer[0]; | 510 | buffer += buffer[0]; |
492 | } | 511 | } |