* [PATCH v9 01/11] media: v4l2_ctrl: Add V4L2_CTRL_TYPE_RECT
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
` (9 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Add p_rect to struct v4l2_ext_control with basic support in
v4l2-ctrls.
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- No change.
Changelog since v7:
- Document V4L2_CTRL_TYPE_RECT in vidioc-queryctrl.rst.
- Rebased to media-stage master.
- Do not assign each field in std_equal.
.../media/v4l/vidioc-g-ext-ctrls.rst | 4 ++++
.../userspace-api/media/v4l/vidioc-queryctrl.rst | 7 +++++++
.../media/videodev2.h.rst.exceptions | 1 +
drivers/media/v4l2-core/v4l2-ctrls-core.c | 15 +++++++++++++++
include/media/v4l2-ctrls.h | 2 ++
include/uapi/linux/videodev2.h | 2 ++
6 files changed, 31 insertions(+)
diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
index 892cfeb8b988..927ef397f1ce 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
@@ -189,6 +189,10 @@ still cause this situation.
- ``p_area``
- A pointer to a struct :c:type:`v4l2_area`. Valid if this control is
of type ``V4L2_CTRL_TYPE_AREA``.
+ * - struct :c:type:`v4l2_rect` *
+ - ``p_rect``
+ - A pointer to a struct :c:type:`v4l2_rect`. Valid if this control is
+ of type ``V4L2_CTRL_TYPE_RECT``.
* - struct :c:type:`v4l2_ctrl_h264_sps` *
- ``p_h264_sps``
- A pointer to a struct :c:type:`v4l2_ctrl_h264_sps`. Valid if this control is
diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
index a20dfa2a933b..58982cd382e3 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
@@ -441,6 +441,13 @@ See also the examples in :ref:`control`.
- n/a
- A struct :c:type:`v4l2_area`, containing the width and the height
of a rectangular area. Units depend on the use case.
+ * - ``V4L2_CTRL_TYPE_RECT``
+ - n/a
+ - n/a
+ - n/a
+ - A struct :c:type:`v4l2_rect`, containing a rectangle described by
+ the position of its top-left corner, the width and the height. Units
+ depend on the use case.
* - ``V4L2_CTRL_TYPE_H264_SPS``
- n/a
- n/a
diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
index 2a589d34b80e..828cca8e2daa 100644
--- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions
+++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
@@ -150,6 +150,7 @@ replace symbol V4L2_CTRL_TYPE_HEVC_SPS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type`
+replace symbol V4L2_CTRL_TYPE_RECT :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_FWHT_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_VP8_FRAME :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR :c:type:`v4l2_ctrl_type`
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 0dab1d7b90f0..0ac36ebc45dd 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -350,6 +350,11 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)
case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS:
pr_cont("HEVC_DECODE_PARAMS");
break;
+ case V4L2_CTRL_TYPE_RECT:
+ pr_cont("%ux%u@%dx%d",
+ ptr.p_rect->width, ptr.p_rect->height,
+ ptr.p_rect->left, ptr.p_rect->top);
+ break;
default:
pr_cont("unknown type %d", ctrl->type);
break;
@@ -569,6 +574,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;
struct v4l2_ctrl_hevc_decode_params *p_hevc_decode_params;
struct v4l2_area *area;
+ struct v4l2_rect *rect;
void *p = ptr.p + idx * ctrl->elem_size;
unsigned int i;
@@ -918,6 +924,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
return -EINVAL;
break;
+ case V4L2_CTRL_TYPE_RECT:
+ rect = p;
+ if (!rect->width || !rect->height)
+ return -EINVAL;
+ break;
+
default:
return -EINVAL;
}
@@ -1605,6 +1617,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
case V4L2_CTRL_TYPE_AREA:
elem_size = sizeof(struct v4l2_area);
break;
+ case V4L2_CTRL_TYPE_RECT:
+ elem_size = sizeof(struct v4l2_rect);
+ break;
default:
if (type < V4L2_CTRL_COMPOUND_TYPES)
elem_size = sizeof(s32);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index e59d9a234631..1846caf9dd53 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -52,6 +52,7 @@ struct video_device;
* @p_hdr10_cll: Pointer to an HDR10 Content Light Level structure.
* @p_hdr10_mastering: Pointer to an HDR10 Mastering Display structure.
* @p_area: Pointer to an area.
+ * @p_rect: Pointer to a rectangle.
* @p: Pointer to a compound value.
* @p_const: Pointer to a constant compound value.
*/
@@ -81,6 +82,7 @@ union v4l2_ctrl_ptr {
struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll;
struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;
struct v4l2_area *p_area;
+ struct v4l2_rect *p_rect;
void *p;
const void *p_const;
};
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 86cae23cc446..a81951c51325 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1780,6 +1780,7 @@ struct v4l2_ext_control {
__u16 __user *p_u16;
__u32 __user *p_u32;
struct v4l2_area __user *p_area;
+ struct v4l2_rect __user *p_rect;
struct v4l2_ctrl_h264_sps __user *p_h264_sps;
struct v4l2_ctrl_h264_pps *p_h264_pps;
struct v4l2_ctrl_h264_scaling_matrix __user *p_h264_scaling_matrix;
@@ -1844,6 +1845,7 @@ enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_U16 = 0x0101,
V4L2_CTRL_TYPE_U32 = 0x0102,
V4L2_CTRL_TYPE_AREA = 0x0106,
+ V4L2_CTRL_TYPE_RECT = 0x0107,
V4L2_CTRL_TYPE_HDR10_CLL_INFO = 0x0110,
V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY = 0x0111,
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
2022-10-25 5:55 ` [PATCH v9 01/11] media: v4l2_ctrl: Add V4L2_CTRL_TYPE_RECT Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 9:26 ` kernel test robot
` (3 more replies)
2022-10-25 5:55 ` [PATCH v9 03/11] media: uvcvideo: introduce __uvc_ctrl_get_std() Yunke Cao
` (8 subsequent siblings)
10 siblings, 4 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Introduce uvc_ctrl_get_boundary(), making it easier to extend to
support compound controls and V4L2_CTRL_WHICH_MIN/MAX_VAL in the
following patches.
For now, it simply returns EINVAL for compound controls and calls
__query_v4l2_ctrl() for non-compound controls.
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- No Change.
Changelog since v7:
- Rename uvc_ctrl_get_fixed() to uvc_ctrl_get_boundary().
- Move refactor (introduce __uvc_ctrl_get_boundary_std()) in this patch
instead of in the patch where we implement compound control.
- Fix locking. uvc_ctrl_get_boundary() now acquires ctrl_mutex.
__uvc_ctrl_get_boundary_std() calls __uvc_query_v4l2_ctrl() while
holding the mutex.
- Define a uvc_ctrl_mapping_is_compound() for readability.
drivers/media/usb/uvc/uvc_ctrl.c | 48 ++++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvc_v4l2.c | 6 +---
drivers/media/usb/uvc/uvcvideo.h | 2 ++
3 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index c95a2229f4fa..6997e7466a2b 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -837,6 +837,12 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping,
}
}
+static bool
+uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping)
+{
+ return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES;
+}
+
/* ------------------------------------------------------------------------
* Terminal and unit management
*/
@@ -1743,6 +1749,48 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
}
+int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ struct v4l2_ext_control *xctrl)
+{
+ struct v4l2_queryctrl qc = { .id = xctrl->id };
+
+ int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc);
+
+ if (ret < 0)
+ return ret;
+
+ xctrl->value = qc.default_value;
+ return 0;
+}
+
+int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
+ struct v4l2_ext_control *xctrl)
+{
+ struct uvc_control *ctrl;
+ struct uvc_control_mapping *mapping;
+ int ret;
+
+ if (mutex_lock_interruptible(&chain->ctrl_mutex))
+ return -ERESTARTSYS;
+
+ ctrl = uvc_find_control(chain, xctrl->id, &mapping);
+ if (!ctrl) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (uvc_ctrl_mapping_is_compound(mapping))
+ ret = -EINVAL;
+ else
+ ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl);
+
+done:
+ mutex_unlock(&chain->ctrl_mutex);
+ return ret;
+}
+
int uvc_ctrl_set(struct uvc_fh *handle,
struct v4l2_ext_control *xctrl)
{
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index f4d4c33b6dfb..e807e348aa41 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1046,15 +1046,11 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
- struct v4l2_queryctrl qc = { .id = ctrl->id };
-
- ret = uvc_query_v4l2_ctrl(chain, &qc);
+ ret = uvc_ctrl_get_boundary(chain, ctrl);
if (ret < 0) {
ctrls->error_idx = i;
return ret;
}
-
- ctrl->value = qc.default_value;
}
return 0;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index df93db259312..b2ee3d59a4c8 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -759,6 +759,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
}
int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl);
+int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
+ struct v4l2_ext_control *xctrl);
int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl);
int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
bool read);
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
@ 2022-10-25 9:26 ` kernel test robot
2022-10-25 9:58 ` Sergey Senozhatsky
` (2 subsequent siblings)
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 9:26 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 2561 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-3-yunkec%40google.com
patch subject: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
config: m68k-allyesconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/3a37413c0b49718560da555fa58b7278de10202d
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 3a37413c0b49718560da555fa58b7278de10202d
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> drivers/media/usb/uvc/uvc_ctrl.c:1752:5: warning: no previous prototype for '__uvc_ctrl_get_boundary_std' [-Wmissing-prototypes]
1752 | int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +/__uvc_ctrl_get_boundary_std +1752 drivers/media/usb/uvc/uvc_ctrl.c
1751
> 1752 int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
1753 struct uvc_control *ctrl,
1754 struct uvc_control_mapping *mapping,
1755 struct v4l2_ext_control *xctrl)
1756 {
1757 struct v4l2_queryctrl qc = { .id = xctrl->id };
1758
1759 int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc);
1760
1761 if (ret < 0)
1762 return ret;
1763
1764 xctrl->value = qc.default_value;
1765 return 0;
1766 }
1767
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66132 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
2022-10-25 9:26 ` kernel test robot
@ 2022-10-25 9:58 ` Sergey Senozhatsky
2022-10-25 10:51 ` Yunke Cao
2022-10-25 13:14 ` kernel test robot
2022-10-25 17:08 ` kernel test robot
3 siblings, 1 reply; 21+ messages in thread
From: Sergey Senozhatsky @ 2022-10-25 9:58 UTC (permalink / raw)
To: Yunke Cao
Cc: Hans Verkuil, Laurent Pinchart, Nicolas Dufresne,
Mauro Carvalho Chehab, Tomasz Figa, Sergey Senozhatsky,
Ricardo Ribalda, linux-media
On (22/10/25 14:55), Yunke Cao wrote:
>
> +int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
> + struct uvc_control *ctrl,
> + struct uvc_control_mapping *mapping,
> + struct v4l2_ext_control *xctrl)
This should be static, as far as I can tell.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 9:58 ` Sergey Senozhatsky
@ 2022-10-25 10:51 ` Yunke Cao
0 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 10:51 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Hans Verkuil, Laurent Pinchart, Nicolas Dufresne,
Mauro Carvalho Chehab, Tomasz Figa, Ricardo Ribalda, linux-media
On Tue, Oct 25, 2022 at 6:58 PM Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> On (22/10/25 14:55), Yunke Cao wrote:
> >
> > +int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
> > + struct uvc_control *ctrl,
> > + struct uvc_control_mapping *mapping,
> > + struct v4l2_ext_control *xctrl)
>
> This should be static, as far as I can tell.
Ah, thanks!
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
2022-10-25 9:26 ` kernel test robot
2022-10-25 9:58 ` Sergey Senozhatsky
@ 2022-10-25 13:14 ` kernel test robot
2022-10-25 17:08 ` kernel test robot
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 13:14 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: llvm, oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 9503 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-3-yunkec%40google.com
patch subject: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
config: riscv-randconfig-r042-20221025 (attached as .config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/3a37413c0b49718560da555fa58b7278de10202d
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 3a37413c0b49718560da555fa58b7278de10202d
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:743:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insb(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:104:53: note: expanded from macro 'insb'
#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:751:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insw(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:105:53: note: expanded from macro 'insw'
#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:759:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insl(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:106:53: note: expanded from macro 'insl'
#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:768:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsb(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:118:55: note: expanded from macro 'outsb'
#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:777:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsw(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:119:55: note: expanded from macro 'outsw'
#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:786:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsl(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:120:55: note: expanded from macro 'outsl'
#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:1134:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
~~~~~~~~~~ ^
>> drivers/media/usb/uvc/uvc_ctrl.c:1752:5: warning: no previous prototype for function '__uvc_ctrl_get_boundary_std' [-Wmissing-prototypes]
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
^
drivers/media/usb/uvc/uvc_ctrl.c:1752:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
^
static
14 warnings generated.
vim +/__uvc_ctrl_get_boundary_std +1752 drivers/media/usb/uvc/uvc_ctrl.c
1751
> 1752 int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
1753 struct uvc_control *ctrl,
1754 struct uvc_control_mapping *mapping,
1755 struct v4l2_ext_control *xctrl)
1756 {
1757 struct v4l2_queryctrl qc = { .id = xctrl->id };
1758
1759 int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc);
1760
1761 if (ret < 0)
1762 return ret;
1763
1764 xctrl->value = qc.default_value;
1765 return 0;
1766 }
1767
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38469 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
` (2 preceding siblings ...)
2022-10-25 13:14 ` kernel test robot
@ 2022-10-25 17:08 ` kernel test robot
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 17:08 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 1812 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-3-yunkec%40google.com
patch subject: [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value
config: i386-randconfig-s003 (attached as .config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/3a37413c0b49718560da555fa58b7278de10202d
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 3a37413c0b49718560da555fa58b7278de10202d
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> drivers/media/usb/uvc/uvc_ctrl.c:1752:5: sparse: sparse: symbol '__uvc_ctrl_get_boundary_std' was not declared. Should it be static?
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 39146 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v9 03/11] media: uvcvideo: introduce __uvc_ctrl_get_std()
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
2022-10-25 5:55 ` [PATCH v9 01/11] media: v4l2_ctrl: Add V4L2_CTRL_TYPE_RECT Yunke Cao
2022-10-25 5:55 ` [PATCH v9 02/11] media: uvcvideo: add uvc_ctrl_get_boundary for getting default value Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 04/11] media: uvcvideo: Split uvc_control_mapping.size to v4l2 and data size Yunke Cao
` (7 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Refactor uvc_ctrl to make adding compound control easier.
Currently uvc_ctrl_get() only work for non-compound controls.
Move the logic into uvc_ctrl_std(), return error for compound
controls.
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- No change.
Changelog since v7:
- Newly added patch. Split the refactoring of uvc_ctrl_get from v7 3/7.
drivers/media/usb/uvc/uvc_ctrl.c | 40 +++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 6997e7466a2b..40c5d01364d9 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1028,15 +1028,15 @@ static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
return ret;
}
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
- struct uvc_control *ctrl,
- struct uvc_control_mapping *mapping,
- s32 *value)
+static int __uvc_ctrl_get_std(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ s32 *value)
{
int ret;
- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
- return -EACCES;
+ if (uvc_ctrl_mapping_is_compound(mapping))
+ return -EINVAL;
ret = __uvc_ctrl_load_cur(chain, ctrl);
if (ret < 0)
@@ -1153,8 +1153,13 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
__uvc_find_control(ctrl->entity, mapping->master_id,
&master_map, &master_ctrl, 0);
if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
- s32 val;
- int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
+ s32 val = 0;
+ int ret;
+
+ if (uvc_ctrl_mapping_is_compound(master_map))
+ return -EINVAL;
+
+ ret = __uvc_ctrl_get_std(chain, master_ctrl, master_map, &val);
if (ret < 0)
return ret;
@@ -1399,7 +1404,8 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain,
if (ctrl == NULL)
return;
- if (__uvc_ctrl_get(chain, ctrl, mapping, &val) == 0)
+ if (uvc_ctrl_mapping_is_compound(mapping) ||
+ __uvc_ctrl_get_std(chain, ctrl, mapping, &val) == 0)
changes |= V4L2_EVENT_CTRL_CH_VALUE;
uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes);
@@ -1566,7 +1572,8 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
s32 val = 0;
- if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+ if (uvc_ctrl_mapping_is_compound(mapping) ||
+ __uvc_ctrl_get_std(handle->chain, ctrl, mapping, &val) == 0)
changes |= V4L2_EVENT_CTRL_CH_VALUE;
uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
@@ -1746,7 +1753,10 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
if (ctrl == NULL)
return -EINVAL;
- return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
+ if (uvc_ctrl_mapping_is_compound(mapping))
+ return -EINVAL;
+ else
+ return __uvc_ctrl_get_std(chain, ctrl, mapping, &xctrl->value);
}
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
@@ -1892,8 +1902,12 @@ int uvc_ctrl_set(struct uvc_fh *handle,
ctrl->info.size);
}
- mapping->set(mapping, value,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+ if (!uvc_ctrl_mapping_is_compound(mapping))
+ mapping->set(mapping, value,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+ else
+ return -EINVAL;
+
if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
ctrl->handle = handle;
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 04/11] media: uvcvideo: Split uvc_control_mapping.size to v4l2 and data size
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (2 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 03/11] media: uvcvideo: introduce __uvc_ctrl_get_std() Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
` (6 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Rename the existing size to data_size to represent uvc control data size,
add a separate field for v4l2 control size. v4l2 control size will be
used the compound controls.
Also modify the uvc driver documents to clarify the size in
uvc_xu_control_mapping corresponds to the uvc control data size.
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- Newly added patch.
Changelog since v7:
- Newly added patch.
.../userspace-api/media/drivers/uvcvideo.rst | 2 +-
drivers/media/usb/uvc/uvc_ctrl.c | 78 +++++++++----------
drivers/media/usb/uvc/uvc_driver.c | 2 +-
drivers/media/usb/uvc/uvc_v4l2.c | 2 +-
drivers/media/usb/uvc/uvcvideo.h | 6 +-
5 files changed, 47 insertions(+), 43 deletions(-)
diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst
index a290f9fadae9..aab4304e6bb5 100644
--- a/Documentation/userspace-api/media/drivers/uvcvideo.rst
+++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst
@@ -157,7 +157,7 @@ Argument: struct uvc_xu_control_mapping
__u8 name[32] V4L2 control name
__u8 entity[16] UVC extension unit GUID
__u8 selector UVC control selector
- __u8 size V4L2 control size (in bits)
+ __u8 size UVC control data size (in bits)
__u8 offset V4L2 control offset (in bits)
enum v4l2_ctrl_type
v4l2_type V4L2 control type
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 40c5d01364d9..020303e2593b 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -436,7 +436,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_BRIGHTNESS,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_BRIGHTNESS_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -445,7 +445,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_CONTRAST,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_CONTRAST_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -454,7 +454,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_HUE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_HUE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -465,7 +465,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_SATURATION,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_SATURATION_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -474,7 +474,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_SHARPNESS,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_SHARPNESS_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -483,7 +483,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_GAMMA,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_GAMMA_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -492,7 +492,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_BACKLIGHT_COMPENSATION,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -501,7 +501,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_GAIN,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_GAIN_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -510,7 +510,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_HUE_AUTO,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_HUE_AUTO_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -520,7 +520,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_EXPOSURE_AUTO,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_AE_MODE_CONTROL,
- .size = 4,
+ .data_size = 4,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_MENU,
.data_type = UVC_CTRL_DATA_TYPE_BITMASK,
@@ -532,7 +532,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_AE_PRIORITY_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -541,7 +541,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_EXPOSURE_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
- .size = 32,
+ .data_size = 32,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -552,7 +552,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_AUTO_WHITE_BALANCE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -562,7 +562,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -573,7 +573,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_AUTO_WHITE_BALANCE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -584,7 +584,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_BLUE_BALANCE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -595,7 +595,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_RED_BALANCE,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 16,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -606,7 +606,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_FOCUS_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -617,7 +617,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_FOCUS_AUTO,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_FOCUS_AUTO_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -627,7 +627,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_IRIS_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_IRIS_ABSOLUTE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -636,7 +636,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_IRIS_RELATIVE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_IRIS_RELATIVE_CONTROL,
- .size = 8,
+ .data_size = 8,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -645,7 +645,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_ZOOM_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
@@ -654,7 +654,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_ZOOM_CONTINUOUS,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_ZOOM_RELATIVE_CONTROL,
- .size = 0,
+ .data_size = 0,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -665,7 +665,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_PAN_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
- .size = 32,
+ .data_size = 32,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -674,7 +674,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_TILT_ABSOLUTE,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
- .size = 32,
+ .data_size = 32,
.offset = 32,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -683,7 +683,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_PAN_SPEED,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_PANTILT_RELATIVE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -694,7 +694,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_TILT_SPEED,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_PANTILT_RELATIVE_CONTROL,
- .size = 16,
+ .data_size = 16,
.offset = 16,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
@@ -705,7 +705,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_PRIVACY,
.entity = UVC_GUID_UVC_CAMERA,
.selector = UVC_CT_PRIVACY_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -714,7 +714,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.id = V4L2_CID_PRIVACY,
.entity = UVC_GUID_EXT_GPIO_CONTROLLER,
.selector = UVC_CT_PRIVACY_CONTROL,
- .size = 1,
+ .data_size = 1,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
@@ -726,7 +726,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc11[] = {
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
- .size = 2,
+ .data_size = 2,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_MENU,
.data_type = UVC_CTRL_DATA_TYPE_ENUM,
@@ -740,7 +740,7 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc15[] = {
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
- .size = 2,
+ .data_size = 2,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_MENU,
.data_type = UVC_CTRL_DATA_TYPE_ENUM,
@@ -769,7 +769,7 @@ static inline void uvc_clear_bit(u8 *data, int bit)
}
/*
- * Extract the bit string specified by mapping->offset and mapping->size
+ * Extract the bit string specified by mapping->offset and mapping->data_size
* from the little-endian data stored at 'data' and return the result as
* a signed 32bit integer. Sign extension will be performed if the mapping
* references a signed data type.
@@ -777,7 +777,7 @@ static inline void uvc_clear_bit(u8 *data, int bit)
static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
u8 query, const u8 *data)
{
- int bits = mapping->size;
+ int bits = mapping->data_size;
int offset = mapping->offset;
s32 value = 0;
u8 mask;
@@ -800,19 +800,19 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
/* Sign-extend the value if needed. */
if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
- value |= -(value & (1 << (mapping->size - 1)));
+ value |= -(value & (1 << (mapping->data_size - 1)));
return value;
}
/*
- * Set the bit string specified by mapping->offset and mapping->size
+ * Set the bit string specified by mapping->offset and mapping->data_size
* in the little-endian data stored at 'data' to the value 'value'.
*/
static void uvc_set_le_value(struct uvc_control_mapping *mapping,
s32 value, u8 *data)
{
- int bits = mapping->size;
+ int bits = mapping->data_size;
int offset = mapping->offset;
u8 mask;
@@ -1889,7 +1889,7 @@ int uvc_ctrl_set(struct uvc_fh *handle,
* needs to be loaded from the device to perform the read-modify-write
* operation.
*/
- if ((ctrl->info.size * 8) != mapping->size) {
+ if ((ctrl->info.size * 8) != mapping->data_size) {
ret = __uvc_ctrl_load_cur(chain, ctrl);
if (ret < 0)
return ret;
@@ -2378,8 +2378,8 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
}
/* Validate the user-provided bit-size and offset */
- if (mapping->size > 32 ||
- mapping->offset + mapping->size > ctrl->info.size * 8) {
+ if (mapping->data_size > 32 ||
+ mapping->offset + mapping->data_size > ctrl->info.size * 8) {
ret = -EINVAL;
goto done;
}
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 215fb483efb0..06317843c486 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2382,7 +2382,7 @@ static const struct uvc_control_mapping uvc_ctrl_power_line_mapping_limited = {
.id = V4L2_CID_POWER_LINE_FREQUENCY,
.entity = UVC_GUID_UVC_PROCESSING,
.selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
- .size = 2,
+ .data_size = 2,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_MENU,
.data_type = UVC_CTRL_DATA_TYPE_ENUM,
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index e807e348aa41..36ff1d0d6edb 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -51,7 +51,7 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
}
memcpy(map->entity, xmap->entity, sizeof(map->entity));
map->selector = xmap->selector;
- map->size = xmap->size;
+ map->data_size = xmap->size;
map->offset = xmap->offset;
map->v4l2_type = xmap->v4l2_type;
map->data_type = xmap->data_type;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index b2ee3d59a4c8..8f7938205a63 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -111,7 +111,11 @@ struct uvc_control_mapping {
u8 entity[16];
u8 selector;
- u8 size;
+ /* Size of the v4l2 control. Required for compound controls. */
+ u8 v4l2_size;
+ /* UVC data size. Required for all controls. */
+ u8 data_size;
+
u8 offset;
enum v4l2_ctrl_type v4l2_type;
u32 data_type;
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (3 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 04/11] media: uvcvideo: Split uvc_control_mapping.size to v4l2 and data size Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 10:00 ` Sergey Senozhatsky
` (3 more replies)
2022-10-25 5:55 ` [PATCH v9 06/11] media: uvcvideo: implement UVC v1.5 ROI Yunke Cao
` (5 subsequent siblings)
10 siblings, 4 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Supports getting/setting current value.
Supports getting default value.
Handles V4L2_CTRL_FLAG_NEXT_COMPOUND.
Signed-off-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
---
Changelog since v8:
- No change.
Changelog since v7:
- Fixed comments styles, indentation and a few other style issues.
- Renamed uvc_g/set_array() to uvc_g/set_compound().
- Moved size check to __uvc_ctrl_add_mapping().
- After setting a new value, copy it back to user.
- In __uvc_ctrl_set_compound(), check size before allocating.
drivers/media/usb/uvc/uvc_ctrl.c | 184 ++++++++++++++++++++++++++++---
drivers/media/usb/uvc/uvcvideo.h | 4 +
2 files changed, 170 insertions(+), 18 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 020303e2593b..fcfaa1ee892d 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -837,6 +837,28 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping,
}
}
+/*
+ * Extract the byte array specified by mapping->offset and mapping->data_size
+ * stored at 'data' to the output array 'data_out'.
+ */
+static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data,
+ u8 *data_out)
+{
+ memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8);
+ return 0;
+}
+
+/*
+ * Copy the byte array 'data_in' to the destination specified by mapping->offset
+ * and mapping->data_size stored at 'data'.
+ */
+static int uvc_set_compound(struct uvc_control_mapping *mapping,
+ const u8 *data_in, u8 *data)
+{
+ memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8);
+ return 0;
+}
+
static bool
uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping)
{
@@ -859,7 +881,7 @@ static int uvc_entity_match_guid(const struct uvc_entity *entity,
static void __uvc_find_control(struct uvc_entity *entity, u32 v4l2_id,
struct uvc_control_mapping **mapping, struct uvc_control **control,
- int next)
+ int next, int next_compound)
{
struct uvc_control *ctrl;
struct uvc_control_mapping *map;
@@ -874,14 +896,17 @@ static void __uvc_find_control(struct uvc_entity *entity, u32 v4l2_id,
continue;
list_for_each_entry(map, &ctrl->info.mappings, list) {
- if ((map->id == v4l2_id) && !next) {
+ if (map->id == v4l2_id && !next && !next_compound) {
*control = ctrl;
*mapping = map;
return;
}
if ((*mapping == NULL || (*mapping)->id > map->id) &&
- (map->id > v4l2_id) && next) {
+ (map->id > v4l2_id) &&
+ ((!uvc_ctrl_mapping_is_compound(map) && next) ||
+ (uvc_ctrl_mapping_is_compound(map) &&
+ next_compound))) {
*control = ctrl;
*mapping = map;
}
@@ -895,6 +920,7 @@ static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
struct uvc_control *ctrl = NULL;
struct uvc_entity *entity;
int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
+ int next_compound = v4l2_id & V4L2_CTRL_FLAG_NEXT_COMPOUND;
*mapping = NULL;
@@ -903,12 +929,13 @@ static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
/* Find the control. */
list_for_each_entry(entity, &chain->entities, chain) {
- __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
- if (ctrl && !next)
+ __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next,
+ next_compound);
+ if (ctrl && !next && !next_compound)
return ctrl;
}
- if (ctrl == NULL && !next)
+ if (!ctrl && !next && !next_compound)
uvc_dbg(chain->dev, CONTROL, "Control 0x%08x not found\n",
v4l2_id);
@@ -1048,10 +1075,59 @@ static int __uvc_ctrl_get_std(struct uvc_video_chain *chain,
return 0;
}
+static int __uvc_ctrl_get_compound(struct uvc_control_mapping *mapping,
+ struct uvc_control *ctrl,
+ int id,
+ struct v4l2_ext_control *xctrl)
+{
+ u8 size;
+ u8 *data;
+ int ret;
+
+ size = mapping->v4l2_size / 8;
+ if (xctrl->size < size) {
+ xctrl->size = size;
+ return -ENOSPC;
+ }
+
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = mapping->get_compound(mapping, uvc_ctrl_data(ctrl, id), data);
+ if (ret < 0)
+ goto out;
+
+ ret = copy_to_user(xctrl->ptr, data, size) ? -EFAULT : 0;
+
+out:
+ kfree(data);
+ return ret;
+}
+
+static int __uvc_ctrl_get_compound_cur(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ struct v4l2_ext_control *xctrl)
+{
+ int ret;
+
+ if (!uvc_ctrl_mapping_is_compound(mapping))
+ return -EINVAL;
+
+ ret = __uvc_ctrl_load_cur(chain, ctrl);
+ if (ret < 0)
+ return ret;
+
+ return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT,
+ xctrl);
+}
+
static int __uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id,
u32 found_id)
{
bool find_next = req_id & V4L2_CTRL_FLAG_NEXT_CTRL;
+ bool find_next_compound = req_id & V4L2_CTRL_FLAG_NEXT_COMPOUND;
unsigned int i;
req_id &= V4L2_CTRL_ID_MASK;
@@ -1059,7 +1135,7 @@ static int __uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id,
for (i = 0; i < ARRAY_SIZE(uvc_control_classes); i++) {
if (!(chain->ctrl_class_bitmap & BIT(i)))
continue;
- if (!find_next) {
+ if (!find_next && !find_next_compound) {
if (uvc_control_classes[i] == req_id)
return i;
continue;
@@ -1151,7 +1227,7 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
if (mapping->master_id)
__uvc_find_control(ctrl->entity, mapping->master_id,
- &master_map, &master_ctrl, 0);
+ &master_map, &master_ctrl, 0, 0);
if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
s32 val = 0;
int ret;
@@ -1167,6 +1243,15 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
}
+ if (v4l2_ctrl->type >= V4L2_CTRL_COMPOUND_TYPES) {
+ v4l2_ctrl->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD;
+ v4l2_ctrl->default_value = 0;
+ v4l2_ctrl->minimum = 0;
+ v4l2_ctrl->maximum = 0;
+ v4l2_ctrl->step = 0;
+ return 0;
+ }
+
if (!ctrl->cached) {
int ret = uvc_ctrl_populate_cache(chain, ctrl);
if (ret < 0)
@@ -1400,7 +1485,7 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain,
u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
s32 val = 0;
- __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0);
+ __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0, 0);
if (ctrl == NULL)
return;
@@ -1706,7 +1791,7 @@ static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity,
for (i = 0; i < ctrls->count; i++) {
__uvc_find_control(entity, ctrls->controls[i].id, &mapping,
- &ctrl_found, 0);
+ &ctrl_found, 0, 0);
if (uvc_control == ctrl_found)
return i;
}
@@ -1754,7 +1839,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
return -EINVAL;
if (uvc_ctrl_mapping_is_compound(mapping))
- return -EINVAL;
+ return __uvc_ctrl_get_compound_cur(chain, ctrl, mapping, xctrl);
else
return __uvc_ctrl_get_std(chain, ctrl, mapping, &xctrl->value);
}
@@ -1775,6 +1860,25 @@ int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
return 0;
}
+static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ struct v4l2_ext_control *xctrl)
+{
+ int ret;
+
+ if (!uvc_ctrl_mapping_is_compound(mapping))
+ return -EINVAL;
+
+ if (!ctrl->cached) {
+ ret = uvc_ctrl_populate_cache(chain, ctrl);
+ if (ret < 0)
+ return ret;
+ }
+
+ return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_DEF, xctrl);
+}
+
int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
struct v4l2_ext_control *xctrl)
{
@@ -1792,7 +1896,8 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
}
if (uvc_ctrl_mapping_is_compound(mapping))
- ret = -EINVAL;
+ ret = __uvc_ctrl_get_boundary_compound(chain, ctrl, mapping,
+ xctrl);
else
ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl);
@@ -1801,6 +1906,34 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
return ret;
}
+int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
+ struct v4l2_ext_control *xctrl,
+ struct uvc_control *ctrl)
+{
+ u8 *data;
+ int ret;
+
+ if (xctrl->size != mapping->v4l2_size / 8)
+ return -EINVAL;
+
+ data = kmalloc(xctrl->size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = copy_from_user(data, xctrl->ptr, xctrl->size);
+ if (ret < 0)
+ goto out;
+
+ ret = mapping->set_compound(mapping, data,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+ __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT, xctrl);
+
+out:
+ kfree(data);
+ return ret;
+}
+
int uvc_ctrl_set(struct uvc_fh *handle,
struct v4l2_ext_control *xctrl)
{
@@ -1902,12 +2035,14 @@ int uvc_ctrl_set(struct uvc_fh *handle,
ctrl->info.size);
}
- if (!uvc_ctrl_mapping_is_compound(mapping))
+ if (!uvc_ctrl_mapping_is_compound(mapping)) {
mapping->set(mapping, value,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
- else
- return -EINVAL;
-
+ } else {
+ ret = __uvc_ctrl_set_compound(mapping, xctrl, ctrl);
+ if (ret < 0)
+ return ret;
+ }
if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
ctrl->handle = handle;
@@ -2307,10 +2442,23 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
return -ENOMEM;
}
- if (map->get == NULL)
+ if (uvc_ctrl_mapping_is_compound(map)) {
+ if (map->data_size != map->v4l2_size)
+ return -EINVAL;
+
+ /* Only supports byte-aligned data. */
+ if (WARN_ON(map->offset % 8 || map->data_size % 8))
+ return -EINVAL;
+ }
+
+ if (!map->get && !uvc_ctrl_mapping_is_compound(map))
map->get = uvc_get_le_value;
- if (map->set == NULL)
+ if (!map->set && !uvc_ctrl_mapping_is_compound(map))
map->set = uvc_set_le_value;
+ if (!map->get_compound && uvc_ctrl_mapping_is_compound(map))
+ map->get_compound = uvc_get_compound;
+ if (!map->set_compound && uvc_ctrl_mapping_is_compound(map))
+ map->set_compound = uvc_set_compound;
for (i = 0; i < ARRAY_SIZE(uvc_control_classes); i++) {
if (V4L2_CTRL_ID2WHICH(uvc_control_classes[i]) ==
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 8f7938205a63..1e1bccd3b2e5 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -129,8 +129,12 @@ struct uvc_control_mapping {
s32 (*get)(struct uvc_control_mapping *mapping, u8 query,
const u8 *data);
+ int (*get_compound)(struct uvc_control_mapping *mapping, const u8 *data,
+ u8 *data_out);
void (*set)(struct uvc_control_mapping *mapping, s32 value,
u8 *data);
+ int (*set_compound)(struct uvc_control_mapping *mapping, const u8 *data_in,
+ u8 *data);
};
struct uvc_control {
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
@ 2022-10-25 10:00 ` Sergey Senozhatsky
2022-10-25 10:16 ` kernel test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 21+ messages in thread
From: Sergey Senozhatsky @ 2022-10-25 10:00 UTC (permalink / raw)
To: Yunke Cao
Cc: Hans Verkuil, Laurent Pinchart, Nicolas Dufresne,
Mauro Carvalho Chehab, Tomasz Figa, Sergey Senozhatsky,
Ricardo Ribalda, linux-media
On (22/10/25 14:55), Yunke Cao wrote:
>
> +int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
> + struct v4l2_ext_control *xctrl,
> + struct uvc_control *ctrl)
> +{
Also should be static?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
2022-10-25 10:00 ` Sergey Senozhatsky
@ 2022-10-25 10:16 ` kernel test robot
2022-10-25 16:08 ` kernel test robot
2022-10-25 20:12 ` kernel test robot
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 10:16 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 4938 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-6-yunkec%40google.com
patch subject: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
config: m68k-allyesconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/732343da19acba5e984f7e545a40c08e40000fc3
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 732343da19acba5e984f7e545a40c08e40000fc3
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/media/usb/uvc/uvc_ctrl.c:1847:5: warning: no previous prototype for '__uvc_ctrl_get_boundary_std' [-Wmissing-prototypes]
1847 | int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/media/usb/uvc/uvc_ctrl.c:1909:5: warning: no previous prototype for '__uvc_ctrl_set_compound' [-Wmissing-prototypes]
1909 | int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
| ^~~~~~~~~~~~~~~~~~~~~~~
vim +/__uvc_ctrl_set_compound +1909 drivers/media/usb/uvc/uvc_ctrl.c
1846
> 1847 int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
1848 struct uvc_control *ctrl,
1849 struct uvc_control_mapping *mapping,
1850 struct v4l2_ext_control *xctrl)
1851 {
1852 struct v4l2_queryctrl qc = { .id = xctrl->id };
1853
1854 int ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &qc);
1855
1856 if (ret < 0)
1857 return ret;
1858
1859 xctrl->value = qc.default_value;
1860 return 0;
1861 }
1862
1863 static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain,
1864 struct uvc_control *ctrl,
1865 struct uvc_control_mapping *mapping,
1866 struct v4l2_ext_control *xctrl)
1867 {
1868 int ret;
1869
1870 if (!uvc_ctrl_mapping_is_compound(mapping))
1871 return -EINVAL;
1872
1873 if (!ctrl->cached) {
1874 ret = uvc_ctrl_populate_cache(chain, ctrl);
1875 if (ret < 0)
1876 return ret;
1877 }
1878
1879 return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_DEF, xctrl);
1880 }
1881
1882 int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
1883 struct v4l2_ext_control *xctrl)
1884 {
1885 struct uvc_control *ctrl;
1886 struct uvc_control_mapping *mapping;
1887 int ret;
1888
1889 if (mutex_lock_interruptible(&chain->ctrl_mutex))
1890 return -ERESTARTSYS;
1891
1892 ctrl = uvc_find_control(chain, xctrl->id, &mapping);
1893 if (!ctrl) {
1894 ret = -EINVAL;
1895 goto done;
1896 }
1897
1898 if (uvc_ctrl_mapping_is_compound(mapping))
1899 ret = __uvc_ctrl_get_boundary_compound(chain, ctrl, mapping,
1900 xctrl);
1901 else
1902 ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl);
1903
1904 done:
1905 mutex_unlock(&chain->ctrl_mutex);
1906 return ret;
1907 }
1908
> 1909 int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
1910 struct v4l2_ext_control *xctrl,
1911 struct uvc_control *ctrl)
1912 {
1913 u8 *data;
1914 int ret;
1915
1916 if (xctrl->size != mapping->v4l2_size / 8)
1917 return -EINVAL;
1918
1919 data = kmalloc(xctrl->size, GFP_KERNEL);
1920 if (!data)
1921 return -ENOMEM;
1922
1923 ret = copy_from_user(data, xctrl->ptr, xctrl->size);
1924 if (ret < 0)
1925 goto out;
1926
1927 ret = mapping->set_compound(mapping, data,
1928 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
1929
1930 __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT, xctrl);
1931
1932 out:
1933 kfree(data);
1934 return ret;
1935 }
1936
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66132 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
2022-10-25 10:00 ` Sergey Senozhatsky
2022-10-25 10:16 ` kernel test robot
@ 2022-10-25 16:08 ` kernel test robot
2022-10-25 20:12 ` kernel test robot
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 16:08 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: llvm, oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 9597 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-6-yunkec%40google.com
patch subject: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
config: riscv-randconfig-r042-20221025 (attached as .config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/732343da19acba5e984f7e545a40c08e40000fc3
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 732343da19acba5e984f7e545a40c08e40000fc3
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
include/asm-generic/io.h:743:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insb(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:104:53: note: expanded from macro 'insb'
#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:751:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insw(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:105:53: note: expanded from macro 'insw'
#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:759:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
insl(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:106:53: note: expanded from macro 'insl'
#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:768:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsb(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:118:55: note: expanded from macro 'outsb'
#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:777:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsw(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:119:55: note: expanded from macro 'outsw'
#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:786:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
outsl(addr, buffer, count);
^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/include/asm/io.h:120:55: note: expanded from macro 'outsl'
#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
~~~~~~~~~~ ^
In file included from drivers/media/usb/uvc/uvc_ctrl.c:14:
In file included from include/linux/usb.h:16:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/riscv/include/asm/io.h:136:
include/asm-generic/io.h:1134:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
~~~~~~~~~~ ^
drivers/media/usb/uvc/uvc_ctrl.c:1847:5: warning: no previous prototype for function '__uvc_ctrl_get_boundary_std' [-Wmissing-prototypes]
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
^
drivers/media/usb/uvc/uvc_ctrl.c:1847:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
^
static
>> drivers/media/usb/uvc/uvc_ctrl.c:1909:5: warning: no previous prototype for function '__uvc_ctrl_set_compound' [-Wmissing-prototypes]
int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
^
drivers/media/usb/uvc/uvc_ctrl.c:1909:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
^
static
15 warnings generated.
vim +/__uvc_ctrl_set_compound +1909 drivers/media/usb/uvc/uvc_ctrl.c
1908
> 1909 int __uvc_ctrl_set_compound(struct uvc_control_mapping *mapping,
1910 struct v4l2_ext_control *xctrl,
1911 struct uvc_control *ctrl)
1912 {
1913 u8 *data;
1914 int ret;
1915
1916 if (xctrl->size != mapping->v4l2_size / 8)
1917 return -EINVAL;
1918
1919 data = kmalloc(xctrl->size, GFP_KERNEL);
1920 if (!data)
1921 return -ENOMEM;
1922
1923 ret = copy_from_user(data, xctrl->ptr, xctrl->size);
1924 if (ret < 0)
1925 goto out;
1926
1927 ret = mapping->set_compound(mapping, data,
1928 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
1929
1930 __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_CURRENT, xctrl);
1931
1932 out:
1933 kfree(data);
1934 return ret;
1935 }
1936
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38469 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
` (2 preceding siblings ...)
2022-10-25 16:08 ` kernel test robot
@ 2022-10-25 20:12 ` kernel test robot
3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-10-25 20:12 UTC (permalink / raw)
To: Yunke Cao, Hans Verkuil, Laurent Pinchart
Cc: oe-kbuild-all, Nicolas Dufresne, Mauro Carvalho Chehab,
linux-media, Tomasz Figa, Sergey Senozhatsky, Ricardo Ribalda,
Yunke Cao
[-- Attachment #1: Type: text/plain, Size: 1926 bytes --]
Hi Yunke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on media-tree/master]
[also build test WARNING on linus/master v6.1-rc2 next-20221025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
base: git://linuxtv.org/media_tree.git master
patch link: https://lore.kernel.org/r/20221025055528.1117251-6-yunkec%40google.com
patch subject: [PATCH v9 05/11] media: uvcvideo: Add support for compound controls
config: i386-randconfig-s003 (attached as .config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/732343da19acba5e984f7e545a40c08e40000fc3
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Yunke-Cao/media-Implement-UVC-v1-5-ROI/20221025-135821
git checkout 732343da19acba5e984f7e545a40c08e40000fc3
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash drivers/media/usb/uvc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
drivers/media/usb/uvc/uvc_ctrl.c:1847:5: sparse: sparse: symbol '__uvc_ctrl_get_boundary_std' was not declared. Should it be static?
>> drivers/media/usb/uvc/uvc_ctrl.c:1909:5: sparse: sparse: symbol '__uvc_ctrl_set_compound' was not declared. Should it be static?
--
0-DAY CI Kernel Test Service
https://01.org/lkp
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 39146 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v9 06/11] media: uvcvideo: implement UVC v1.5 ROI
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (4 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 05/11] media: uvcvideo: Add support for compound controls Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 07/11] media: uvcvideo: initilaize ROI control to default value Yunke Cao
` (4 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
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.
Signed-off-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
---
Changelog since v8:
- No change.
Changelog since v7:
- Fix a few style issues.
- Only allow 4-byte aligned data.
- Add control names.
- Move initialization to 7/10.
Question:
- Is V4L2_CID_CAMERA_UVC_BASE defined correctly?
Should we use V4L2_CID_PRIVATE_BASE?
drivers/media/usb/uvc/uvc_ctrl.c | 111 +++++++++++++++++++++++++++--
drivers/media/usb/uvc/uvc_v4l2.c | 5 +-
drivers/media/usb/uvc/uvcvideo.h | 7 ++
include/uapi/linux/usb/video.h | 1 +
include/uapi/linux/uvcvideo.h | 13 ++++
include/uapi/linux/v4l2-controls.h | 9 +++
6 files changed, 140 insertions(+), 6 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index fcfaa1ee892d..3616505e22b4 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -356,6 +356,24 @@ static const struct uvc_control_info uvc_ctrls[] = {
.flags = UVC_CTRL_FLAG_GET_CUR
| UVC_CTRL_FLAG_AUTO_UPDATE,
},
+ /*
+ * UVC_CTRL_FLAG_AUTO_UPDATE is needed because the RoI may get updated
+ * by sensors.
+ * "This RoI should be the same as specified in most recent SET_CUR
+ * except in the case where the ‘Auto Detect and Track’ and/or
+ * ‘Image Stabilization’ bit have been set."
+ * 4.2.2.1.20 Digital Region of Interest (ROI) Control
+ */
+ {
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
+ .index = 21,
+ .size = 10,
+ .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+ | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
+ | UVC_CTRL_FLAG_GET_DEF
+ | UVC_CTRL_FLAG_AUTO_UPDATE,
+ },
};
static const u32 uvc_control_classes[] = {
@@ -431,6 +449,57 @@ static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping,
data[first+1] = min_t(int, abs(value), 0xff);
}
+static int uvc_to_v4l2_rect(struct v4l2_rect *v4l2_rect,
+ const struct uvc_rect *uvc_rect)
+{
+ if (uvc_rect->top < uvc_rect->bottom ||
+ uvc_rect->right < uvc_rect->left)
+ return -EINVAL;
+
+ v4l2_rect->top = uvc_rect->top;
+ v4l2_rect->left = uvc_rect->left;
+ v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1;
+ v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1;
+ return 0;
+}
+
+static int v4l2_to_uvc_rect(struct uvc_rect *uvc_rect,
+ const struct v4l2_rect *v4l2_rect)
+{
+ /* Safely converts s32 and u32 to u16. */
+ if (v4l2_rect->top > U16_MAX || v4l2_rect->top < 0 ||
+ v4l2_rect->left > U16_MAX || v4l2_rect->left < 0 ||
+ v4l2_rect->height > U16_MAX || v4l2_rect->height == 0 ||
+ v4l2_rect->width > U16_MAX || v4l2_rect->width == 0 ||
+ v4l2_rect->height + v4l2_rect->top - 1 > U16_MAX ||
+ v4l2_rect->width + v4l2_rect->left - 1 > U16_MAX)
+ return -ERANGE;
+
+ uvc_rect->top = v4l2_rect->top;
+ uvc_rect->left = v4l2_rect->left;
+ uvc_rect->bottom = v4l2_rect->height + v4l2_rect->top - 1;
+ uvc_rect->right = v4l2_rect->width + v4l2_rect->left - 1;
+ return 0;
+}
+
+static int uvc_get_compound_rect(struct uvc_control_mapping *mapping,
+ const u8 *data, u8 *data_out)
+{
+ struct uvc_rect *uvc_rect;
+
+ uvc_rect = (struct uvc_rect *)(data + mapping->offset / 8);
+ return uvc_to_v4l2_rect((struct v4l2_rect *)data_out, uvc_rect);
+}
+
+static int uvc_set_compound_rect(struct uvc_control_mapping *mapping,
+ const u8 *data_in, u8 *data)
+{
+ struct uvc_rect *uvc_rect;
+
+ uvc_rect = (struct uvc_rect *)(data + mapping->offset / 8);
+ return v4l2_to_uvc_rect(uvc_rect, (struct v4l2_rect *)data_in);
+}
+
static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
{
.id = V4L2_CID_BRIGHTNESS,
@@ -719,6 +788,29 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
},
+ {
+ .id = V4L2_CID_UVC_REGION_OF_INTEREST_RECT,
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
+ .v4l2_size = sizeof(struct v4l2_rect) * 8,
+ .data_size = sizeof(struct uvc_rect) * 8,
+ .offset = 0,
+ .v4l2_type = V4L2_CTRL_TYPE_RECT,
+ .data_type = UVC_CTRL_DATA_TYPE_RECT,
+ .get_compound = uvc_get_compound_rect,
+ .set_compound = uvc_set_compound_rect,
+ .name = "Region Of Interest Rectangle",
+ },
+ {
+ .id = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
+ .entity = UVC_GUID_UVC_CAMERA,
+ .selector = UVC_CT_REGION_OF_INTEREST_CONTROL,
+ .data_size = 16,
+ .offset = 64,
+ .v4l2_type = V4L2_CTRL_TYPE_BITMASK,
+ .data_type = UVC_CTRL_DATA_TYPE_BITMASK,
+ .name = "Region Of Interest Auto Controls",
+ },
};
static const struct uvc_control_mapping uvc_ctrl_mappings_uvc11[] = {
@@ -2443,12 +2535,21 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
}
if (uvc_ctrl_mapping_is_compound(map)) {
- if (map->data_size != map->v4l2_size)
- return -EINVAL;
+ switch (map->v4l2_type) {
+ case V4L2_CTRL_TYPE_RECT:
+ /* Only supports 4 bytes-aligned data. */
+ if (WARN_ON(map->offset % 32))
+ return -EINVAL;
+ break;
+ default:
+ if (WARN_ON(map->data_size != map->v4l2_size))
+ return -EINVAL;
+
+ /* Only supports byte-aligned data. */
+ if (WARN_ON(map->offset % 8 || map->data_size % 8))
+ return -EINVAL;
+ }
- /* Only supports byte-aligned data. */
- if (WARN_ON(map->offset % 8 || map->data_size % 8))
- return -EINVAL;
}
if (!map->get && !uvc_ctrl_mapping_is_compound(map))
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 36ff1d0d6edb..52a7dc9ad4b9 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1002,7 +1002,10 @@ static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh,
qec->step = qc.step;
qec->default_value = qc.default_value;
qec->flags = qc.flags;
- qec->elem_size = 4;
+ if (qc.type == V4L2_CTRL_TYPE_RECT)
+ qec->elem_size = sizeof(struct v4l2_rect);
+ else
+ qec->elem_size = 4;
qec->elems = 1;
qec->nr_of_dims = 0;
memset(qec->dims, 0, sizeof(qec->dims));
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 1e1bccd3b2e5..c47304a63a7d 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -291,6 +291,13 @@ struct uvc_streaming_header {
u8 bTriggerUsage;
};
+struct uvc_rect {
+ u16 top;
+ u16 left;
+ u16 bottom;
+ u16 right;
+} __packed;
+
enum uvc_buffer_state {
UVC_BUF_STATE_IDLE = 0,
UVC_BUF_STATE_QUEUED = 1,
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
index bfdae12cdacf..9076a444758a 100644
--- a/include/uapi/linux/usb/video.h
+++ b/include/uapi/linux/usb/video.h
@@ -104,6 +104,7 @@
#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f
#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10
#define UVC_CT_PRIVACY_CONTROL 0x11
+#define UVC_CT_REGION_OF_INTEREST_CONTROL 0x14
/* A.9.5. Processing Unit Control Selectors */
#define UVC_PU_CONTROL_UNDEFINED 0x00
diff --git a/include/uapi/linux/uvcvideo.h b/include/uapi/linux/uvcvideo.h
index 8288137387c0..ae5eaa14eca2 100644
--- a/include/uapi/linux/uvcvideo.h
+++ b/include/uapi/linux/uvcvideo.h
@@ -16,6 +16,7 @@
#define UVC_CTRL_DATA_TYPE_BOOLEAN 3
#define UVC_CTRL_DATA_TYPE_ENUM 4
#define UVC_CTRL_DATA_TYPE_BITMASK 5
+#define UVC_CTRL_DATA_TYPE_RECT 6
/* Control flags */
#define UVC_CTRL_FLAG_SET_CUR (1 << 0)
@@ -36,6 +37,18 @@
UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES | \
UVC_CTRL_FLAG_GET_DEF)
+/* V4L2 driver-specific controls */
+#define V4L2_CID_UVC_REGION_OF_INTEREST_RECT (V4L2_CID_CAMERA_UVC_BASE + 1)
+#define V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (V4L2_CID_CAMERA_UVC_BASE + 2)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE (1 << 0)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS (1 << 1)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE (1 << 2)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS (1 << 3)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT (1 << 4)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK (1 << 5)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION (1 << 6)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY (1 << 7)
+
struct uvc_menu_info {
__u32 value;
__u8 name[32];
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index b5e7d082b8ad..b3544355be8f 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1019,6 +1019,15 @@ enum v4l2_auto_focus_range {
#define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE+35)
+/* CAMERA-class private control IDs */
+
+/*
+ * The base for the uvc driver controls.
+ * See linux/uvcvideo.h for the list of controls.
+ * We reserve 64 controls for this driver.
+ */
+#define V4L2_CID_CAMERA_UVC_BASE (V4L2_CID_CAMERA_CLASS_BASE + 0x1000)
+
/* FM Modulator class control IDs */
#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900)
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 07/11] media: uvcvideo: initilaize ROI control to default value
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (5 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 06/11] media: uvcvideo: implement UVC v1.5 ROI Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 08/11] v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL Yunke Cao
` (3 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Add an init function to uvc_control_info. Use the function to
initialize ROI control to default value.
Also moves utility functions to the top of uvc_ctrl.c, above
the uvc_ctrls definition. uvc_ctrl_init_roi() calls uvc_ctrl_data()
and need to be declared before uvc_ctrls.
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- No change.
Changelog since v7:
- Newly added patch. Split initializing from the previous patch.
- Add an init operation to uvc_control_info and use it for ROI
initialization.
drivers/media/usb/uvc/uvc_ctrl.c | 272 ++++++++++++++++++-------------
drivers/media/usb/uvc/uvcvideo.h | 3 +
2 files changed, 159 insertions(+), 116 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 3616505e22b4..33199de7f1be 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -30,6 +30,157 @@
#define UVC_CTRL_DATA_DEF 5
#define UVC_CTRL_DATA_LAST 6
+/* ------------------------------------------------------------------------
+ * Utility functions
+ */
+
+static inline u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
+{
+ return ctrl->uvc_data + id * ctrl->info.size;
+}
+
+static inline int uvc_test_bit(const u8 *data, int bit)
+{
+ return (data[bit >> 3] >> (bit & 7)) & 1;
+}
+
+static inline void uvc_clear_bit(u8 *data, int bit)
+{
+ data[bit >> 3] &= ~(1 << (bit & 7));
+}
+
+/*
+ * Extract the bit string specified by mapping->offset and mapping->data_size
+ * from the little-endian data stored at 'data' and return the result as
+ * a signed 32bit integer. Sign extension will be performed if the mapping
+ * references a signed data type.
+ */
+static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
+ u8 query, const u8 *data)
+{
+ int bits = mapping->data_size;
+ int offset = mapping->offset;
+ s32 value = 0;
+ u8 mask;
+
+ data += offset / 8;
+ offset &= 7;
+ mask = ((1LL << bits) - 1) << offset;
+
+ while (1) {
+ u8 byte = *data & mask;
+
+ value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
+ bits -= 8 - (offset > 0 ? offset : 0);
+ if (bits <= 0)
+ break;
+
+ offset -= 8;
+ mask = (1 << bits) - 1;
+ data++;
+ }
+
+ /* Sign-extend the value if needed. */
+ if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
+ value |= -(value & (1 << (mapping->data_size - 1)));
+
+ return value;
+}
+
+/*
+ * Set the bit string specified by mapping->offset and mapping->data_size
+ * in the little-endian data stored at 'data' to the value 'value'.
+ */
+static void uvc_set_le_value(struct uvc_control_mapping *mapping,
+ s32 value, u8 *data)
+{
+ int bits = mapping->data_size;
+ int offset = mapping->offset;
+ u8 mask;
+
+ /*
+ * According to the v4l2 spec, writing any value to a button control
+ * should result in the action belonging to the button control being
+ * triggered. UVC devices however want to see a 1 written -> override
+ * value.
+ */
+ if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON)
+ value = -1;
+
+ data += offset / 8;
+ offset &= 7;
+
+ for (; bits > 0; data++) {
+ mask = ((1LL << bits) - 1) << offset;
+ *data = (*data & ~mask) | ((value << offset) & mask);
+ value >>= offset ? offset : 8;
+ bits -= 8 - offset;
+ offset = 0;
+ }
+}
+
+/*
+ * Extract the byte array specified by mapping->offset and mapping->data_size
+ * stored at 'data' to the output array 'data_out'.
+ */
+static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data,
+ u8 *data_out)
+{
+ memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8);
+ return 0;
+}
+
+/*
+ * Copy the byte array 'data_in' to the destination specified by mapping->offset
+ * and mapping->data_size stored at 'data'.
+ */
+static int uvc_set_compound(struct uvc_control_mapping *mapping,
+ const u8 *data_in, u8 *data)
+{
+ memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8);
+ return 0;
+}
+
+static bool
+uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping)
+{
+ return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES;
+}
+
+static int uvc_ctrl_init_roi(struct uvc_device *dev, struct uvc_control *ctrl)
+{
+ int ret;
+
+ ret = uvc_query_ctrl(dev, UVC_GET_DEF, ctrl->entity->id, dev->intfnum,
+ UVC_CT_REGION_OF_INTEREST_CONTROL,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
+ ctrl->info.size);
+ if (ret)
+ goto out;
+
+ /*
+ * Most firmwares have wrong GET_CUR configuration. E.g. it's
+ * below GET_MIN, or have rectangle coordinates mixed up. This
+ * causes problems sometimes, because we are unable to set
+ * auto-controls value without first setting ROI rectangle to
+ * valid configuration.
+ *
+ * We expect that default configuration is always correct and
+ * is within the GET_MIN / GET_MAX boundaries.
+ *
+ * Set current ROI configuration to GET_DEF, so that we will
+ * always have properly configured ROI.
+ */
+ ret = uvc_query_ctrl(dev, UVC_SET_CUR, 1, dev->intfnum,
+ UVC_CT_REGION_OF_INTEREST_CONTROL,
+ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
+ ctrl->info.size);
+out:
+ if (ret)
+ dev_err(&dev->udev->dev, "Failed to fixup ROI (%d).\n", ret);
+ return ret;
+}
+
/* ------------------------------------------------------------------------
* Controls
*/
@@ -373,6 +524,7 @@ static const struct uvc_control_info uvc_ctrls[] = {
| UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
| UVC_CTRL_FLAG_GET_DEF
| UVC_CTRL_FLAG_AUTO_UPDATE,
+ .init = uvc_ctrl_init_roi,
},
};
@@ -841,122 +993,6 @@ static const struct uvc_control_mapping uvc_ctrl_mappings_uvc15[] = {
},
};
-/* ------------------------------------------------------------------------
- * Utility functions
- */
-
-static inline u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
-{
- return ctrl->uvc_data + id * ctrl->info.size;
-}
-
-static inline int uvc_test_bit(const u8 *data, int bit)
-{
- return (data[bit >> 3] >> (bit & 7)) & 1;
-}
-
-static inline void uvc_clear_bit(u8 *data, int bit)
-{
- data[bit >> 3] &= ~(1 << (bit & 7));
-}
-
-/*
- * Extract the bit string specified by mapping->offset and mapping->data_size
- * from the little-endian data stored at 'data' and return the result as
- * a signed 32bit integer. Sign extension will be performed if the mapping
- * references a signed data type.
- */
-static s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
- u8 query, const u8 *data)
-{
- int bits = mapping->data_size;
- int offset = mapping->offset;
- s32 value = 0;
- u8 mask;
-
- data += offset / 8;
- offset &= 7;
- mask = ((1LL << bits) - 1) << offset;
-
- while (1) {
- u8 byte = *data & mask;
- value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
- bits -= 8 - (offset > 0 ? offset : 0);
- if (bits <= 0)
- break;
-
- offset -= 8;
- mask = (1 << bits) - 1;
- data++;
- }
-
- /* Sign-extend the value if needed. */
- if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
- value |= -(value & (1 << (mapping->data_size - 1)));
-
- return value;
-}
-
-/*
- * Set the bit string specified by mapping->offset and mapping->data_size
- * in the little-endian data stored at 'data' to the value 'value'.
- */
-static void uvc_set_le_value(struct uvc_control_mapping *mapping,
- s32 value, u8 *data)
-{
- int bits = mapping->data_size;
- int offset = mapping->offset;
- u8 mask;
-
- /*
- * According to the v4l2 spec, writing any value to a button control
- * should result in the action belonging to the button control being
- * triggered. UVC devices however want to see a 1 written -> override
- * value.
- */
- if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON)
- value = -1;
-
- data += offset / 8;
- offset &= 7;
-
- for (; bits > 0; data++) {
- mask = ((1LL << bits) - 1) << offset;
- *data = (*data & ~mask) | ((value << offset) & mask);
- value >>= offset ? offset : 8;
- bits -= 8 - offset;
- offset = 0;
- }
-}
-
-/*
- * Extract the byte array specified by mapping->offset and mapping->data_size
- * stored at 'data' to the output array 'data_out'.
- */
-static int uvc_get_compound(struct uvc_control_mapping *mapping, const u8 *data,
- u8 *data_out)
-{
- memcpy(data_out, data + mapping->offset / 8, mapping->data_size / 8);
- return 0;
-}
-
-/*
- * Copy the byte array 'data_in' to the destination specified by mapping->offset
- * and mapping->data_size stored at 'data'.
- */
-static int uvc_set_compound(struct uvc_control_mapping *mapping,
- const u8 *data_in, u8 *data)
-{
- memcpy(data + mapping->offset / 8, data_in, mapping->data_size / 8);
- return 0;
-}
-
-static bool
-uvc_ctrl_mapping_is_compound(const struct uvc_control_mapping *mapping)
-{
- return mapping->v4l2_type >= V4L2_CTRL_COMPOUND_TYPES;
-}
-
/* ------------------------------------------------------------------------
* Terminal and unit management
*/
@@ -2758,6 +2794,10 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
* GET_INFO on standard controls.
*/
uvc_ctrl_get_flags(chain->dev, ctrl, &ctrl->info);
+
+ if (info->init)
+ info->init(chain->dev, ctrl);
+
break;
}
}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index c47304a63a7d..c7d20333ca8a 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -86,6 +86,7 @@
struct gpio_desc;
struct sg_table;
struct uvc_device;
+struct uvc_control;
/*
* TODO: Put the most frequently accessed fields at the beginning of
@@ -100,6 +101,8 @@ struct uvc_control_info {
u16 size;
u32 flags;
+
+ int (*init)(struct uvc_device *dev, struct uvc_control *ctrl);
};
struct uvc_control_mapping {
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 08/11] v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (6 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 07/11] media: uvcvideo: initilaize ROI control to default value Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 09/11] media: v4l2: document the usage of min/max for V4L2_CTRL_TYPE_RECT Yunke Cao
` (2 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Add the capability of retrieving the min and max values of a
compound control.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- Return ENODATA when min/max is not implemented. Document this behavior.
- Created a shared helper function __v4l2_ctrl_type_op_init that takes "which"
as a parameter. Call it in def, min and max operations.
Changelog since v7:
- Document that the definition of the min/max are provided by compound controls
are defined in control documentation.
- Return error, instead of zeroed memory for v4l2_ctrl_ptr_create(NULL).
git am from https://lore.kernel.org/all/20191119113457.57833-3-hverkuil-cisco@xs4all.nl/
- Fixed some merge conflits.
- Fixed the build error in drivers/media/platform/qcom/venus.
.../media/v4l/vidioc-g-ext-ctrls.rst | 11 +-
.../media/videodev2.h.rst.exceptions | 2 +
drivers/media/i2c/imx214.c | 5 +-
.../media/platform/qcom/venus/venc_ctrls.c | 9 +-
drivers/media/v4l2-core/v4l2-ctrls-api.c | 57 +++++--
drivers/media/v4l2-core/v4l2-ctrls-core.c | 156 +++++++++++++++---
drivers/media/v4l2-core/v4l2-ioctl.c | 4 +-
include/media/v4l2-ctrls.h | 34 +++-
include/uapi/linux/videodev2.h | 2 +
9 files changed, 236 insertions(+), 44 deletions(-)
diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
index 927ef397f1ce..1cc21ee229aa 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
@@ -304,14 +304,21 @@ still cause this situation.
- Which value of the control to get/set/try.
* - :cspan:`2` ``V4L2_CTRL_WHICH_CUR_VAL`` will return the current value of
the control, ``V4L2_CTRL_WHICH_DEF_VAL`` will return the default
+ value of the control, ``V4L2_CTRL_WHICH_MIN_VAL`` will return the minimum
+ value of the control, ``V4L2_CTRL_WHICH_MAX_VAL`` will return the maximum
value of the control and ``V4L2_CTRL_WHICH_REQUEST_VAL`` indicates that
these controls have to be retrieved from a request or tried/set for
a request. In the latter case the ``request_fd`` field contains the
file descriptor of the request that should be used. If the device
does not support requests, then ``EACCES`` will be returned.
- When using ``V4L2_CTRL_WHICH_DEF_VAL`` be aware that you can only
- get the default value of the control, you cannot set or try it.
+ When using ``V4L2_CTRL_WHICH_DEF_VAL``, ``V4L2_CTRL_WHICH_MIN_VAL``
+ or ``V4L2_CTRL_WHICH_MAX_VAL`` be aware that you can only get the
+ default/minimum/maximum value of the control, you cannot set or try it.
+ The definition of minimum/maximum values for compound types are provided by
+ the control documentation. If the control documentation does not
+ document the meaning of minimum/maximum value, then it is not supported.
+ Querying its minmimum/maximum value will result in -ENODATA.
For backwards compatibility you can also use a control class here
(see :ref:`ctrl-class`). In that case all controls have to
diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
index 828cca8e2daa..6295b0fa5716 100644
--- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions
+++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
@@ -563,6 +563,8 @@ ignore define V4L2_CTRL_DRIVER_PRIV
ignore define V4L2_CTRL_MAX_DIMS
ignore define V4L2_CTRL_WHICH_CUR_VAL
ignore define V4L2_CTRL_WHICH_DEF_VAL
+ignore define V4L2_CTRL_WHICH_MIN_VAL
+ignore define V4L2_CTRL_WHICH_MAX_VAL
ignore define V4L2_CTRL_WHICH_REQUEST_VAL
ignore define V4L2_OUT_CAP_CUSTOM_TIMINGS
ignore define V4L2_CID_MAX_CTRLS
diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
index 710c9fb515fd..bd11bd8105aa 100644
--- a/drivers/media/i2c/imx214.c
+++ b/drivers/media/i2c/imx214.c
@@ -1037,7 +1037,10 @@ static int imx214_probe(struct i2c_client *client)
imx214->unit_size = v4l2_ctrl_new_std_compound(&imx214->ctrls,
NULL,
V4L2_CID_UNIT_CELL_SIZE,
- v4l2_ctrl_ptr_create((void *)&unit_size));
+ v4l2_ctrl_ptr_create((void *)&unit_size),
+ v4l2_ctrl_ptr_create(NULL),
+ v4l2_ctrl_ptr_create(NULL));
+
ret = imx214->ctrls.error;
if (ret) {
dev_err(&client->dev, "%s control init failed (%d)\n",
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index 7468e43800a9..28eca8f9d148 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -607,11 +607,16 @@ int venc_ctrl_init(struct venus_inst *inst)
v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_COLORIMETRY_HDR10_CLL_INFO,
- v4l2_ctrl_ptr_create(&p_hdr10_cll));
+ v4l2_ctrl_ptr_create(&p_hdr10_cll),
+ v4l2_ctrl_ptr_create(NULL),
+ v4l2_ctrl_ptr_create(NULL));
v4l2_ctrl_new_std_compound(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY,
- v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering));
+ v4l2_ctrl_ptr_create((void *)&p_hdr10_mastering),
+ v4l2_ctrl_ptr_create(NULL),
+ v4l2_ctrl_ptr_create(NULL));
+
v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c
index d0a3aa3806fb..3bfab11fe148 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
@@ -94,6 +94,34 @@ static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
return ptr_to_user(c, ctrl, ctrl->p_new);
}
+/* Helper function: copy the minimum control value back to the caller */
+static int min_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
+{
+ int idx, ret;
+
+ for (idx = 0; idx < ctrl->elems; idx++) {
+ ret = ctrl->type_ops->minimum(ctrl, idx, ctrl->p_new);
+ if (ret)
+ return ret;
+ }
+
+ return ptr_to_user(c, ctrl, ctrl->p_new);
+}
+
+/* Helper function: copy the maximum control value back to the caller */
+static int max_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
+{
+ int idx, ret;
+
+ for (idx = 0; idx < ctrl->elems; idx++) {
+ ret = ctrl->type_ops->maximum(ctrl, idx, ctrl->p_new);
+ if (ret)
+ return ret;
+ }
+
+ return ptr_to_user(c, ctrl, ctrl->p_new);
+}
+
/* Helper function: copy the caller-provider value as the new control value */
static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
{
@@ -228,8 +256,8 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
cs->error_idx = i;
if (cs->which &&
- cs->which != V4L2_CTRL_WHICH_DEF_VAL &&
- cs->which != V4L2_CTRL_WHICH_REQUEST_VAL &&
+ (cs->which < V4L2_CTRL_WHICH_DEF_VAL ||
+ cs->which > V4L2_CTRL_WHICH_MAX_VAL) &&
V4L2_CTRL_ID2WHICH(id) != cs->which) {
dprintk(vdev,
"invalid which 0x%x or control id 0x%x\n",
@@ -367,8 +395,8 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
*/
static int class_check(struct v4l2_ctrl_handler *hdl, u32 which)
{
- if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL ||
- which == V4L2_CTRL_WHICH_REQUEST_VAL)
+ if (which == 0 || (which >= V4L2_CTRL_WHICH_DEF_VAL &&
+ which <= V4L2_CTRL_WHICH_MAX_VAL))
return 0;
return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
}
@@ -388,10 +416,12 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl_helper *helpers = helper;
int ret;
int i, j;
- bool is_default, is_request;
+ bool is_default, is_request, is_min, is_max;
is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
+ is_min = (cs->which == V4L2_CTRL_WHICH_MIN_VAL);
+ is_max = (cs->which == V4L2_CTRL_WHICH_MAX_VAL);
cs->error_idx = cs->count;
cs->which = V4L2_CTRL_ID2WHICH(cs->which);
@@ -431,13 +461,14 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
/*
* g_volatile_ctrl will update the new control values.
- * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and
+ * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL,
+ * V4L2_CTRL_WHICH_MIN_VAL, V4L2_CTRL_WHICH_MAX_VAL and
* V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests
* it is v4l2_ctrl_request_complete() that copies the
* volatile controls at the time of request completion
* to the request, so you don't want to do that again.
*/
- if (!is_default && !is_request &&
+ if (!is_default && !is_request && !is_min && !is_max &&
((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
(master->has_volatiles && !is_cur_manual(master)))) {
for (j = 0; j < master->ncontrols; j++)
@@ -466,6 +497,10 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
ret = -ENOMEM;
else if (is_request && ref->p_req_valid)
ret = req_to_user(cs->controls + idx, ref);
+ else if (is_min)
+ ret = min_to_user(cs->controls + idx, ref->ctrl);
+ else if (is_max)
+ ret = max_to_user(cs->controls + idx, ref->ctrl);
else if (is_volatile)
ret = new_to_user(cs->controls + idx, ref->ctrl);
else
@@ -563,9 +598,11 @@ int try_set_ext_ctrls_common(struct v4l2_fh *fh,
cs->error_idx = cs->count;
- /* Default value cannot be changed */
- if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) {
- dprintk(vdev, "%s: cannot change default value\n",
+ /* Default/minimum/maximum values cannot be changed */
+ if (cs->which == V4L2_CTRL_WHICH_DEF_VAL ||
+ cs->which == V4L2_CTRL_WHICH_MIN_VAL ||
+ cs->which == V4L2_CTRL_WHICH_MAX_VAL) {
+ dprintk(vdev, "%s: cannot change default/min/max value\n",
video_device_node_name(vdev));
return -EINVAL;
}
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 0ac36ebc45dd..f8de0a974f16 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -177,29 +177,72 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
}
}
-void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
+static int std_min_compound(const struct v4l2_ctrl *ctrl, u32 idx,
union v4l2_ctrl_ptr ptr)
+{
+ void *p = ptr.p + idx * ctrl->elem_size;
+
+ if (!ctrl->p_min.p_const)
+ return -ENODATA;
+
+ memcpy(p, ctrl->p_min.p_const, ctrl->elem_size);
+ return 0;
+}
+
+static int std_max_compound(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ void *p = ptr.p + idx * ctrl->elem_size;
+
+ if (!ctrl->p_max.p_const)
+ return -ENODATA;
+
+ memcpy(p, ctrl->p_max.p_const, ctrl->elem_size);
+ return 0;
+}
+
+static int __v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
+ u32 which, union v4l2_ctrl_ptr ptr)
{
unsigned int i;
u32 tot_elems = ctrl->elems;
u32 elems = tot_elems - from_idx;
+ s64 value;
+ int ret;
if (from_idx >= tot_elems)
- return;
+ return -EINVAL;
+
+ switch (which) {
+ case V4L2_CTRL_WHICH_DEF_VAL:
+ value = ctrl->default_value;
+ break;
+ case V4L2_CTRL_WHICH_MAX_VAL:
+ value = ctrl->maximum;
+ break;
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ value = ctrl->minimum;
+ break;
+ default:
+ return -EINVAL;
+ }
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
+ if (which == V4L2_CTRL_WHICH_DEF_VAL)
+ value = ctrl->minimum;
+
for (i = from_idx; i < tot_elems; i++) {
unsigned int offset = i * ctrl->elem_size;
- memset(ptr.p_char + offset, ' ', ctrl->minimum);
- ptr.p_char[offset + ctrl->minimum] = '\0';
+ memset(ptr.p_char + offset, ' ', value);
+ ptr.p_char[offset + value] = '\0';
}
break;
case V4L2_CTRL_TYPE_INTEGER64:
- if (ctrl->default_value) {
+ if (value) {
for (i = from_idx; i < tot_elems; i++)
- ptr.p_s64[i] = ctrl->default_value;
+ ptr.p_s64[i] = value;
} else {
memset(ptr.p_s64 + from_idx, 0, elems * sizeof(s64));
}
@@ -209,9 +252,9 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_BITMASK:
case V4L2_CTRL_TYPE_BOOLEAN:
- if (ctrl->default_value) {
+ if (value) {
for (i = from_idx; i < tot_elems; i++)
- ptr.p_s32[i] = ctrl->default_value;
+ ptr.p_s32[i] = value;
} else {
memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32));
}
@@ -221,32 +264,69 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32));
break;
case V4L2_CTRL_TYPE_U8:
- memset(ptr.p_u8 + from_idx, ctrl->default_value, elems);
+ memset(ptr.p_u8 + from_idx, value, elems);
break;
case V4L2_CTRL_TYPE_U16:
- if (ctrl->default_value) {
+ if (value) {
for (i = from_idx; i < tot_elems; i++)
- ptr.p_u16[i] = ctrl->default_value;
+ ptr.p_u16[i] = value;
} else {
memset(ptr.p_u16 + from_idx, 0, elems * sizeof(u16));
}
break;
case V4L2_CTRL_TYPE_U32:
- if (ctrl->default_value) {
+ if (value) {
for (i = from_idx; i < tot_elems; i++)
- ptr.p_u32[i] = ctrl->default_value;
+ ptr.p_u32[i] = value;
} else {
memset(ptr.p_u32 + from_idx, 0, elems * sizeof(u32));
}
break;
default:
- for (i = from_idx; i < tot_elems; i++)
- std_init_compound(ctrl, i, ptr);
+ for (i = from_idx; i < tot_elems; i++) {
+ switch (which) {
+ case V4L2_CTRL_WHICH_DEF_VAL:
+ std_init_compound(ctrl, i, ptr);
+ break;
+ case V4L2_CTRL_WHICH_MAX_VAL:
+ ret = std_max_compound(ctrl, i, ptr);
+ if (ret)
+ return ret;
+ break;
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ ret = std_min_compound(ctrl, i, ptr);
+ if (ret)
+ return ret;
+ break;
+ }
+ }
break;
}
+
+ return 0;
+}
+
+void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ __v4l2_ctrl_type_op_init(ctrl, from_idx, V4L2_CTRL_WHICH_DEF_VAL, ptr);
}
EXPORT_SYMBOL(v4l2_ctrl_type_op_init);
+static int v4l2_ctrl_type_op_minimum(const struct v4l2_ctrl *ctrl, u32 from_idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ return __v4l2_ctrl_type_op_init(ctrl, from_idx,
+ V4L2_CTRL_WHICH_MIN_VAL, ptr);
+}
+
+static int v4l2_ctrl_type_op_maximum(const struct v4l2_ctrl *ctrl, u32 from_idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ return __v4l2_ctrl_type_op_init(ctrl, from_idx,
+ V4L2_CTRL_WHICH_MAX_VAL, ptr);
+}
+
void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)
{
union v4l2_ctrl_ptr ptr = ctrl->p_cur;
@@ -1043,6 +1123,8 @@ EXPORT_SYMBOL(v4l2_ctrl_type_op_validate);
static const struct v4l2_ctrl_type_ops std_type_ops = {
.equal = v4l2_ctrl_type_op_equal,
.init = v4l2_ctrl_type_op_init,
+ .minimum = v4l2_ctrl_type_op_minimum,
+ .maximum = v4l2_ctrl_type_op_maximum,
.log = v4l2_ctrl_type_op_log,
.validate = v4l2_ctrl_type_op_validate,
};
@@ -1514,7 +1596,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
s64 min, s64 max, u64 step, s64 def,
const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
u32 flags, const char * const *qmenu,
- const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def,
+ const s64 *qmenu_int,
+ const union v4l2_ctrl_ptr p_def,
+ const union v4l2_ctrl_ptr p_min,
+ const union v4l2_ctrl_ptr p_max,
void *priv)
{
struct v4l2_ctrl *ctrl;
@@ -1634,6 +1719,14 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -ERANGE);
return NULL;
}
+
+ if ((!p_def.p_const && p_min.p_const) ||
+ (p_min.p_const && !p_max.p_const) ||
+ (!p_min.p_const && p_max.p_const)) {
+ handler_set_err(hdl, -EINVAL);
+ return NULL;
+ }
+
err = check_range(type, min, max, step, def);
if (err) {
handler_set_err(hdl, err);
@@ -1675,6 +1768,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const)
sz_extra += elem_size;
+ if (type >= V4L2_CTRL_COMPOUND_TYPES && p_min.p_const)
+ sz_extra += elem_size * 2;
ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
if (ctrl == NULL) {
@@ -1740,6 +1835,14 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
memcpy(ctrl->p_def.p, p_def.p_const, elem_size);
}
+ if (type >= V4L2_CTRL_COMPOUND_TYPES &&
+ p_min.p_const && p_max.p_const) {
+ ctrl->p_min.p = ctrl->p_def.p + elem_size;
+ memcpy(ctrl->p_min.p, p_min.p_const, elem_size);
+ ctrl->p_max.p = ctrl->p_min.p + elem_size;
+ memcpy(ctrl->p_max.p, p_max.p_const, elem_size);
+ }
+
ctrl->type_ops->init(ctrl, 0, ctrl->p_cur);
cur_to_new(ctrl);
@@ -1790,7 +1893,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
type, min, max,
is_menu ? cfg->menu_skip_mask : step, def,
cfg->dims, cfg->elem_size,
- flags, qmenu, qmenu_int, cfg->p_def, priv);
+ flags, qmenu, qmenu_int, cfg->p_def, cfg->p_min,
+ cfg->p_max, priv);
if (ctrl)
ctrl->is_private = cfg->is_private;
return ctrl;
@@ -1815,7 +1919,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
}
return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
min, max, step, def, NULL, 0,
- flags, NULL, NULL, ptr_null, NULL);
+ flags, NULL, NULL, ptr_null, ptr_null,
+ ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std);
@@ -1848,7 +1953,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
}
return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
0, max, mask, def, NULL, 0,
- flags, qmenu, qmenu_int, ptr_null, NULL);
+ flags, qmenu, qmenu_int, ptr_null, ptr_null,
+ ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
@@ -1880,7 +1986,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
}
return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
0, max, mask, def, NULL, 0,
- flags, qmenu, NULL, ptr_null, NULL);
+ flags, qmenu, NULL, ptr_null, ptr_null,
+ ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
@@ -1888,7 +1995,9 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
/* Helper function for standard compound controls */
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id,
- const union v4l2_ctrl_ptr p_def)
+ const union v4l2_ctrl_ptr p_def,
+ const union v4l2_ctrl_ptr p_min,
+ const union v4l2_ctrl_ptr p_max)
{
const char *name;
enum v4l2_ctrl_type type;
@@ -1902,7 +2011,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
}
return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
min, max, step, def, NULL, 0,
- flags, NULL, NULL, p_def, NULL);
+ flags, NULL, NULL, p_def, p_min, p_max, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_compound);
@@ -1926,7 +2035,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
}
return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
0, max, 0, def, NULL, 0,
- flags, NULL, qmenu_int, ptr_null, NULL);
+ flags, NULL, qmenu_int, ptr_null, ptr_null,
+ ptr_null, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index fddba75d9074..5d49e6d71b64 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -893,7 +893,9 @@ static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl)
return false;
break;
case V4L2_CTRL_WHICH_DEF_VAL:
- /* Default value cannot be changed */
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ case V4L2_CTRL_WHICH_MAX_VAL:
+ /* Default, minimum or maximum value cannot be changed */
if (ioctl == VIDIOC_S_EXT_CTRLS ||
ioctl == VIDIOC_TRY_EXT_CTRLS) {
c->error_idx = c->count;
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 1846caf9dd53..6feeb18411e4 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -125,6 +125,8 @@ struct v4l2_ctrl_ops {
*
* @equal: return true if all ctrl->elems array elements are equal.
* @init: initialize the value for array elements from from_idx to ctrl->elems.
+ * @minimum: set the value to the minimum value of the control.
+ * @maximum: set the value to the maximum value of the control.
* @log: log the value.
* @validate: validate the value for ctrl->new_elems array elements.
* Return 0 on success and a negative value otherwise.
@@ -134,6 +136,10 @@ struct v4l2_ctrl_type_ops {
union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2);
void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx,
union v4l2_ctrl_ptr ptr);
+ int (*minimum)(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr);
+ int (*maximum)(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr);
void (*log)(const struct v4l2_ctrl *ctrl);
int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
};
@@ -239,6 +245,12 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* @p_def: The control's default value represented via a union which
* provides a standard way of accessing control types
* through a pointer (for compound controls only).
+ * @p_min: The control's minimum value represented via a union which
+ * provides a standard way of accessing control types
+ * through a pointer (for compound controls only).
+ * @p_max: The control's maximum value represented via a union which
+ * provides a standard way of accessing control types
+ * through a pointer (for compound controls only).
* @p_cur: The control's current value represented via a union which
* provides a standard way of accessing control types
* through a pointer.
@@ -298,6 +310,8 @@ struct v4l2_ctrl {
} cur;
union v4l2_ctrl_ptr p_def;
+ union v4l2_ctrl_ptr p_min;
+ union v4l2_ctrl_ptr p_max;
union v4l2_ctrl_ptr p_new;
union v4l2_ctrl_ptr p_cur;
};
@@ -417,6 +431,8 @@ struct v4l2_ctrl_handler {
* @step: The control's step value for non-menu controls.
* @def: The control's default value.
* @p_def: The control's default value for compound controls.
+ * @p_min: The control's minimum value for compound controls.
+ * @p_max: The control's maximum value for compound controls.
* @dims: The size of each dimension.
* @elem_size: The size in bytes of the control.
* @flags: The control's flags.
@@ -446,6 +462,8 @@ struct v4l2_ctrl_config {
u64 step;
s64 def;
union v4l2_ctrl_ptr p_def;
+ union v4l2_ctrl_ptr p_min;
+ union v4l2_ctrl_ptr p_max;
u32 dims[V4L2_CTRL_MAX_DIMS];
u32 elem_size;
u32 flags;
@@ -715,17 +733,23 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
* @ops: The control ops.
* @id: The control ID.
* @p_def: The control's default value.
+ * @p_min: The control's minimum value.
+ * @p_max: The control's maximum value.
*
- * Sames as v4l2_ctrl_new_std(), but with support to compound controls, thanks
- * to the @p_def field. Use v4l2_ctrl_ptr_create() to create @p_def from a
- * pointer. Use v4l2_ctrl_ptr_create(NULL) if the default value of the
- * compound control should be all zeroes.
+ * Same as v4l2_ctrl_new_std(), but with support to compound controls, thanks
+ * to the @p_def/min/max fields. Use v4l2_ctrl_ptr_create() to create
+ * @p_def/min/max from a pointer. Use v4l2_ctrl_ptr_create(NULL) if the
+ * default value of the compound control should be all zeroes. Use
+ * v4l2_ctrl_ptr_create(NULL) if the min/max value of the compound control
+ * is not defined, -ENODATA will be returned in this case.
*
*/
struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id,
- const union v4l2_ctrl_ptr p_def);
+ const union v4l2_ctrl_ptr p_def,
+ const union v4l2_ctrl_ptr p_min,
+ const union v4l2_ctrl_ptr p_max);
/**
* v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index a81951c51325..5f698b49c02e 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1827,6 +1827,8 @@ struct v4l2_ext_controls {
#define V4L2_CTRL_WHICH_CUR_VAL 0
#define V4L2_CTRL_WHICH_DEF_VAL 0x0f000000
#define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f010000
+#define V4L2_CTRL_WHICH_MIN_VAL 0x0f020000
+#define V4L2_CTRL_WHICH_MAX_VAL 0x0f030000
enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_INTEGER = 1,
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 09/11] media: v4l2: document the usage of min/max for V4L2_CTRL_TYPE_RECT
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (7 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 08/11] v4l2-ctrls: add support for V4L2_CTRL_WHICH_MIN/MAX_VAL Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 10/11] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL Yunke Cao
2022-10-25 5:55 ` [PATCH v9 11/11] media: uvcvideo: document UVC v1.5 ROI Yunke Cao
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Document the default implementation of min/max for rectangle controls.
Signed-off-by: Yunke Cao <yunkec@google.com>
---
Changelog since v8:
- New patch.
Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
index 58982cd382e3..efa07428ba7a 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst
@@ -447,7 +447,11 @@ See also the examples in :ref:`control`.
- n/a
- A struct :c:type:`v4l2_rect`, containing a rectangle described by
the position of its top-left corner, the width and the height. Units
- depend on the use case.
+ depend on the use case. Use ``V4L2_CTRL_WHICH_MIN_VAL`` and
+ ``V4L2_CTRL_WHICH_MAX_VAL`` to query the range of rectangle sizes. The
+ top-left corner of the minimum and maximum rectangles should be the
+ same. For example, a control can have a minimum rectangle of 1x1@0x0 and
+ a maximum of 640x480@0x0.
* - ``V4L2_CTRL_TYPE_H264_SPS``
- n/a
- n/a
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 10/11] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (8 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 09/11] media: v4l2: document the usage of min/max for V4L2_CTRL_TYPE_RECT Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
2022-10-25 5:55 ` [PATCH v9 11/11] media: uvcvideo: document UVC v1.5 ROI Yunke Cao
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Add support for V4L2_CTRL_WHICH_MIN/MAX_VAL in uvc driver.
It is useful for the V4L2_CID_UVC_REGION_OF_INTEREST_RECT control.
Signed-off-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
---
Changelog since v8:
- No change.
Changelog since v7:
- Address some comments.
drivers/media/usb/uvc/uvc_ctrl.c | 45 +++++++++++++++++++++++++++-----
drivers/media/usb/uvc/uvc_v4l2.c | 11 ++++++--
drivers/media/usb/uvc/uvcvideo.h | 3 ++-
3 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 33199de7f1be..0713685f8005 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1975,6 +1975,7 @@ int uvc_ctrl_get(struct uvc_video_chain *chain,
int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
struct uvc_control *ctrl,
struct uvc_control_mapping *mapping,
+ u32 v4l2_which,
struct v4l2_ext_control *xctrl)
{
struct v4l2_queryctrl qc = { .id = xctrl->id };
@@ -1984,19 +1985,47 @@ int __uvc_ctrl_get_boundary_std(struct uvc_video_chain *chain,
if (ret < 0)
return ret;
- xctrl->value = qc.default_value;
+ switch (v4l2_which) {
+ case V4L2_CTRL_WHICH_DEF_VAL:
+ xctrl->value = qc.default_value;
+ break;
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ xctrl->value = qc.minimum;
+ break;
+ case V4L2_CTRL_WHICH_MAX_VAL:
+ xctrl->value = qc.maximum;
+ break;
+ }
+
return 0;
}
static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain,
struct uvc_control *ctrl,
struct uvc_control_mapping *mapping,
+ u32 v4l2_which,
struct v4l2_ext_control *xctrl)
{
+ u32 flag, id;
int ret;
- if (!uvc_ctrl_mapping_is_compound(mapping))
- return -EINVAL;
+ switch (v4l2_which) {
+ case V4L2_CTRL_WHICH_DEF_VAL:
+ flag = UVC_CTRL_FLAG_GET_DEF;
+ id = UVC_CTRL_DATA_DEF;
+ break;
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ flag = UVC_CTRL_FLAG_GET_MIN;
+ id = UVC_CTRL_DATA_MIN;
+ break;
+ case V4L2_CTRL_WHICH_MAX_VAL:
+ flag = UVC_CTRL_FLAG_GET_MAX;
+ id = UVC_CTRL_DATA_MAX;
+ break;
+ }
+
+ if (!(ctrl->info.flags & flag) && flag != UVC_CTRL_FLAG_GET_DEF)
+ return -EACCES;
if (!ctrl->cached) {
ret = uvc_ctrl_populate_cache(chain, ctrl);
@@ -2004,11 +2033,11 @@ static int __uvc_ctrl_get_boundary_compound(struct uvc_video_chain *chain,
return ret;
}
- return __uvc_ctrl_get_compound(mapping, ctrl, UVC_CTRL_DATA_DEF, xctrl);
+ return __uvc_ctrl_get_compound(mapping, ctrl, id, xctrl);
}
int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
- struct v4l2_ext_control *xctrl)
+ struct v4l2_ext_control *xctrl, u32 v4l2_which)
{
struct uvc_control *ctrl;
struct uvc_control_mapping *mapping;
@@ -2025,9 +2054,11 @@ int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
if (uvc_ctrl_mapping_is_compound(mapping))
ret = __uvc_ctrl_get_boundary_compound(chain, ctrl, mapping,
- xctrl);
+ v4l2_which, xctrl);
else
- ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping, xctrl);
+ ret = __uvc_ctrl_get_boundary_std(chain, ctrl, mapping,
+ v4l2_which, xctrl);
+
done:
mutex_unlock(&chain->ctrl_mutex);
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 52a7dc9ad4b9..08060145700a 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1047,9 +1047,12 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
if (ret < 0)
return ret;
- if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) {
+ switch (ctrls->which) {
+ case V4L2_CTRL_WHICH_DEF_VAL:
+ case V4L2_CTRL_WHICH_MIN_VAL:
+ case V4L2_CTRL_WHICH_MAX_VAL:
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
- ret = uvc_ctrl_get_boundary(chain, ctrl);
+ ret = uvc_ctrl_get_boundary(chain, ctrl, ctrls->which);
if (ret < 0) {
ctrls->error_idx = i;
return ret;
@@ -1057,6 +1060,10 @@ static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
}
return 0;
+ case V4L2_CTRL_WHICH_CUR_VAL:
+ break;
+ default:
+ return -EINVAL;
}
ret = uvc_ctrl_begin(chain);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index c7d20333ca8a..5c3b4ce85615 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -778,7 +778,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl);
int uvc_ctrl_get_boundary(struct uvc_video_chain *chain,
- struct v4l2_ext_control *xctrl);
+ struct v4l2_ext_control *xctrl,
+ u32 v4l2_which);
int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl);
int uvc_ctrl_is_accessible(struct uvc_video_chain *chain, u32 v4l2_id,
bool read);
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v9 11/11] media: uvcvideo: document UVC v1.5 ROI
2022-10-25 5:55 [PATCH v9 00/11] media: Implement UVC v1.5 ROI Yunke Cao
` (9 preceding siblings ...)
2022-10-25 5:55 ` [PATCH v9 10/11] media: uvcvideo: support V4L2_CTRL_WHICH_MIN/MAX_VAL Yunke Cao
@ 2022-10-25 5:55 ` Yunke Cao
10 siblings, 0 replies; 21+ messages in thread
From: Yunke Cao @ 2022-10-25 5:55 UTC (permalink / raw)
To: Hans Verkuil, Laurent Pinchart
Cc: Nicolas Dufresne, Mauro Carvalho Chehab, Tomasz Figa,
Sergey Senozhatsky, Ricardo Ribalda, linux-media, Yunke Cao
Added documentation of V4L2_CID_UVC_REGION_OF_INTEREST_RECT and
V4L2_CID_UVC_REGION_OF_INTEREST_AUTO.
Signed-off-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
---
Changelog since v8:
- No change.
Changelog since v7:
- Fix documentation for automatic exposure based on comment in v7.
Some descriptions for some V4L2_UVC_REGION_OF_INTEREST_AUTO_* are vague because
I copied these options from the UVC spec.
.../userspace-api/media/drivers/uvcvideo.rst | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/Documentation/userspace-api/media/drivers/uvcvideo.rst b/Documentation/userspace-api/media/drivers/uvcvideo.rst
index aab4304e6bb5..3dc062221f8b 100644
--- a/Documentation/userspace-api/media/drivers/uvcvideo.rst
+++ b/Documentation/userspace-api/media/drivers/uvcvideo.rst
@@ -181,6 +181,7 @@ Argument: struct uvc_xu_control_mapping
UVC_CTRL_DATA_TYPE_BOOLEAN Boolean
UVC_CTRL_DATA_TYPE_ENUM Enumeration
UVC_CTRL_DATA_TYPE_BITMASK Bitmask
+ UVC_CTRL_DATA_TYPE_RECT Rectangular area
UVCIOC_CTRL_QUERY - Query a UVC XU control
@@ -255,3 +256,64 @@ Argument: struct uvc_xu_control_query
__u8 query Request code to send to the device
__u16 size Control data size (in bytes)
__u8 *data Control value
+
+
+Driver-specific V4L2 controls
+-----------------------------
+
+The uvcvideo driver implements the following UVC-specific controls:
+
+``V4L2_CID_UVC_REGION_OF_INTEREST_RECT (struct)``
+ This control determines the region of interest (ROI). ROI is a
+ rectangular area represented by a struct :c:type:`v4l2_rect`. The
+ rectangle is in global sensor coordinates and pixel units. It is
+ independent of the field of view, not impacted by any cropping or
+ scaling.
+
+ Use ``V4L2_CTRL_WHICH_MIN_VAL`` and ``V4L2_CTRL_WHICH_MAX_VAL`` to query
+ the range of rectangle sizes. The left/top coordinates of a minimum or
+ maximum rectangle are always 0. For example, a device can have a minimum
+ ROI rectangle of 1x1@0x0 and a maximum of 640x480@0x0.
+
+ Setting a ROI allows the camera to optimize the capture for the region.
+ The value of ``V4L2_CID_REGION_OF_INTEREST_AUTO`` control determines
+ the detailed behavior.
+
+
+``V4L2_CID_UVC_REGION_OF_INTEREST_AUTO (bitmask)``
+ This determines which, if any, on board features should track to the
+ Region of Interest specified by the current value of
+ ``V4L2_CID_UVD__REGION_OF_INTEREST_RECT``.
+
+ Max value is a mask indicating all supported Auto Controls.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE``
+ - Setting this to true causes automatic exposure to track the region of
+ interest instead of the whole image.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS``
+ - Setting this to true causes automatic iris to track the region of
+ interest instead of the whole image.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE``
+ - Setting this to true causes automatic white balance to track the region
+ of interest instead of the whole image.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS``
+ - Setting this to true causes automatic focus adjustment to track the
+ region of interest instead of the whole image.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT``
+ - Setting this to true causes automatic face detection to track the
+ region of interest instead of the whole image.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK``
+ - Setting this to true enables automatic face detection and tracking. The
+ current value of ``V4L2_CID_REGION_OF_INTEREST_RECT`` may be updated by
+ the driver.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION``
+ - Setting this to true enables automatic image stabilization. The
+ current value of ``V4L2_CID_REGION_OF_INTEREST_RECT`` may be updated by
+ the driver.
+ * - ``V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY``
+ - Setting this to true enables automatically capture the specified region
+ with higher quality if possible.
--
2.38.0.135.g90850a2211-goog
^ permalink raw reply related [flat|nested] 21+ messages in thread