[libcamera-devel] [PATCH v2 6/7] v4l2: v4l2_compat: Add eventfd signaling to support polling

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Jun 5 12:16:59 CEST 2020


Hi Paul,

Thank you for the patch.

On Fri, Jun 05, 2020 at 06:01:05PM +0900, Paul Elder wrote:
> To support polling, we need to be able to signal when data is
> available to be read (POLLIN), as well as events (POLLPRI). Add the
> necessary calls to eventfd to allow signaling POLLIN. We signal POLLIN
> by writing writing to the eventfd, and clear it by reading from the
> eventfd, upon VIDIOC_DQBUF.
> 
> Note that eventfd does not support signaling POLLPRI, so we don't yet
> support V4L2 events.
> 
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> ---
> Changes in v2: use eventfd instead of socket
> ---
>  src/v4l2/v4l2_camera.cpp         |  9 +++++++++
>  src/v4l2/v4l2_camera.h           |  3 +++
>  src/v4l2/v4l2_camera_proxy.cpp   | 10 ++++++++++
>  src/v4l2/v4l2_camera_proxy.h     |  4 ++++
>  src/v4l2/v4l2_compat_manager.cpp |  7 ++++++-
>  5 files changed, 32 insertions(+), 1 deletion(-)
> 
> diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp
> index 4da01a45..3c369328 100644
> --- a/src/v4l2/v4l2_camera.cpp
> +++ b/src/v4l2/v4l2_camera.cpp
> @@ -8,6 +8,7 @@
>  #include "v4l2_camera.h"
>  
>  #include <errno.h>
> +#include <unistd.h>
>  
>  #include "libcamera/internal/log.h"
>  
> @@ -53,6 +54,11 @@ void V4L2Camera::close()
>  	camera_->release();
>  }
>  
> +void V4L2Camera::bind(int efd)
> +{
> +	efd_ = efd;
> +}
> +
>  void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig)
>  {
>  	*streamConfig = config_->at(0);
> @@ -84,6 +90,9 @@ void V4L2Camera::requestComplete(Request *request)
>  	completedBuffers_.push_back(std::move(metadata));
>  	bufferLock_.unlock();
>  
> +	uint64_t data = 1;
> +	::write(efd_, &data, sizeof(data));
> +
>  	bufferSema_.release();
>  }
>  
> diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h
> index 303eda44..33f5eb02 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 efd);
>  	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 efd_;
>  };
>  
>  #endif /* __V4L2_CAMERA_H__ */
> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> index cbe9e026..7ee4c0cb 100644
> --- a/src/v4l2/v4l2_camera_proxy.cpp
> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> @@ -13,6 +13,7 @@
>  #include <linux/videodev2.h>
>  #include <string.h>
>  #include <sys/mman.h>
> +#include <unistd.h>
>  
>  #include <libcamera/camera.h>
>  #include <libcamera/object.h>
> @@ -451,6 +452,9 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg)
>  
>  	currentBuf_ = (currentBuf_ + 1) % bufferCount_;
>  
> +	uint64_t data;
> +	::read(efd_, &data, sizeof(data));
> +
>  	return 0;
>  }
>  
> @@ -529,6 +533,12 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg)
>  	return ret;
>  }
>  
> +void V4L2CameraProxy::bind(int fd)
> +{
> +	efd_ = fd;
> +	vcam_->bind(fd);
> +}
> +
>  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..7c65c886 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 fd);
> +
>  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 efd_;
>  };
>  
>  #endif /* __V4L2_CAMERA_PROXY_H__ */
> diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
> index 2338a0ee..56533c4f 100644
> --- a/src/v4l2/v4l2_compat_manager.cpp
> +++ b/src/v4l2/v4l2_compat_manager.cpp
> @@ -155,12 +155,17 @@ 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));
> +	int efd = eventfd(0, EFD_SEMAPHORE |
> +			     ((oflag & O_CLOEXEC) ? EFD_CLOEXEC : 0) |
> +			     ((oflag & O_NONBLOCK) ? EFD_NONBLOCK : 0));
>  	if (efd < 0) {
> +		int err = errno;
>  		proxy->close();
> +		errno = err;
>  		return efd;
>  	}
>  
> +	proxy->bind(efd);
>  	devices_.emplace(efd, proxy);
>  
>  	return efd;

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list