Skip to content

Commit 4f4b3dc

Browse files
author
Desnes Nunes
committed
media: uvcvideo: implement UVC v1.5 ROI
JIRA: https://issues.redhat.com/browse/RHEL-78934 commit 2dc768d Author: Yunke Cao <yunkec@google.com> Date: Mon, 3 Feb 2025 11:55:52 +0000 Implement support for ROI as described in UVC 1.5: 4.2.2.1.20 Digital Region of Interest (ROI) Control ROI control is implemented using V4L2 control API as two UVC-specific controls: V4L2_CID_UVC_REGION_OF_INTEREST_RECT and V4L2_CID_UVC_REGION_OF_INTEREST_AUTO. Reviewed-by: Ricardo Ribalda <ribalda@chromium.org> Signed-off-by: Yunke Cao <yunkec@google.com> Reviewed-by: Yunke Cao <yunkec@google.com> Tested-by: Yunke Cao <yunkec@google.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Ricardo Ribalda <ribalda@chromium.org> Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-16-5900a9fed613@chromium.org Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> [hverkuil: fix control names: "Of" -> "of", "Controls" -> "Ctrls"] Signed-off-by: Desnes Nunes <desnesn@redhat.com>
1 parent a0d7271 commit 4f4b3dc

File tree

5 files changed

+109
-0
lines changed

5 files changed

+109
-0
lines changed

drivers/media/usb/uvc/uvc_ctrl.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,24 @@ static const struct uvc_control_info uvc_ctrls[] = {
358358
.flags = UVC_CTRL_FLAG_GET_CUR
359359
| UVC_CTRL_FLAG_AUTO_UPDATE,
360360
},
361+
/*
362+
* UVC_CTRL_FLAG_AUTO_UPDATE is needed because the RoI may get updated
363+
* by sensors.
364+
* "This RoI should be the same as specified in most recent SET_CUR
365+
* except in the case where the ‘Auto Detect and Track’ and/or
366+
* ‘Image Stabilization’ bit have been set."
367+
* 4.2.2.1.20 Digital Region of Interest (ROI) Control
368+
*/
369+
{
370+
.entity = UVC_GUID_UVC_CAMERA,
371+
.selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
372+
.index = 21,
373+
.size = 10,
374+
.flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
375+
| UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
376+
| UVC_CTRL_FLAG_GET_DEF
377+
| UVC_CTRL_FLAG_AUTO_UPDATE,
378+
},
361379
};
362380

363381
static const u32 uvc_control_classes[] = {
@@ -603,6 +621,44 @@ static const struct uvc_control_mapping *uvc_ctrl_filter_plf_mapping(
603621
return out_mapping;
604622
}
605623

624+
static int uvc_get_rect(struct uvc_control_mapping *mapping, u8 query,
625+
const void *uvc_in, size_t v4l2_size, void *v4l2_out)
626+
{
627+
const struct uvc_rect *uvc_rect = uvc_in;
628+
struct v4l2_rect *v4l2_rect = v4l2_out;
629+
630+
if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
631+
return -EINVAL;
632+
633+
if (uvc_rect->left > uvc_rect->right ||
634+
uvc_rect->top > uvc_rect->bottom)
635+
return -EIO;
636+
637+
v4l2_rect->top = uvc_rect->top;
638+
v4l2_rect->left = uvc_rect->left;
639+
v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1;
640+
v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1;
641+
642+
return 0;
643+
}
644+
645+
static int uvc_set_rect(struct uvc_control_mapping *mapping, size_t v4l2_size,
646+
const void *v4l2_in, void *uvc_out)
647+
{
648+
struct uvc_rect *uvc_rect = uvc_out;
649+
const struct v4l2_rect *v4l2_rect = v4l2_in;
650+
651+
if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
652+
return -EINVAL;
653+
654+
uvc_rect->top = min(0xffff, v4l2_rect->top);
655+
uvc_rect->left = min(0xffff, v4l2_rect->left);
656+
uvc_rect->bottom = min(0xffff, v4l2_rect->top + v4l2_rect->height - 1);
657+
uvc_rect->right = min(0xffff, v4l2_rect->left + v4l2_rect->width - 1);
658+
659+
return 0;
660+
}
661+
606662
static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
607663
{
608664
.id = V4L2_CID_BRIGHTNESS,
@@ -897,6 +953,28 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
897953
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
898954
.filter_mapping = uvc_ctrl_filter_plf_mapping,
899955
},
956+
{
957+
.id = V4L2_CID_UVC_REGION_OF_INTEREST_RECT,
958+
.entity = UVC_GUID_UVC_CAMERA,
959+
.selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
960+
.size = sizeof(struct uvc_rect) * 8,
961+
.offset = 0,
962+
.v4l2_type = V4L2_CTRL_TYPE_RECT,
963+
.data_type = UVC_CTRL_DATA_TYPE_RECT,
964+
.get = uvc_get_rect,
965+
.set = uvc_set_rect,
966+
.name = "Region of Interest Rectangle",
967+
},
968+
{
969+
.id = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
970+
.entity = UVC_GUID_UVC_CAMERA,
971+
.selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
972+
.size = 16,
973+
.offset = 64,
974+
.v4l2_type = V4L2_CTRL_TYPE_BITMASK,
975+
.data_type = UVC_CTRL_DATA_TYPE_BITMASK,
976+
.name = "Region of Interest Auto Ctrls",
977+
},
900978
};
901979

