From 58a0e8baf9015786404e01a2d17427cb9d278c98 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Fri, 1 May 2026 12:00:00 +0000 Subject: [PATCH] v4l2: add QUERYCTRL/QUERYMENU capability-probe helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure utility additions, no behaviour change. Three helpers in src/v4l2.{c,h}: - v4l2_query_ext_ctrl(): wraps VIDIOC_QUERY_EXT_CTRL by CID. Returns 0 if the control exists, -1 if not. Caller passes NULL qec to test existence only. - v4l2_query_menu(): wraps VIDIOC_QUERYMENU at a given index. Returns 0 if a menu item exists at that index, -1 otherwise. - v4l2_ctrl_menu_has_value(): convenience layered on the above. For a menu/intmenu-type control, walks all menu items between minimum and maximum and returns true iff `value` is a valid entry. Used by callers that ask "does this driver accept menu value X for this CID?" without caring about iteration details. These unblock commit 3 (request_pool — needs ext-ctrl probing for codec-ops dispatch) and commit 4 (probe-then-set DECODE_MODE/ START_CODE — replaces 0002's unconditional set with a real probe) of the upstreamable design's six-commit series. Forward-declarations in v4l2.h keep the header lean: existing prototypes already use opaque struct v4l2_ext_control * pointers without including ; we follow the same convention for struct v4l2_query_ext_ctrl and struct v4l2_querymenu. No call sites added in this commit. Compile-only verification: the .so links cleanly with three new exports. Signed-off-by: Markus Fritsche --- src/v4l2.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/v4l2.h | 33 ++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/v4l2.c b/src/v4l2.c index 3addb33..765b05f 100644 --- a/src/v4l2.c +++ b/src/v4l2.c @@ -508,3 +508,63 @@ int v4l2_set_stream(int video_fd, unsigned int type, bool enable) return 0; } + +int v4l2_query_ext_ctrl(int video_fd, unsigned int id, + struct v4l2_query_ext_ctrl *qec) +{ + struct v4l2_query_ext_ctrl local; + struct v4l2_query_ext_ctrl *target = qec ? qec : &local; + int rc; + + memset(target, 0, sizeof(*target)); + target->id = id; + + rc = ioctl(video_fd, VIDIOC_QUERY_EXT_CTRL, target); + if (rc < 0) + return -1; + + return 0; +} + +int v4l2_query_menu(int video_fd, unsigned int id, unsigned int index, + struct v4l2_querymenu *qm) +{ + int rc; + + if (qm == NULL) + return -1; + + memset(qm, 0, sizeof(*qm)); + qm->id = id; + qm->index = index; + + rc = ioctl(video_fd, VIDIOC_QUERYMENU, qm); + if (rc < 0) + return -1; + + return 0; +} + +bool v4l2_ctrl_menu_has_value(int video_fd, unsigned int id, + unsigned int value) +{ + struct v4l2_query_ext_ctrl qec; + struct v4l2_querymenu qm; + long long i; + + if (v4l2_query_ext_ctrl(video_fd, id, &qec) < 0) + return false; + + if (qec.type != V4L2_CTRL_TYPE_MENU && + qec.type != V4L2_CTRL_TYPE_INTEGER_MENU) + return false; + + for (i = qec.minimum; i <= qec.maximum; i += qec.step ? qec.step : 1) { + if (v4l2_query_menu(video_fd, id, (unsigned int)i, &qm) < 0) + continue; + if ((unsigned int)i == value) + return true; + } + + return false; +} diff --git a/src/v4l2.h b/src/v4l2.h index 24c12a0..ddb8f86 100644 --- a/src/v4l2.h +++ b/src/v4l2.h @@ -64,4 +64,37 @@ int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data, unsigned int size); int v4l2_set_stream(int video_fd, unsigned int type, bool enable); +/* + * Capability-probe helpers. These let calling code discover what the + * backing kernel driver supports rather than hardcoding assumptions + * about specific decoder hardware. + */ + +/* + * Query the metadata of an extended control by CID. Fills *qec on + * success. Returns 0 if the control exists, -1 (errno=EINVAL) if the + * driver does not expose this CID. Pass qec=NULL to test existence + * only. + */ +struct v4l2_query_ext_ctrl; +int v4l2_query_ext_ctrl(int video_fd, unsigned int id, + struct v4l2_query_ext_ctrl *qec); + +/* + * Query a single menu item of a menu/intmenu control at the given + * index. Fills *qm on success. Returns 0 if the menu item exists at + * this index, -1 otherwise. + */ +struct v4l2_querymenu; +int v4l2_query_menu(int video_fd, unsigned int id, unsigned int index, + struct v4l2_querymenu *qm); + +/* + * Convenience: for a menu-type control, return true iff `value` is a + * valid menu entry (i.e. the driver accepts it). Walks all menu items + * up to the control's maximum to check. + */ +bool v4l2_ctrl_menu_has_value(int video_fd, unsigned int id, + unsigned int value); + #endif