diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-11 17:48:11 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-11 17:48:11 -0300 |
commit | aaaaa6a00dd372109ceb39c63aef9088ec86e344 (patch) | |
tree | a33ab322c266ae761fa32c397c88a761b92c3bd8 | |
parent | 0e0a1701b02504470a123c46787736681b329c9e (diff) | |
parent | 3d4939aa3fd67ca96970740ca759d960c8511437 (diff) | |
download | mediapointer-dvb-s2-aaaaa6a00dd372109ceb39c63aef9088ec86e344.tar.gz mediapointer-dvb-s2-aaaaa6a00dd372109ceb39c63aef9088ec86e344.tar.bz2 |
merge: http://linuxtv.org/hg/~pinchartl/uvcvideo/
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_ctrl.c | 35 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_driver.c | 25 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_queue.c | 14 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_v4l2.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvcvideo.h | 2 |
5 files changed, 52 insertions, 26 deletions
diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 7774ce6b5..ef55bc35a 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -1374,21 +1374,19 @@ end: } /* - * Prune an entity of its bogus controls. This currently includes processing - * unit auto controls for which no corresponding manual control is available. - * Such auto controls make little sense if any, and are known to crash at - * least the SiGma Micro webcam. + * Prune an entity of its bogus controls using a blacklist. Bogus controls + * are currently the ones that crash the camera or unconditionally return an + * error when queried. */ static void -uvc_ctrl_prune_entity(struct uvc_entity *entity) +uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) { static const struct { - u8 idx_manual; - u8 idx_auto; + struct usb_device_id id; + u8 index; } blacklist[] = { - { 2, 11 }, /* Hue */ - { 6, 12 }, /* White Balance Temperature */ - { 7, 13 }, /* White Balance Component */ + { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ + { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ }; u8 *controls; @@ -1402,19 +1400,17 @@ uvc_ctrl_prune_entity(struct uvc_entity *entity) size = entity->processing.bControlSize; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { - if (blacklist[i].idx_auto >= 8 * size || - blacklist[i].idx_manual >= 8 * size) + if (!usb_match_id(dev->intf, &blacklist[i].id)) continue; - if (!uvc_test_bit(controls, blacklist[i].idx_auto) || - uvc_test_bit(controls, blacklist[i].idx_manual)) + if (blacklist[i].index >= 8 * size || + !uvc_test_bit(controls, blacklist[i].index)) continue; - uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no " - "matching manual control, removing it.\n", entity->id, - blacklist[i].idx_auto); + uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, " + "removing it.\n", entity->id, blacklist[i].index); - uvc_clear_bit(controls, blacklist[i].idx_auto); + uvc_clear_bit(controls, blacklist[i].index); } } @@ -1444,8 +1440,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) bControlSize = entity->camera.bControlSize; } - if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS) - uvc_ctrl_prune_entity(entity); + uvc_ctrl_prune_entity(dev, entity); for (i = 0; i < bControlSize; ++i) ncontrols += hweight8(bmControls[i]); diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 8d193376c..40df6828f 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -644,7 +644,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, _buflen = buflen; /* Count the format and frame descriptors. */ - while (_buflen > 2) { + while (_buflen > 2 && _buffer[1] == CS_INTERFACE) { switch (_buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: @@ -709,7 +709,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->nformats = nformats; /* Parse the format descriptors. */ - while (buflen > 2) { + while (buflen > 2 && buffer[1] == CS_INTERFACE) { switch (buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: @@ -1919,6 +1919,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* Aveo Technology USB 2.0 Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1871, + .idProduct = 0x0306, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, /* Ecamm Pico iMage */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -1928,6 +1937,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, + /* FSC WebCam V30S */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x18ec, + .idProduct = 0x3288, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bodelin ProScopeHR */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_HI @@ -1948,8 +1966,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_IGNORE_SELECTOR_UNIT - | UVC_QUIRK_PRUNE_CONTROLS }, + | UVC_QUIRK_IGNORE_SELECTOR_UNIT }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} diff --git a/linux/drivers/media/video/uvc/uvc_queue.c b/linux/drivers/media/video/uvc/uvc_queue.c index 0155752e4..f854698c4 100644 --- a/linux/drivers/media/video/uvc/uvc_queue.c +++ b/linux/drivers/media/video/uvc/uvc_queue.c @@ -172,6 +172,20 @@ int uvc_free_buffers(struct uvc_video_queue *queue) return 0; } +/* + * Check if buffers have been allocated. + */ +int uvc_queue_allocated(struct uvc_video_queue *queue) +{ + int allocated; + + mutex_lock(&queue->mutex); + allocated = queue->count != 0; + mutex_unlock(&queue->mutex); + + return allocated; +} + static void __uvc_query_buffer(struct uvc_buffer *buf, struct v4l2_buffer *v4l2_buf) { diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 160c01314..736d8ae23 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -251,7 +251,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, if (fmt->type != video->streaming->type) return -EINVAL; - if (uvc_queue_streaming(&video->queue)) + if (uvc_queue_allocated(&video->queue)) return -EBUSY; ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 6b254fd39..de13c86f2 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -314,7 +314,6 @@ struct uvc_xu_control { #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 -#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 /* Format flags */ @@ -749,6 +748,7 @@ extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +extern int uvc_queue_allocated(struct uvc_video_queue *queue); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { return queue->flags & UVC_QUEUE_STREAMING; |