$ git -P log --oneline v6.13..
102e81a4ca67 (HEAD -> v4l2-loopback, origin/v4l2-loopback, origin/HEAD) Use _IO*() for declaring the ioctls
b23722b0cd42 Rename ready_for_capture as active_writers
e61f00594c83 Open code free_devices()
599291c9d3ee Remove V4L2LOOPBACK_CTL_QUERY
5cc9d24a3171 Set video_set_drvdata(dev->vdev, dev) directly
3b13a59d5144 Remove HAVE_TIMER_SETUP
743149844edb Remove sysfs device attributes
84ee7af7394b Remove redundant module parameters
29bb94896aa4 Do not create a device in module_init()
122ddd353ccb Remove redundant module information
37955369d9f2 Remove LINUX_VERSION_CODE checks
e87cf1bb681a Reburnish file headers and SPDX identifiers
497e4575d495 Remove clang-format comments
7b4bb35c0be3 Remove dprintk*()
353e603c9d3c Remove MARK()
6009806fe555 media: v4l2-loopback
The point of all these small tweaks:
I’ve also tested that every commit is still running version, except the top most break ABI (not API).
The first thing to do with fd based model is to make capabilities a static creation time thing:
diff --git a/drivers/media/v4l2-core/v4l2-loopback.c b/drivers/media/v4l2-core/v4l2-loopback.c
index 2f5b81628e7c..f643d5dd9dca 100644
--- a/drivers/media/v4l2-core/v4l2-loopback.c
+++ b/drivers/media/v4l2-core/v4l2-loopback.c
@@ -232,9 +232,11 @@ struct v4l2_loopback_device {
* this differs slightly from !ready_for_capture,
* e.g. when using fallback images */
int active_readers; /* increase if any reader starts streaming */
- int announce_all_caps; /* set to false, if device caps (OUTPUT/CAPTURE)
- * should only be announced if the resp. "ready"
- * flag is set; default=TRUE */
+
+ /*
+ * Any subset of V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT.
+ */
+ __u32 capabilities;
int min_width, max_width;
int min_height, max_height;
@@ -777,22 +779,10 @@ static int vidioc_querycap(struct file *file, void *priv,
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:v4l2loopback-%03d", dev->device_nr);
- if (dev->announce_all_caps) {
- capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
- } else {
- if (dev->ready_for_capture) {
- capabilities |= V4L2_CAP_VIDEO_CAPTURE;
- }
- if (dev->ready_for_output) {
- capabilities |= V4L2_CAP_VIDEO_OUTPUT;
- }
- }
-
- dev->vdev->device_caps =
- cap->device_caps = cap->capabilities = capabilities;
-
- cap->capabilities |= V4L2_CAP_DEVICE_CAPS;
-
+ capabilities |= dev->capabilities;
+ dev->vdev->device_caps = capabilities;
+ cap->device_caps = capabilities;
+ cap->capabilities = capabilities | V4L2_CAP_DEVICE_CAPS;
memset(cap->reserved, 0, sizeof(cap->reserved));
return 0;
}
@@ -1273,7 +1263,7 @@ static int vidioc_enum_output(struct file *file, void *fh,
struct v4l2_loopback_device *dev = video_drvdata(file);
__u32 index = outp->index;
- if (!dev->announce_all_caps && !dev->ready_for_output)
+ if (!dev->capabilities && !dev->ready_for_output)
return -ENOTTY;
if (0 != index)
@@ -1304,7 +1294,7 @@ static int vidioc_g_output(struct file *file, void *fh, unsigned int *i)
{
struct v4l2_loopback_device *dev = video_drvdata(file);
- if (!dev->announce_all_caps && !dev->ready_for_output)
+ if (!dev->capabilities && !dev->ready_for_output)
return -ENOTTY;
if (i)
*i = 0;
@@ -1318,7 +1308,7 @@ static int vidioc_s_output(struct file *file, void *fh, unsigned int i)
{
struct v4l2_loopback_device *dev = video_drvdata(file);
- if (!dev->announce_all_caps && !dev->ready_for_output)
+ if (!dev->capabilities && !dev->ready_for_output)
return -ENOTTY;
if (i)
@@ -1372,7 +1362,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
{
struct v4l2_loopback_device *dev = video_drvdata(file);
- if (!dev->announce_all_caps && !dev->ready_for_capture)
+ if (!dev->capabilities && !dev->ready_for_capture)
return -ENOTTY;
if (i)
*i = 0;
@@ -1386,7 +1376,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
{
struct v4l2_loopback_device *dev = video_drvdata(file);
- if (!dev->announce_all_caps && !dev->ready_for_capture)
+ if (!dev->capabilities && !dev->ready_for_capture)
return -ENOTTY;
if (i == 0)
return 0;
@@ -2383,7 +2373,7 @@ static int v4l2_loopback_add(struct v4l2_loopback_config *conf, int *ret_nr)
struct v4l2_ctrl_handler *hdl;
int err = -ENOMEM;
- if (conf->announce_all_caps != 0 && conf->announce_all_caps != 1)
+ if (conf->capabilities & ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
if (conf->max_buffers > 0)
@@ -2488,7 +2478,7 @@ static int v4l2_loopback_add(struct v4l2_loopback_config *conf, int *ret_nr)
dev->keep_format = 0;
dev->sustain_framerate = 0;
- dev->announce_all_caps = conf->announce_all_caps;
+ dev->capabilities = conf->capabilities;
dev->min_width = min_width;
dev->min_height = min_height;
dev->max_width = max_width;
diff --git a/include/uapi/linux/v4l2-loopback.h b/include/uapi/linux/v4l2-loopback.h
index 74527dd3676c..d10270548f84 100644
--- a/include/uapi/linux/v4l2-loopback.h
+++ b/include/uapi/linux/v4l2-loopback.h
@@ -58,14 +58,10 @@ struct v4l2_loopback_config {
*/
int debug;
- /**
- * whether to announce OUTPUT/CAPTURE capabilities exclusively
- * for this device or not
- * (!exclusive_caps)
- * NOTE: this is going to be removed once separate output/capture
- * devices are implemented
+ /*
+ * Any subset of V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT.
*/
- int announce_all_caps;
+ __u32 capabilities;
};
#define V4L2LOOPBACK_CTL_ADD _IOW('v', 0x00, struct v4l2_loopback_config)
The driver side will then respect these and clients will be “sort of” mirror of the capabilities. And most likely exclusive per streamon. Internals need some clean ups and some add-ons. Perhaps quickest PoC is to just add DRIVER enum opener_type at first, which the fd returned by ioctl will receive.
Still need to clean up and clear the path a bit :-) I just did the above beginnings of a patch to get idea what the other end will look like and where I just converge into…
#ilovefs is almost here, and we wanted to kick off the celebrations with a little #Trivia 💗 When was the term "#FreeSoftware" created?
See if you can answer this correctly before your friends :D
Answer will be posted tomorrow morning.
An Open Letter to All European Politicians and Leaders to Abandon X/Twitter:
"By abandoning X/Twitter, leaders can reduce its credibility, promote fairer alternatives, and take a stand against the spread of disinformation, ensuring democratic principles are upheld."
H/T to @everton137 for organizing this - already close to 1,000 signatures:
No-Libc Zig Now Outperforms Glibc Zig
https://ziglang.org/devlog/2025/#2025-02-07
Discussions: https://discu.eu/q/https://ziglang.org/devlog/2025/%232025-02-07