aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2009-05-06 11:30:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 17:21:10 -0400
commit078f8947926732a526fb280c0f3a8920bf173b9c (patch)
treee0984df189bde0ae2223e45d65b25ec9d023928c
parent86cf5f84e60fe32e3e665fdc69325f8993970189 (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.c24
-rw-r--r--drivers/media/video/uvc/uvc_video.c17
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];