aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2008-11-08 16:53:49 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-29 14:53:30 -0500
commitc9535db3d23c56db50fe4e65542bf1c7f0a4681c (patch)
tree92312dbe1558a2a0b2b6e5bbf9b70573f18012b6 /drivers/media/video/uvc
parent2f38483bc45e11dc138cedce72135f57819f57c4 (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.c25
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 }