From 56094f2f714025a756faf2acd42500698dacb100 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 May 2009 17:30:30 +0200 Subject: uvcvideo: Parse frame descriptors with non-continuous indexes. From: Laurent Pinchart 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. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'linux/drivers/media/video/uvc/uvc_driver.c') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 31d60647d..94bb63ef1 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -289,10 +289,8 @@ 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]; @@ -413,20 +411,11 @@ 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 @@ -441,16 +430,6 @@ 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 = get_unaligned_le16(&buffer[5]); @@ -507,6 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, 10000000/frame->dwDefaultFrameInterval, (100000000/frame->dwDefaultFrameInterval)%10); + format->nframes++; buflen -= buffer[0]; buffer += buffer[0]; } -- cgit v1.2.3 From b872a134312bd4a2a97b537ab0b547a021d594df Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 May 2009 17:37:44 +0200 Subject: uvcvideo: Add missing whitespaces to multi-line format strings. From: Laurent Pinchart Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'linux/drivers/media/video/uvc/uvc_driver.c') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 94bb63ef1..1768389c4 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -301,7 +301,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_FRAME_BASED: n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28; if (buflen < n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -336,7 +336,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_MJPEG: if (buflen < 11) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -352,7 +352,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_DV: if (buflen < 9) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -370,7 +370,7 @@ static int uvc_parse_format(struct uvc_device *dev, strlcpy(format->name, "HD-DV", sizeof format->name); break; default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d: unknown DV format %u\n", dev->udev->devnum, alts->desc.bInterfaceNumber, buffer[8]); @@ -399,7 +399,7 @@ static int uvc_parse_format(struct uvc_device *dev, case VS_FORMAT_STREAM_BASED: /* Not supported yet. */ default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d unsupported format %u\n", dev->udev->devnum, alts->desc.bInterfaceNumber, buffer[2]); @@ -424,7 +424,7 @@ static int uvc_parse_format(struct uvc_device *dev, n = n ? n : 3; if (buflen < 26 + 4*n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FRAME error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); return -EINVAL; @@ -498,7 +498,7 @@ static int uvc_parse_format(struct uvc_device *dev, if (buflen > 2 && buffer[2] == VS_COLORFORMAT) { if (buflen < 6) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" + uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d COLORFORMAT error\n", dev->udev->devnum, alts->desc.bInterfaceNumber); @@ -1296,7 +1296,7 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, continue; if (forward->extension.bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has" + uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has " "more than 1 input pin.\n", entity->id); return -1; } -- cgit v1.2.3 From 39d53fcd39df81baf92cc74a0de40d5a1cbbd9bf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 May 2009 15:08:03 +0200 Subject: uvcvideo: Start status polling on device open From: Laurent Pinchart Most UVC camera include an interrupt endpoint to report control value changes, video streaming errors and camera button events. The USB controller continuously polls the interrupt endpoint to retrieve such events. This prevents the device from being auto-suspended, and thus consumes power. Reporting video streaming errors don't make sense when the V4L2 device is closed. Control value changes are probably useless as well if nobody listens to the events, although caching will probably have to be completely disabled then. No polling is thus be required when /dev/videoX is not opened. To enable auto-suspend and save power do not poll the interrupt endpoint until the device is open. We lose the ability to detect button events if no application is using the camera. http://bugzilla.kernel.org/show_bug.cgi?id=11948 Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers/media/video/uvc/uvc_driver.c') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 1768389c4..13bd05576 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1594,6 +1594,7 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->entities); INIT_LIST_HEAD(&dev->streaming); kref_init(&dev->kref); + atomic_set(&dev->users, 0); dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); -- cgit v1.2.3 From 2da5cdaefead4beb36671ca025826f9e8deadef4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 19 May 2009 15:12:17 +0200 Subject: uvcvideo: Add Lenovo Thinkpad SL400 to device list comments From: Filipe Rosset Update the 17ef:480b device comment to list Lenovo Thinkpad SL400. Priority: low Signed-off-by: Filipe Rosset Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media/video/uvc/uvc_driver.c') diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 13bd05576..177d149a5 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1907,7 +1907,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Lenovo Thinkpad SL500 */ + /* Lenovo Thinkpad SL400/SL500 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x17ef, -- cgit v1.2.3