Use flags the device exposes for UVC controls. Signed-off-by: Edgar Thier <info@xxxxxxxxxxxxxx> --- drivers/media/usb/uvc/uvc_ctrl.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index c2ee6e3..bc69e92 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1568,7 +1568,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, return ret; } - ctrl->loaded = 1; + if (!(ctrl->info.flags && UVC_CTRL_FLAG_AUTO_UPDATE)) + ctrl->loaded = 1; } /* Backup the current value in case we need to rollback later. */ @@ -1889,8 +1890,13 @@ int uvc_ctrl_restore_values(struct uvc_device *dev) static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, const struct uvc_control_info *info) { + u8 *data; int ret = 0; + data = kmalloc(2, GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + ctrl->info = *info; INIT_LIST_HEAD(&ctrl->info.mappings); @@ -1904,6 +1910,23 @@ static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, ctrl->initialized = 1; + ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum, + info->selector, data, 1); + if (ret < 0) { + uvc_trace(UVC_TRACE_CONTROL, + "GET_INFO failed on control %pUl/%u (%d).\n", + info->entity, info->selector, ret); + } + else { + ctrl->info.flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF + | (data[0] & UVC_CONTROL_CAP_GET ? + UVC_CTRL_FLAG_GET_CUR : 0) + | (data[0] & UVC_CONTROL_CAP_SET ? + UVC_CTRL_FLAG_SET_CUR : 0) + | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? + UVC_CTRL_FLAG_AUTO_UPDATE : 0); + } uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " "entity %u\n", ctrl->info.entity, ctrl->info.selector, dev->udev->devpath, ctrl->entity->id); @@ -1911,6 +1934,7 @@ static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, done: if (ret < 0) kfree(ctrl->uvc_data); + kfree(data); return ret; } -- 2.7.4