diff options
Diffstat (limited to 'drivers/media/usb/uvc/uvc_driver.c')
-rw-r--r-- | drivers/media/usb/uvc/uvc_driver.c | 74 |
1 files changed, 35 insertions, 39 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index da24a655ab68..775bede0d93d 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -344,6 +344,9 @@ static int uvc_parse_format(struct uvc_device *dev, u8 ftype; int ret; + if (buflen < 4) + return -EINVAL; + format->type = buffer[2]; format->index = buffer[3]; format->frames = frames; @@ -1866,7 +1869,7 @@ static int uvc_scan_device(struct uvc_device *dev) if (list_empty(&dev->chains)) { dev_info(&dev->udev->dev, "No valid video chain found.\n"); - return -1; + return -ENODEV; } /* Add GPIO entity to the first chain. */ @@ -1958,31 +1961,7 @@ static void uvc_unregister_video(struct uvc_device *dev) if (!video_is_registered(&stream->vdev)) continue; - /* - * For stream->vdev we follow the same logic as: - * vb2_video_unregister_device(). - */ - - /* 1. Take a reference to vdev */ - get_device(&stream->vdev.dev); - - /* 2. Ensure that no new ioctls can be called. */ - video_unregister_device(&stream->vdev); - - /* 3. Wait for old ioctls to finish. */ - mutex_lock(&stream->mutex); - - /* 4. Stop streaming. */ - uvc_queue_release(&stream->queue); - - mutex_unlock(&stream->mutex); - - put_device(&stream->vdev.dev); - - /* - * For stream->meta.vdev we can directly call: - * vb2_video_unregister_device(). - */ + vb2_video_unregister_device(&stream->vdev); vb2_video_unregister_device(&stream->meta.vdev); /* @@ -2030,6 +2009,8 @@ int uvc_register_video_device(struct uvc_device *dev, vdev->ioctl_ops = ioctl_ops; vdev->release = uvc_release; vdev->prio = &stream->chain->prio; + vdev->queue = &queue->queue; + vdev->lock = &queue->mutex; if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) vdev->vfl_dir = VFL_DIR_TX; else @@ -2239,7 +2220,6 @@ static int uvc_probe(struct usb_interface *intf, /* Parse the Video Class control descriptor. */ ret = uvc_parse_control(dev); if (ret < 0) { - ret = -ENODEV; uvc_dbg(dev, PROBE, "Unable to parse UVC descriptors\n"); goto error; } @@ -2275,22 +2255,19 @@ static int uvc_probe(struct usb_interface *intf, goto error; /* Scan the device for video chains. */ - if (uvc_scan_device(dev) < 0) { - ret = -ENODEV; + ret = uvc_scan_device(dev); + if (ret < 0) goto error; - } /* Initialize controls. */ - if (uvc_ctrl_init_device(dev) < 0) { - ret = -ENODEV; + ret = uvc_ctrl_init_device(dev); + if (ret < 0) goto error; - } /* Register video device nodes. */ - if (uvc_register_chains(dev) < 0) { - ret = -ENODEV; + ret = uvc_register_chains(dev); + if (ret < 0) goto error; - } #ifdef CONFIG_MEDIA_CONTROLLER /* Register the media device node */ @@ -2316,6 +2293,13 @@ static int uvc_probe(struct usb_interface *intf, goto error; } + ret = uvc_meta_init(dev); + if (ret < 0) { + dev_err(&dev->udev->dev, + "Error initializing the metadata formats (%d)\n", ret); + goto error; + } + if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME) udev->quirks &= ~USB_QUIRK_RESET_RESUME; @@ -2398,9 +2382,12 @@ static int __uvc_resume(struct usb_interface *intf, int reset) list_for_each_entry(stream, &dev->streams, list) { if (stream->intf == intf) { ret = uvc_video_resume(stream, reset); - if (ret < 0) - uvc_queue_streamoff(&stream->queue, - stream->queue.queue.type); + if (ret < 0) { + mutex_lock(&stream->queue.mutex); + vb2_streamoff(&stream->queue.queue, + stream->queue.queue.type); + mutex_unlock(&stream->queue.mutex); + } return ret; } } @@ -2514,6 +2501,15 @@ static const struct uvc_device_info uvc_quirk_force_y8 = { * Sort these by vendor/product ID. */ static const struct usb_device_id uvc_ids[] = { + /* HP Webcam HD 2300 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x03f0, + .idProduct = 0xe207, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = (kernel_ulong_t)&uvc_quirk_stream_no_fid }, /* Quanta ACER HD User Facing */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, |