diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp
index 4da01a45..ecbc87ec 100644
--- a/src/v4l2/v4l2_camera.cpp
+++ b/src/v4l2/v4l2_camera.cpp
@@ -8,6 +8,9 @@
 #include "v4l2_camera.h"
 
 #include <errno.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "libcamera/internal/log.h"
 
@@ -51,6 +54,13 @@ void V4L2Camera::close()
 	bufferAllocator_ = nullptr;
 
 	camera_->release();
+
+	::close(sockfd_);
+}
+
+void V4L2Camera::bind(int sockfd)
+{
+	sockfd_ = sockfd;
 }
 
 void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig)
@@ -85,6 +95,9 @@ void V4L2Camera::requestComplete(Request *request)
 	bufferLock_.unlock();
 
 	bufferSema_.release();
+
+	char tmp = 0;
+	::send(sockfd_, &tmp, 1, 0);
 }
 
 int V4L2Camera::configure(StreamConfiguration *streamConfigOut,
diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h
index 303eda44..1ad040c1 100644
--- a/src/v4l2/v4l2_camera.h
+++ b/src/v4l2/v4l2_camera.h
@@ -39,6 +39,7 @@ public:
 
 	int open();
 	void close();
+	void bind(int sockfd);
 	void getStreamConfig(StreamConfiguration *streamConfig);
 	std::vector<Buffer> completedBuffers();
 
@@ -70,6 +71,8 @@ private:
 
 	std::deque<std::unique_ptr<Request>> pendingRequests_;
 	std::deque<std::unique_ptr<Buffer>> completedBuffers_;
+
+	int sockfd_;
 };
 
 #endif /* __V4L2_CAMERA_H__ */
diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
index f84982a2..c9d7945a 100644
--- a/src/v4l2/v4l2_camera_proxy.cpp
+++ b/src/v4l2/v4l2_camera_proxy.cpp
@@ -13,6 +13,9 @@
 #include <linux/videodev2.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <libcamera/camera.h>
 #include <libcamera/object.h>
@@ -451,6 +454,11 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg)
 
 	currentBuf_ = (currentBuf_ + 1) % bufferCount_;
 
+	char tmp;
+	int ret = ::recv(sockfd_, &tmp, 1, 0);
+	if (ret < 1)
+		return -EBUSY;
+
 	return 0;
 }
 
@@ -529,6 +537,12 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg)
 	return ret;
 }
 
+void V4L2CameraProxy::bind(int sockfds[2])
+{
+	sockfd_ = sockfds[0];
+	vcam_->bind(sockfds[1]);
+}
+
 struct PixelFormatPlaneInfo {
 	unsigned int bitsPerPixel;
 	unsigned int hSubSampling;
diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h
index af9f9bbe..251b14a8 100644
--- a/src/v4l2/v4l2_camera_proxy.h
+++ b/src/v4l2/v4l2_camera_proxy.h
@@ -33,6 +33,8 @@ public:
 
 	int ioctl(unsigned long request, void *arg);
 
+	void bind(int sockfds[2]);
+
 private:
 	bool validateBufferType(uint32_t type);
 	bool validateMemoryType(uint32_t memory);
@@ -77,6 +79,8 @@ private:
 	std::map<void *, unsigned int> mmaps_;
 
 	std::unique_ptr<V4L2Camera> vcam_;
+
+	int sockfd_;
 };
 
 #endif /* __V4L2_CAMERA_PROXY_H__ */
diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
index 2338a0ee..b6e84866 100644
--- a/src/v4l2/v4l2_compat_manager.cpp
+++ b/src/v4l2/v4l2_compat_manager.cpp
@@ -12,8 +12,8 @@
 #include <map>
 #include <stdarg.h>
 #include <string.h>
-#include <sys/eventfd.h>
 #include <sys/mman.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
@@ -155,15 +155,25 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod
 	if (ret < 0)
 		return ret;
 
-	int efd = eventfd(0, oflag & (O_CLOEXEC | O_NONBLOCK));
-	if (efd < 0) {
+	int sockets[2];
+	ret = socketpair(AF_UNIX,
+			 SOCK_STREAM
+			 | ((oflag & O_CLOEXEC) ? SOCK_CLOEXEC : 0)
+			 | ((oflag & O_NONBLOCK) ? SOCK_NONBLOCK : 0),
+			 0, sockets);
+	if (ret) {
+		int err = errno;
 		proxy->close();
-		return efd;
+		errno = err;
+
+		return ret;
 	}
 
-	devices_.emplace(efd, proxy);
+	proxy->bind(sockets);
+
+	devices_.emplace(sockets[0], proxy);
 
-	return efd;
+	return sockets[0];
 }
 
 int V4L2CompatManager::dup(int oldfd)