902980
/* ------------------------------------------------------------------------
@@ -1473,6 +1551,9 @@ static int __uvc_queryctrl_boundaries(struct uvc_video_chain *chain,
14731551

14741552
static size_t uvc_mapping_v4l2_size(struct uvc_control_mapping *mapping)
14751553
{
1554+
if (mapping->v4l2_type == V4L2_CTRL_TYPE_RECT)
1555+
return sizeof(struct v4l2_rect);
1556+
14761557
if (uvc_ctrl_mapping_is_compound(mapping))
14771558
return DIV_ROUND_UP(mapping->size, 8);
14781559

drivers/media/usb/uvc/uvcvideo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,13 @@ struct uvc_device_info {
543543
u16 uvc_version;
544544
};
545545

546+
struct uvc_rect {
547+
u16 top;
548+
u16 left;
549+
u16 bottom;
550+
u16 right;
551+
} __packed;
552+
546553
struct uvc_status_streaming {
547554
u8 button;
548555
} __packed;

include/uapi/linux/usb/video.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f
105105
#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10
106106
#define UVC_CT_PRIVACY_CONTROL 0x11
107+
#define UVC_CT_REGION_OF_INTEREST_CONTROL 0x14
107108

108109
/* A.9.5. Processing Unit Control Selectors */
109110
#define UVC_PU_CONTROL_UNDEFINED 0x00

include/uapi/linux/uvcvideo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define UVC_CTRL_DATA_TYPE_BOOLEAN 3
1717
#define UVC_CTRL_DATA_TYPE_ENUM 4
1818
#define UVC_CTRL_DATA_TYPE_BITMASK 5
19+
#define UVC_CTRL_DATA_TYPE_RECT 6
1920

2021
/* Control flags */
2122
#define UVC_CTRL_FLAG_SET_CUR (1 << 0)
@@ -38,6 +39,18 @@
3839

3940
#define UVC_MENU_NAME_LEN 32
4041

42+
/* V4L2 driver-specific controls */
43+
#define V4L2_CID_UVC_REGION_OF_INTEREST_RECT (V4L2_CID_USER_UVC_BASE + 1)
44+
#define V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (V4L2_CID_USER_UVC_BASE + 2)
45+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE (1 << 0)
46+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS (1 << 1)
47+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE (1 << 2)
48+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS (1 << 3)
49+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT (1 << 4)
50+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK (1 << 5)
51+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION (1 << 6)
52+
#define V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY (1 << 7)
53+
4154
struct uvc_menu_info {
4255
__u32 value;
4356
__u8 name[UVC_MENU_NAME_LEN];

include/uapi/linux/v4l2-controls.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ enum v4l2_colorfx {
215215
*/
216216
#define V4L2_CID_USER_THP7312_BASE (V4L2_CID_USER_BASE + 0x11c0)
217217

218+
/*
219+
* The base for the uvc driver controls.
220+
* See linux/uvcvideo.h for the list of controls.
221+
* We reserve 64 controls for this driver.
222+
*/
223+
#define V4L2_CID_USER_UVC_BASE (V4L2_CID_USER_BASE + 0x11e0)
224+
218225
/* MPEG-class control IDs */
219226
/* The MPEG controls are applicable to all codec controls
220227
* and the 'MPEG' part of the define is historical */

0 commit comments

Comments
 (0)