diff options
author | Laurent Pinchart <laurent.pinchart@skynet.be> | 2009-05-06 11:30:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 17:21:10 -0400 |
commit | 078f8947926732a526fb280c0f3a8920bf173b9c (patch) | |
tree | e0984df189bde0ae2223e45d65b25ec9d023928c | |
parent | 86cf5f84e60fe32e3e665fdc69325f8993970189 (diff) |
V4L/DVB (11835): uvcvideo: Parse frame descriptors with non-continuous indexes.
The UVC specification requires frame descriptors indexes to range from 1 to
the number of frame descriptors. At least some Hercules Dualpix Infinite
webcams erroneously use non-continuous index ranges. Make the driver support
them.
Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 24 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 17 |
2 files changed, 13 insertions, 28 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 507dc85646b2..34cd36037f11 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -289,10 +289,8 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
289 | struct uvc_format_desc *fmtdesc; | 289 | struct uvc_format_desc *fmtdesc; |
290 | struct uvc_frame *frame; | 290 | struct uvc_frame *frame; |
291 | const unsigned char *start = buffer; | 291 | const unsigned char *start = buffer; |
292 | unsigned char *_buffer; | ||
293 | unsigned int interval; | 292 | unsigned int interval; |
294 | unsigned int i, n; | 293 | unsigned int i, n; |
295 | int _buflen; | ||
296 | __u8 ftype; | 294 | __u8 ftype; |
297 | 295 | ||
298 | format->type = buffer[2]; | 296 | format->type = buffer[2]; |
@@ -413,20 +411,11 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
413 | buflen -= buffer[0]; | 411 | buflen -= buffer[0]; |
414 | buffer += buffer[0]; | 412 | buffer += buffer[0]; |
415 | 413 | ||
416 | /* Count the number of frame descriptors to test the bFrameIndex | ||
417 | * field when parsing the descriptors. We can't rely on the | ||
418 | * bNumFrameDescriptors field as some cameras don't initialize it | ||
419 | * properly. | ||
420 | */ | ||
421 | for (_buflen = buflen, _buffer = buffer; | ||
422 | _buflen > 2 && _buffer[2] == ftype; | ||
423 | _buflen -= _buffer[0], _buffer += _buffer[0]) | ||
424 | format->nframes++; | ||
425 | |||
426 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | 414 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame |
427 | * based formats have frame descriptors. | 415 | * based formats have frame descriptors. |
428 | */ | 416 | */ |
429 | while (buflen > 2 && buffer[2] == ftype) { | 417 | while (buflen > 2 && buffer[2] == ftype) { |
418 | frame = &format->frame[format->nframes]; | ||
430 | if (ftype != VS_FRAME_FRAME_BASED) | 419 | if (ftype != VS_FRAME_FRAME_BASED) |
431 | n = buflen > 25 ? buffer[25] : 0; | 420 | n = buflen > 25 ? buffer[25] : 0; |
432 | else | 421 | else |
@@ -441,16 +430,6 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
441 | return -EINVAL; | 430 | return -EINVAL; |
442 | } | 431 | } |
443 | 432 | ||
444 | if (buffer[3] - 1 >= format->nframes) { | ||
445 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
446 | "interface %d frame index %u out of range\n", | ||
447 | dev->udev->devnum, alts->desc.bInterfaceNumber, | ||
448 | buffer[3]); | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | |||
452 | frame = &format->frame[buffer[3] - 1]; | ||
453 | |||
454 | frame->bFrameIndex = buffer[3]; | 433 | frame->bFrameIndex = buffer[3]; |
455 | frame->bmCapabilities = buffer[4]; | 434 | frame->bmCapabilities = buffer[4]; |
456 | frame->wWidth = get_unaligned_le16(&buffer[5]); | 435 | frame->wWidth = get_unaligned_le16(&buffer[5]); |
@@ -507,6 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
507 | 10000000/frame->dwDefaultFrameInterval, | 486 | 10000000/frame->dwDefaultFrameInterval, |
508 | (100000000/frame->dwDefaultFrameInterval)%10); | 487 | (100000000/frame->dwDefaultFrameInterval)%10); |
509 | 488 | ||
489 | format->nframes++; | ||
510 | buflen -= buffer[0]; | 490 | buflen -= buffer[0]; |
511 | buffer += buffer[0]; | 491 | buffer += buffer[0]; |
512 | } | 492 | } |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 6ce974d7362f..01b633c73480 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -65,7 +65,8 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, | |||
65 | struct uvc_streaming_control *ctrl) | 65 | struct uvc_streaming_control *ctrl) |
66 | { | 66 | { |
67 | struct uvc_format *format; | 67 | struct uvc_format *format; |
68 | struct uvc_frame *frame; | 68 | struct uvc_frame *frame = NULL; |
69 | unsigned int i; | ||
69 | 70 | ||
70 | if (ctrl->bFormatIndex <= 0 || | 71 | if (ctrl->bFormatIndex <= 0 || |
71 | ctrl->bFormatIndex > video->streaming->nformats) | 72 | ctrl->bFormatIndex > video->streaming->nformats) |
@@ -73,11 +74,15 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, | |||
73 | 74 | ||
74 | format = &video->streaming->format[ctrl->bFormatIndex - 1]; | 75 | format = &video->streaming->format[ctrl->bFormatIndex - 1]; |
75 | 76 | ||
76 | if (ctrl->bFrameIndex <= 0 || | 77 | for (i = 0; i < format->nframes; ++i) { |
77 | ctrl->bFrameIndex > format->nframes) | 78 | if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { |
78 | return; | 79 | frame = &format->frame[i]; |
80 | break; | ||
81 | } | ||
82 | } | ||
79 | 83 | ||
80 | frame = &format->frame[ctrl->bFrameIndex - 1]; | 84 | if (frame == NULL) |
85 | return; | ||
81 | 86 | ||
82 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || | 87 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || |
83 | (ctrl->dwMaxVideoFrameSize == 0 && | 88 | (ctrl->dwMaxVideoFrameSize == 0 && |
@@ -1089,7 +1094,7 @@ int uvc_video_init(struct uvc_video_device *video) | |||
1089 | /* Zero bFrameIndex might be correct. Stream-based formats (including | 1094 | /* Zero bFrameIndex might be correct. Stream-based formats (including |
1090 | * MPEG-2 TS and DV) do not support frames but have a dummy frame | 1095 | * MPEG-2 TS and DV) do not support frames but have a dummy frame |
1091 | * descriptor with bFrameIndex set to zero. If the default frame | 1096 | * descriptor with bFrameIndex set to zero. If the default frame |
1092 | * descriptor is not found, use the first avalable frame. | 1097 | * descriptor is not found, use the first available frame. |
1093 | */ | 1098 | */ |
1094 | for (i = format->nframes; i > 0; --i) { | 1099 | for (i = format->nframes; i > 0; --i) { |
1095 | frame = &format->frame[i-1]; | 1100 | frame = &format->frame[i-1]; |