diff options
Diffstat (limited to 'linux/drivers/media/video/uvc')
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_ctrl.c | 185 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_driver.c | 9 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_status.c | 11 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_v4l2.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvc_video.c | 5 | ||||
-rw-r--r-- | linux/drivers/media/video/uvc/uvcvideo.h | 4 |
6 files changed, 184 insertions, 34 deletions
diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 6ef3e5297..b66c95ffd 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -83,6 +83,22 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .index = 7, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, .index = 8, .size = 2, @@ -114,6 +130,60 @@ static struct uvc_control_info uvc_ctrls[] = { | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, + .index = 12, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .index = 13, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, + .index = 15, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, + .index = 16, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_LOCK_STATUS_CONTROL, + .index = 17, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_SCANNING_MODE_CONTROL, + .index = 0, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, + { .entity = UVC_GUID_UVC_CAMERA, .selector = CT_AE_MODE_CONTROL, .index = 1, @@ -140,6 +210,14 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, + .index = 4, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, .selector = CT_FOCUS_ABSOLUTE_CONTROL, .index = 5, .size = 2, @@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_AUTO_CONTROL, - .index = 17, - .size = 1, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + .selector = CT_FOCUS_RELATIVE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .index = 12, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_ABSOLUTE_CONTROL, + .index = 7, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_RELATIVE_CONTROL, + .index = 8, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .index = 6, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_RELATIVE_CONTROL, + .index = 10, + .size = 3, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_ABSOLUTE_CONTROL, + .index = 11, + .size = 8, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_RELATIVE_CONTROL, + .index = 12, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_ABSOLUTE_CONTROL, .index = 13, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_RELATIVE_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_FOCUS_AUTO_CONTROL, + .index = 17, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, - .index = 7, - .size = 4, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PRIVACY_CONTROL, + .index = 18, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, }; @@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, for (i = 0; i < entity->ncontrols; ++i) { ctrl = &entity->controls[i]; - if (ctrl->info == NULL || !ctrl->dirty) + if (ctrl->info == NULL) + continue; + + /* Reset the loaded flag for auto-update controls that were + * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent + * uvc_ctrl_get from using the cached value. + */ + if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) + ctrl->loaded = 0; + + if (!ctrl->dirty) continue; if (!rollback) @@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), ctrl->info->size); - if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) - ctrl->loaded = 0; - ctrl->dirty = 0; if (ret < 0) @@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, if (ret < 0) return ret; - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } xctrl->value = uvc_get_le_value( @@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, return ret; } - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } if (!ctrl->dirty) { diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index b2482502a..5364417de 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1941,6 +1941,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* Advent 4211 - Bison Electronics */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x5986, + .idProduct = 0x0203, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bison Electronics */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index 75e678ac5..5d60b264d 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev) uvc_input_init(dev); + dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); + if (dev->status == NULL) + return -ENOMEM; + dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dev->int_urb == NULL) + if (dev->int_urb == NULL) { + kfree(dev->status); return -ENOMEM; + } pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); @@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev) interval = fls(interval) - 1; usb_fill_int_urb(dev->int_urb, dev->udev, pipe, - dev->status, sizeof dev->status, uvc_status_complete, + dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, dev, interval); return usb_submit_urb(dev->int_urb, GFP_KERNEL); @@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); usb_free_urb(dev->int_urb); + kfree(dev->status); uvc_input_cleanup(dev); } diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index d4758c8e1..78e4c4e09 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -842,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, if (ret < 0) return ret; - if (!(video->streaming->cur_format->flags & - UVC_FMT_FLAG_COMPRESSED)) - video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; - rb->count = ret; ret = 0; break; diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 593aebffe..b7bb23820 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -971,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) return 0; } + if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) + video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + else + video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; + if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) return ret; diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index bafe3406e..9a6bc1aaf 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -303,6 +303,8 @@ struct uvc_xu_control { #define UVC_MAX_FRAME_SIZE (16*1024*1024) /* Maximum number of video buffers. */ #define UVC_MAX_VIDEO_BUFFERS 32 +/* Maximum status buffer size in bytes of interrupt URB. */ +#define UVC_MAX_STATUS_SIZE 16 #define UVC_CTRL_CONTROL_TIMEOUT 300 #define UVC_CTRL_STREAMING_TIMEOUT 1000 @@ -634,7 +636,7 @@ struct uvc_device { /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; struct urb *int_urb; - __u8 status[16]; + __u8 *status; struct input_dev *input; /* Video Streaming interfaces */ |