Skip to content

Commit

Permalink
V4L/DVB (9569): uvcvideo: Sort the frame descriptors during parsing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Dec 29, 2008
1 parent 2f38483 commit c9535db
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions drivers/media/video/uvc/uvc_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,10 @@ static int uvc_parse_format(struct uvc_device *dev,
struct uvc_format_desc *fmtdesc;
struct uvc_frame *frame;
const unsigned char *start = buffer;
unsigned char *_buffer;
unsigned int interval;
unsigned int i, n;
int _buflen;
__u8 ftype;

format->type = buffer[2];
Expand Down Expand Up @@ -410,12 +412,20 @@ static int uvc_parse_format(struct uvc_device *dev,
buflen -= buffer[0];
buffer += buffer[0];

/* Count the number of frame descriptors to test the bFrameIndex
* field when parsing the descriptors. We can't rely on the
* bNumFrameDescriptors field as some cameras don't initialize it
* properly.
*/
for (_buflen = buflen, _buffer = buffer;
_buflen > 2 && _buffer[2] == ftype;
_buflen -= _buffer[0], _buffer += _buffer[0])
format->nframes++;

/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
* based formats have frame descriptors.
*/
while (buflen > 2 && buffer[2] == ftype) {
frame = &format->frame[format->nframes];

if (ftype != VS_FRAME_FRAME_BASED)
n = buflen > 25 ? buffer[25] : 0;
else
Expand All @@ -430,6 +440,16 @@ static int uvc_parse_format(struct uvc_device *dev,
return -EINVAL;
}

if (buffer[3] - 1 >= format->nframes) {
uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
"interface %d frame index %u out of range\n",
dev->udev->devnum, alts->desc.bInterfaceNumber,
buffer[3]);
return -EINVAL;
}

frame = &format->frame[buffer[3] - 1];

frame->bFrameIndex = buffer[3];
frame->bmCapabilities = buffer[4];
frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]);
Expand Down Expand Up @@ -486,7 +506,6 @@ static int uvc_parse_format(struct uvc_device *dev,
10000000/frame->dwDefaultFrameInterval,
(100000000/frame->dwDefaultFrameInterval)%10);

format->nframes++;
buflen -= buffer[0];
buffer += buffer[0];
}
Expand Down

0 comments on commit c9535db

Please sign in to comment.