From patchwork Tue Jun 23 19:08:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4175 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3A971609C4 for ; Tue, 23 Jun 2020 21:09:05 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BJnDKxK1"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 481C42A9; Tue, 23 Jun 2020 21:09:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939344; bh=VeCFJATKtInuOjDMzMyeOpt7r0xRQBA/flQvr3Jr5ic=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BJnDKxK1+hGHP9gdfeYdYjBEhKOUOU1DQFF6uc/LTSWQM9cmlPymnq6RU+fqiOacb IzkG0IxJdlHJ6y2Hqds9Wxu9deAAxFqsvdIMZkZtLj+UrgC6A+4/4MTgTPHtWd/+fH G7OGXbbW8F8plOONsh0nLzY56r9Q0hxiQn099fVE= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:15 +0900 Message-Id: <20200623190836.53446-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 01/22] v4l2: v4l2_camera_file: Add V4L2CameraFile to model the opened camera file X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:05 -0000 With relation to opening files, the kernel has three objects related to files: - inodes, that represent files on disk - file objects, that are allocated at open() time and store all data related to the open file - file descriptors, that are integers that map to a file In the V4L2 compatibility layer, V4L2CameraProxy, which wraps a single libcamera camera via V4L2Camera, is more or less equivalent to the inode. We also already have file descriptors (that are really eventfds) that mirror the file descriptors. Here we create a V4L2CameraFile to model the file objects, to contain information related to the open file, namely if the file has been opened as non-blocking, and the V4L2 priority (to support VIDIOC_G/S_PRIORITY later on). This new class allows us to more cleanly support multiple open later on, since we can move out of V4L2CameraProxy the handling of mapping the fd to the open file information. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - cosmetic changes - change public V4L2CameraFile::priority_ to private with public getter and setter New in v2 --- src/v4l2/meson.build | 1 + src/v4l2/v4l2_camera_file.cpp | 26 ++++++++++++++++++++++++ src/v4l2/v4l2_camera_file.h | 37 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/v4l2/v4l2_camera_file.cpp create mode 100644 src/v4l2/v4l2_camera_file.h diff --git a/src/v4l2/meson.build b/src/v4l2/meson.build index f2e4aaf..e3838f0 100644 --- a/src/v4l2/meson.build +++ b/src/v4l2/meson.build @@ -2,6 +2,7 @@ v4l2_compat_sources = files([ 'v4l2_camera.cpp', + 'v4l2_camera_file.cpp', 'v4l2_camera_proxy.cpp', 'v4l2_compat.cpp', 'v4l2_compat_manager.cpp', diff --git a/src/v4l2/v4l2_camera_file.cpp b/src/v4l2/v4l2_camera_file.cpp new file mode 100644 index 0000000..d3232ab --- /dev/null +++ b/src/v4l2/v4l2_camera_file.cpp @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * v4l2_camera_file.h - V4L2 compatibility camera file information + */ + +#include "v4l2_camera_file.h" + +#include + +#include "v4l2_camera_proxy.h" + +using namespace libcamera; + +V4L2CameraFile::V4L2CameraFile(int efd, bool nonBlocking, V4L2CameraProxy *proxy) + : proxy_(proxy), nonBlocking_(nonBlocking), efd_(efd), + priority_(V4L2_PRIORITY_DEFAULT) +{ + proxy_->open(nonBlocking); +} + +V4L2CameraFile::~V4L2CameraFile() +{ + proxy_->close(); +} diff --git a/src/v4l2/v4l2_camera_file.h b/src/v4l2/v4l2_camera_file.h new file mode 100644 index 0000000..8f4670a --- /dev/null +++ b/src/v4l2/v4l2_camera_file.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * v4l2_camera_file.h - V4L2 compatibility camera file information + */ + +#ifndef __V4L2_CAMERA_FILE_H__ +#define __V4L2_CAMERA_FILE_H__ + +#include + +class V4L2CameraProxy; + +class V4L2CameraFile +{ +public: + V4L2CameraFile(int efd, bool nonBlocking, V4L2CameraProxy *proxy); + ~V4L2CameraFile(); + + V4L2CameraProxy *proxy() const { return proxy_; } + + bool nonBlocking() const { return nonBlocking_; } + int efd() const { return efd_; } + + enum v4l2_priority priority() const { return priority_; } + void setPriority(enum v4l2_priority priority) { priority_ = priority; } + +private: + V4L2CameraProxy *proxy_; + + bool nonBlocking_; + int efd_; + enum v4l2_priority priority_; +}; + +#endif /* __V4L2_CAMERA_FILE_H__ */ From patchwork Tue Jun 23 19:08:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4176 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C94F609C6 for ; Tue, 23 Jun 2020 21:09:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ONVz81Un"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BE5CF329; Tue, 23 Jun 2020 21:09:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939347; bh=/QJsJSD1wnk2C7tJzBlBn/MeDkC0CFgL6rDguYYXavU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ONVz81Unyme3wTI/VO8pk49ptz1GDxG9syyxDJga88LuQU6QnDKAVlXfJ5v90ZdJo 4du0RkAppxvqYx2chMhVmnf4P+pnZKTVBFd/hQXKC0PWrEmqPQNloO9W7CBbJdA39S R/98dTTRUsOQtu9qC/k7WNKtrcs4Jd6ELpQAdqnc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:16 +0900 Message-Id: <20200623190836.53446-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 02/22] v4l2: V4L2CameraProxy: Take V4L2CameraFile as argument for intercepted calls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:08 -0000 Prepare for using the V4L2CameraFile as a container for file-specific information in the V4L2 compatibility layer by making it a required argument for all V4L2CameraProxy calls that are directed from V4L2CompatManager, which are intercepted via LD_PRELOAD. Change V4L2CameraFile accordingly. Also change V4L2CompatManager accordingly. Instead of keeping a map of file descriptors to V4L2CameraProxy instances, we keep a map of V4L2CameraFile instances to V4L2CameraProxy instances. When the proxy methods are called, feed the file as a parameter. The dup function is also modified, in that it is removed from V4L2CameraProxy, and is handled completely in V4L2CompatManager, as a map from file descriptors to V4L2CameraFile instances. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New in v3 - split from "v4l2: v4l2_compat: Support multiple open" --- src/v4l2/v4l2_camera_file.cpp | 4 +- src/v4l2/v4l2_camera_proxy.cpp | 89 +++++++++++++++----------------- src/v4l2/v4l2_camera_proxy.h | 31 ++++++----- src/v4l2/v4l2_compat_manager.cpp | 69 +++++++++++-------------- src/v4l2/v4l2_compat_manager.h | 4 +- 5 files changed, 90 insertions(+), 107 deletions(-) diff --git a/src/v4l2/v4l2_camera_file.cpp b/src/v4l2/v4l2_camera_file.cpp index d3232ab..a07679b 100644 --- a/src/v4l2/v4l2_camera_file.cpp +++ b/src/v4l2/v4l2_camera_file.cpp @@ -17,10 +17,10 @@ V4L2CameraFile::V4L2CameraFile(int efd, bool nonBlocking, V4L2CameraProxy *proxy : proxy_(proxy), nonBlocking_(nonBlocking), efd_(efd), priority_(V4L2_PRIORITY_DEFAULT) { - proxy_->open(nonBlocking); + proxy_->open(this); } V4L2CameraFile::~V4L2CameraFile() { - proxy_->close(); + proxy_->close(this); } diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index bf47aa7..c1ee1be 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -23,6 +23,7 @@ #include "libcamera/internal/utils.h" #include "v4l2_camera.h" +#include "v4l2_camera_file.h" #include "v4l2_compat_manager.h" #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) @@ -39,9 +40,9 @@ V4L2CameraProxy::V4L2CameraProxy(unsigned int index, querycap(camera); } -int V4L2CameraProxy::open(bool nonBlocking) +int V4L2CameraProxy::open(V4L2CameraFile *file) { - LOG(V4L2Compat, Debug) << "Servicing open"; + LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd(); int ret = vcam_->open(); if (ret < 0) { @@ -49,8 +50,6 @@ int V4L2CameraProxy::open(bool nonBlocking) return -1; } - nonBlocking_ = nonBlocking; - vcam_->getStreamConfig(&streamConfig_); setFmtFromConfig(streamConfig_); sizeimage_ = calculateSizeImage(streamConfig_); @@ -60,14 +59,10 @@ int V4L2CameraProxy::open(bool nonBlocking) return 0; } -void V4L2CameraProxy::dup() +void V4L2CameraProxy::close(V4L2CameraFile *file) { - refcount_++; -} + LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd(); -void V4L2CameraProxy::close() -{ - LOG(V4L2Compat, Debug) << "Servicing close"; if (--refcount_ > 0) return; @@ -221,9 +216,9 @@ int V4L2CameraProxy::vidioc_querycap(struct v4l2_capability *arg) return 0; } -int V4L2CameraProxy::vidioc_enum_fmt(struct v4l2_fmtdesc *arg) +int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_fmt"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_fmt fd = " << file->efd(); if (!validateBufferType(arg->type) || arg->index >= streamConfig_.formats().pixelformats().size()) @@ -237,9 +232,9 @@ int V4L2CameraProxy::vidioc_enum_fmt(struct v4l2_fmtdesc *arg) return 0; } -int V4L2CameraProxy::vidioc_g_fmt(struct v4l2_format *arg) +int V4L2CameraProxy::vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_g_fmt"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_g_fmt fd = " << file->efd(); if (!validateBufferType(arg->type)) return -EINVAL; @@ -275,9 +270,9 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) arg->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; } -int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg) +int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_s_fmt"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_s_fmt fd = " << file->efd(); if (!validateBufferType(arg->type)) return -EINVAL; @@ -302,9 +297,9 @@ int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg) return 0; } -int V4L2CameraProxy::vidioc_try_fmt(struct v4l2_format *arg) +int V4L2CameraProxy::vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_try_fmt"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_try_fmt fd = " << file->efd(); if (!validateBufferType(arg->type)) return -EINVAL; @@ -329,11 +324,9 @@ int V4L2CameraProxy::freeBuffers() return 0; } -int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) +int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg) { - int ret; - - LOG(V4L2Compat, Debug) << "Servicing vidioc_reqbufs"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_reqbufs fd = " << file->efd(); if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory)) @@ -347,9 +340,9 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) return freeBuffers(); Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); - ret = vcam_->configure(&streamConfig_, size, - v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), - arg->count); + int ret = vcam_->configure(&streamConfig_, size, + v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), + arg->count); if (ret < 0) return -EINVAL; @@ -396,9 +389,9 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) return 0; } -int V4L2CameraProxy::vidioc_querybuf(struct v4l2_buffer *arg) +int V4L2CameraProxy::vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_querybuf"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_querybuf fd = " << file->efd(); if (!validateBufferType(arg->type) || arg->index >= bufferCount_) @@ -411,10 +404,10 @@ int V4L2CameraProxy::vidioc_querybuf(struct v4l2_buffer *arg) return 0; } -int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg) +int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) { LOG(V4L2Compat, Debug) << "Servicing vidioc_qbuf, index = " - << arg->index; + << arg->index << " fd = " << file->efd(); if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory) || @@ -431,15 +424,15 @@ int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg) return ret; } -int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg) +int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd(); if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory)) return -EINVAL; - if (!nonBlocking_) + if (!(file->nonBlocking())) vcam_->bufferSema_.acquire(); else if (!vcam_->bufferSema_.tryAcquire()) return -EAGAIN; @@ -455,16 +448,16 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg) currentBuf_ = (currentBuf_ + 1) % bufferCount_; uint64_t data; - int ret = ::read(efd_, &data, sizeof(data)); + int ret = ::read(file->efd(), &data, sizeof(data)); if (ret != sizeof(data)) LOG(V4L2Compat, Error) << "Failed to clear eventfd POLLIN"; return 0; } -int V4L2CameraProxy::vidioc_streamon(int *arg) +int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_streamon"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_streamon fd = " << file->efd(); if (!validateBufferType(*arg)) return -EINVAL; @@ -474,9 +467,9 @@ int V4L2CameraProxy::vidioc_streamon(int *arg) return vcam_->streamOn(); } -int V4L2CameraProxy::vidioc_streamoff(int *arg) +int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) { - LOG(V4L2Compat, Debug) << "Servicing vidioc_streamoff"; + LOG(V4L2Compat, Debug) << "Servicing vidioc_streamoff fd = " << file->efd(); if (!validateBufferType(*arg)) return -EINVAL; @@ -489,7 +482,7 @@ int V4L2CameraProxy::vidioc_streamoff(int *arg) return ret; } -int V4L2CameraProxy::ioctl(unsigned long request, void *arg) +int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg) { int ret; switch (request) { @@ -497,34 +490,34 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg) ret = vidioc_querycap(static_cast(arg)); break; case VIDIOC_ENUM_FMT: - ret = vidioc_enum_fmt(static_cast(arg)); + ret = vidioc_enum_fmt(file, static_cast(arg)); break; case VIDIOC_G_FMT: - ret = vidioc_g_fmt(static_cast(arg)); + ret = vidioc_g_fmt(file, static_cast(arg)); break; case VIDIOC_S_FMT: - ret = vidioc_s_fmt(static_cast(arg)); + ret = vidioc_s_fmt(file, static_cast(arg)); break; case VIDIOC_TRY_FMT: - ret = vidioc_try_fmt(static_cast(arg)); + ret = vidioc_try_fmt(file, static_cast(arg)); break; case VIDIOC_REQBUFS: - ret = vidioc_reqbufs(static_cast(arg)); + ret = vidioc_reqbufs(file, static_cast(arg)); break; case VIDIOC_QUERYBUF: - ret = vidioc_querybuf(static_cast(arg)); + ret = vidioc_querybuf(file, static_cast(arg)); break; case VIDIOC_QBUF: - ret = vidioc_qbuf(static_cast(arg)); + ret = vidioc_qbuf(file, static_cast(arg)); break; case VIDIOC_DQBUF: - ret = vidioc_dqbuf(static_cast(arg)); + ret = vidioc_dqbuf(file, static_cast(arg)); break; case VIDIOC_STREAMON: - ret = vidioc_streamon(static_cast(arg)); + ret = vidioc_streamon(file, static_cast(arg)); break; case VIDIOC_STREAMOFF: - ret = vidioc_streamoff(static_cast(arg)); + ret = vidioc_streamoff(file, static_cast(arg)); break; default: ret = -ENOTTY; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 27d3e50..b2197ef 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -21,20 +21,20 @@ using namespace libcamera; +class V4L2CameraFile; + class V4L2CameraProxy { public: V4L2CameraProxy(unsigned int index, std::shared_ptr camera); - int open(bool nonBlocking); - void dup(); - void close(); + int open(V4L2CameraFile *file); + void close(V4L2CameraFile *file); void *mmap(void *addr, size_t length, int prot, int flags, off64_t offset); int munmap(void *addr, size_t length); - int ioctl(unsigned long request, void *arg); - void bind(int fd); + int ioctl(V4L2CameraFile *file, unsigned long request, void *arg); private: bool validateBufferType(uint32_t type); @@ -47,16 +47,16 @@ private: int freeBuffers(); int vidioc_querycap(struct v4l2_capability *arg); - int vidioc_enum_fmt(struct v4l2_fmtdesc *arg); - int vidioc_g_fmt(struct v4l2_format *arg); - int vidioc_s_fmt(struct v4l2_format *arg); - int vidioc_try_fmt(struct v4l2_format *arg); - int vidioc_reqbufs(struct v4l2_requestbuffers *arg); - int vidioc_querybuf(struct v4l2_buffer *arg); - int vidioc_qbuf(struct v4l2_buffer *arg); - int vidioc_dqbuf(struct v4l2_buffer *arg); - int vidioc_streamon(int *arg); - int vidioc_streamoff(int *arg); + int vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg); + int vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg); + int vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg); + int vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg); + int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg); + int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg); + int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); + int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); + int vidioc_streamon(V4L2CameraFile *file, int *arg); + int vidioc_streamoff(V4L2CameraFile *file, int *arg); static unsigned int bplMultiplier(uint32_t format); static unsigned int imageSize(uint32_t format, unsigned int width, @@ -67,7 +67,6 @@ private: unsigned int refcount_; unsigned int index_; - bool nonBlocking_; struct v4l2_format curV4L2Format_; StreamConfiguration streamConfig_; diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 8da3316..8118170 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -24,6 +24,8 @@ #include "libcamera/internal/log.h" +#include "v4l2_camera_file.h" + using namespace libcamera; LOG_DEFINE_CATEGORY(V4L2Compat) @@ -49,7 +51,7 @@ V4L2CompatManager::V4L2CompatManager() V4L2CompatManager::~V4L2CompatManager() { - devices_.clear(); + files_.clear(); mmaps_.clear(); if (cm_) { @@ -95,13 +97,13 @@ V4L2CompatManager *V4L2CompatManager::instance() return &instance; } -V4L2CameraProxy *V4L2CompatManager::getProxy(int fd) +std::shared_ptr V4L2CompatManager::cameraFile(int fd) { - auto device = devices_.find(fd); - if (device == devices_.end()) - return nullptr; + auto file = files_.find(fd); + if (file == files_.end()) + return std::shared_ptr(); - return device->second; + return file->second; } int V4L2CompatManager::getCameraIndex(int fd) @@ -148,25 +150,15 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod fops_.close(fd); - unsigned int camera_index = static_cast(ret); - - V4L2CameraProxy *proxy = proxies_[camera_index].get(); - ret = proxy->open(oflag & O_NONBLOCK); - if (ret < 0) - return ret; - 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; + if (efd < 0) return efd; - } - proxy->bind(efd); - devices_.emplace(efd, proxy); + unsigned int index = static_cast(ret); + V4L2CameraProxy *proxy = proxies_[index].get(); + files_.emplace(efd, std::make_shared(efd, oflag & O_NONBLOCK, proxy)); return efd; } @@ -177,40 +169,39 @@ int V4L2CompatManager::dup(int oldfd) if (newfd < 0) return newfd; - auto device = devices_.find(oldfd); - if (device != devices_.end()) { - V4L2CameraProxy *proxy = device->second; - devices_[newfd] = proxy; - proxy->dup(); - } + auto file = files_.find(oldfd); + if (file != files_.end()) + files_[newfd] = file->second; return newfd; } int V4L2CompatManager::close(int fd) { - V4L2CameraProxy *proxy = getProxy(fd); - if (proxy) { - proxy->close(); - devices_.erase(fd); - return 0; - } + auto file = files_.find(fd); + if (file != files_.end()) + files_.erase(file); + /* We still need to close the eventfd. */ return fops_.close(fd); } void *V4L2CompatManager::mmap(void *addr, size_t length, int prot, int flags, int fd, off64_t offset) { - V4L2CameraProxy *proxy = getProxy(fd); - if (!proxy) + std::shared_ptr file = cameraFile(fd); + if (!file) return fops_.mmap(addr, length, prot, flags, fd, offset); - void *map = proxy->mmap(addr, length, prot, flags, offset); + void *map = file->proxy()->mmap(addr, length, prot, flags, offset); if (map == MAP_FAILED) return map; - mmaps_[map] = proxy; + /* + * Map to V4L2CameraProxy directly to prevent adding more references + * to V4L2CameraFile. + */ + mmaps_[map] = file->proxy(); return map; } @@ -233,9 +224,9 @@ int V4L2CompatManager::munmap(void *addr, size_t length) int V4L2CompatManager::ioctl(int fd, unsigned long request, void *arg) { - V4L2CameraProxy *proxy = getProxy(fd); - if (!proxy) + std::shared_ptr file = cameraFile(fd); + if (!file) return fops_.ioctl(fd, request, arg); - return proxy->ioctl(request, arg); + return file->proxy()->ioctl(file.get(), request, arg); } diff --git a/src/v4l2/v4l2_compat_manager.h b/src/v4l2/v4l2_compat_manager.h index 3d4e512..bc548ab 100644 --- a/src/v4l2/v4l2_compat_manager.h +++ b/src/v4l2/v4l2_compat_manager.h @@ -44,7 +44,6 @@ public: static V4L2CompatManager *instance(); - V4L2CameraProxy *getProxy(int fd); const FileOperations &fops() const { return fops_; } int openat(int dirfd, const char *path, int oflag, mode_t mode); @@ -62,13 +61,14 @@ private: int start(); int getCameraIndex(int fd); + std::shared_ptr cameraFile(int fd); FileOperations fops_; CameraManager *cm_; std::vector> proxies_; - std::map devices_; + std::map> files_; std::map mmaps_; }; From patchwork Tue Jun 23 19:08:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4177 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A8B5F609A7 for ; Tue, 23 Jun 2020 21:09:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="asW8hx07"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3368E329; Tue, 23 Jun 2020 21:09:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939349; bh=CNI07xPVFaxx9sRcBYHZW10aL6IHbfGQFJJV6UkxiB4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=asW8hx078i150GYwFQQbEzp6XBh+oWNtBbKLScScyWizY2M5Ht3PKyCkWcd7QJyPv drPItMTkjRdtZX2dBaZ9M8ViHV8hJg+dVMw8TOS4ZJ7chRYI9Phh97yEzIEKWSFW4I qtaEt32iHSMc/YenWP0h/V/cYRbbeqtPueiC7Lo8= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:17 +0900 Message-Id: <20200623190836.53446-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 03/22] v4l2: v4l2_compat: Support multiple open X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:10 -0000 Previously, since we acquired the libcamera camera upon open(), it was impossible to support multiple open, as any subsequent opens would return error because the camera would already be acquired. To fix this, we first initialize the camera in the first call to V4L2CameraProxy::open(), just to heat up the stream format cache. We then add ownership by a V4L2CameraFile of a V4L2Camera via the V4L2CameraProxy. All vidioc ioctls prior to reqbufs > 0 (except for s_fmt) are able to access the camera without ownership. A call to reqbufs > 0 (and s_fmt) will take ownership, and the ownership will be released at reqbufs = 0. While ownership is assigned, the eventfd that should be signaled (and cleared) by V4L2Camera and V4L2CameraProxy is set to the V4L2CameraFile that has ownership, and is cleared when the ownership is released. In case close() is called without a reqbufs = 0 first, the ownership is also released on close(). We also use the V4L2CameraFile to contain all the information specific to an open instance of the file. This removes the need to keep track of such information within V4L2CameraProxy via multiple maps from int fd to info. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - split V4L2CompatManager stuff into separate patch - split changing the fd argument to camera file argument in all proxy methods into the separate patch - remove V4L2CameraProxy::efd_ (it's duplicated from V4L2CameraFile::efd()) - rename cf in all the V4L2CameraProxy methods to file - rename V4L2CameraProxy::acquiredCf_ to V4L2CameraProxy::owner_ - remove V4L2CameraProxy::initialized_; just use V4L2CameraProxy::refcount_ - move bufferCount_ > 0 in reqbufs to different patch - move TIMESTAMP_MONOTONIC to different patch - don't take the lock for querybuf - add V4L2CameraProxy::hasOwnership - rename lock() to acquire() and unlock() to release() - only lock on s_fmt and reqbufs > 0, in other ioctls only check for ownership - add explanation about not supporting polling for events from an fd different than the one that owns the device for polling for bufs Changes in v2: - use V4L2CameraFile in V4L2CompatManager to deal with dup, and in V4L2CameraProxy to deal with information specific to the open file (nonblock and priority) - unlock exclusive camera lock on close() --- src/v4l2/v4l2_camera.cpp | 9 +++- src/v4l2/v4l2_camera.h | 1 + src/v4l2/v4l2_camera_proxy.cpp | 99 ++++++++++++++++++++++++++++------ src/v4l2/v4l2_camera_proxy.h | 16 +++++- 4 files changed, 106 insertions(+), 19 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 9a1ebc8..2557320 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -17,7 +17,8 @@ using namespace libcamera; LOG_DECLARE_CATEGORY(V4L2Compat); V4L2Camera::V4L2Camera(std::shared_ptr camera) - : camera_(camera), isRunning_(false), bufferAllocator_(nullptr) + : camera_(camera), isRunning_(false), bufferAllocator_(nullptr), + efd_(-1) { camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete); } @@ -29,7 +30,6 @@ V4L2Camera::~V4L2Camera() int V4L2Camera::open() { - /* \todo Support multiple open. */ if (camera_->acquire() < 0) { LOG(V4L2Compat, Error) << "Failed to acquire camera"; return -EINVAL; @@ -59,6 +59,11 @@ void V4L2Camera::bind(int efd) efd_ = efd; } +void V4L2Camera::unbind() +{ + efd_ = -1; +} + void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig) { *streamConfig = config_->at(0); diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 33f5eb0..30114ed 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -40,6 +40,7 @@ public: int open(); void close(); void bind(int efd); + void unbind(); void getStreamConfig(StreamConfiguration *streamConfig); std::vector completedBuffers(); diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index c1ee1be..eb59d49 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -35,7 +35,7 @@ LOG_DECLARE_CATEGORY(V4L2Compat); V4L2CameraProxy::V4L2CameraProxy(unsigned int index, std::shared_ptr camera) : refcount_(0), index_(index), bufferCount_(0), currentBuf_(0), - vcam_(std::make_unique(camera)) + vcam_(std::make_unique(camera)), owner_(nullptr) { querycap(camera); } @@ -44,18 +44,29 @@ int V4L2CameraProxy::open(V4L2CameraFile *file) { LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd(); + if (refcount_++) + return 0; + + /* + * We open the camera here, once, and keep it open until the last + * V4L2CameraFile is closed. The proxy is initially not owned by any + * file. The first file that calls reqbufs with count > 0 will become + * the owner, and no other file will be allowed to call buffer-related + * ioctls (except querycap, querybuf, try_fmt, g/s_priority, + * enum/g/s_input), set the format or start or stop the stream until + * ownership is released with a call to reqbufs with count = 0. + */ + int ret = vcam_->open(); if (ret < 0) { - errno = -ret; - return -1; + refcount_--; + return ret; } vcam_->getStreamConfig(&streamConfig_); setFmtFromConfig(streamConfig_); sizeimage_ = calculateSizeImage(streamConfig_); - refcount_++; - return 0; } @@ -63,6 +74,7 @@ void V4L2CameraProxy::close(V4L2CameraFile *file) { LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd(); + release(file); if (--refcount_ > 0) return; @@ -277,12 +289,16 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) if (!validateBufferType(arg->type)) return -EINVAL; + int ret = acquire(file); + if (ret < 0) + return ret; + tryFormat(arg); Size size(arg->fmt.pix.width, arg->fmt.pix.height); - int ret = vcam_->configure(&streamConfig_, size, - v4l2ToDrm(arg->fmt.pix.pixelformat), - bufferCount_); + ret = vcam_->configure(&streamConfig_, size, + v4l2ToDrm(arg->fmt.pix.pixelformat), + bufferCount_); if (ret < 0) return -EINVAL; @@ -334,15 +350,21 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf LOG(V4L2Compat, Debug) << arg->count << " buffers requested "; + int ret = acquire(file); + if (ret < 0) + return ret; + arg->capabilities = V4L2_BUF_CAP_SUPPORTS_MMAP; - if (arg->count == 0) + if (arg->count == 0) { + release(file); return freeBuffers(); + } Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); - int ret = vcam_->configure(&streamConfig_, size, - v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), - arg->count); + ret = vcam_->configure(&streamConfig_, size, + v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), + arg->count); if (ret < 0) return -EINVAL; @@ -409,6 +431,9 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) LOG(V4L2Compat, Debug) << "Servicing vidioc_qbuf, index = " << arg->index << " fd = " << file->efd(); + if (!hasOwnership(file)) + return -EBUSY; + if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory) || arg->index >= bufferCount_) @@ -428,6 +453,9 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) { LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd(); + if (!hasOwnership(file)) + return -EBUSY; + if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory)) return -EINVAL; @@ -462,6 +490,9 @@ int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg) if (!validateBufferType(*arg)) return -EINVAL; + if (!hasOwnership(file)) + return -EBUSY; + currentBuf_ = 0; return vcam_->streamOn(); @@ -474,6 +505,9 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) if (!validateBufferType(*arg)) return -EINVAL; + if (!hasOwnership(file) && owner_) + return -EBUSY; + int ret = vcam_->streamOff(); for (struct v4l2_buffer &buf : buffers_) @@ -532,10 +566,45 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar return ret; } -void V4L2CameraProxy::bind(int fd) +bool V4L2CameraProxy::hasOwnership(V4L2CameraFile *file) +{ + return owner_ == file; +} + +/** + * \brief Acquire exclusive ownership of the V4L2Camera + * + * \return Zero on success or if already acquired, and negative error on + * failure. + * + * This is sufficient for poll()ing for buffers. Events, however, are signaled + * on the file level, so all fds must be signaled. poll()ing from a different + * fd than the one that locks the device is a corner case, and is currently not + * supported. + */ +int V4L2CameraProxy::acquire(V4L2CameraFile *file) { - efd_ = fd; - vcam_->bind(fd); + if (owner_ == file) + return 0; + + if (owner_) + return -EBUSY; + + vcam_->bind(file->efd()); + + owner_ = file; + + return 0; +} + +void V4L2CameraProxy::release(V4L2CameraFile *file) +{ + if (owner_ != file) + return; + + vcam_->unbind(); + + owner_ = nullptr; } struct PixelFormatPlaneInfo { diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index b2197ef..2be46e6 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -33,7 +33,6 @@ public: void *mmap(void *addr, size_t length, int prot, int flags, off64_t offset); int munmap(void *addr, size_t length); - void bind(int fd); int ioctl(V4L2CameraFile *file, unsigned long request, void *arg); private: @@ -58,6 +57,10 @@ private: int vidioc_streamon(V4L2CameraFile *file, int *arg); int vidioc_streamoff(V4L2CameraFile *file, int *arg); + bool hasOwnership(V4L2CameraFile *file); + int acquire(V4L2CameraFile *file); + void release(V4L2CameraFile *file); + static unsigned int bplMultiplier(uint32_t format); static unsigned int imageSize(uint32_t format, unsigned int width, unsigned int height); @@ -80,7 +83,16 @@ private: std::unique_ptr vcam_; - int efd_; + /* + * This is the exclusive owner of this V4L2CameraProxy instance. + * When there is no owner, anybody can call any ioctl before reqbufs. + * The first file to call reqbufs with count > 0 will become the owner, + * and when the owner calls reqbufs with count = 0 it will release + * ownership. Any ioctl that is call by a non-owner while there exists + * and owner will return -EBUSY (except querycap, querybuf, try_fmt, + * g/s_priority, enum/g/s_input + */ + V4L2CameraFile *owner_; }; #endif /* __V4L2_CAMERA_PROXY_H__ */ From patchwork Tue Jun 23 19:08:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4178 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C5C18609DD for ; Tue, 23 Jun 2020 21:09:11 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="IhI9jx0p"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 43DB9329; Tue, 23 Jun 2020 21:09:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939351; bh=6GGe/InUYHXIuZVUMfE7B96sNpqlO57plP/B5g8DYo4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IhI9jx0pUL6O2X488MZ3FjvAnS8gT/ZT8Tqq8tvUVXKo5yxAgVo+KHX9+VBKlqBhz lQ+vMXxnNsnQrJFAV2x7OKkZbhgN9YiI25tYI2+9//xJo7jt4CjH/eGMElDqqdpQ8E KW23PlDzWdP7Y62qCKd9YWmYcKndaJGkO61gPfVY= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:18 +0900 Message-Id: <20200623190836.53446-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 04/22] v4l2: v4l2_camera_proxy: Free old buffers on reqbufs > 0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:12 -0000 Free buffers if any were previously allocated, at VIDIOC_REQBUFS with count > 0. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New in v3 - split from... a conglomerate of v4l2-compliance fixes patch --- src/v4l2/v4l2_camera_proxy.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index eb59d49..7262453 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -361,6 +361,15 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf return freeBuffers(); } + if (bufferCount_ > 0) { + int ret = freeBuffers(); + if (ret < 0) { + LOG(V4L2Compat, Error) + << "Failed to free libcamera buffers for re-reqbufs"; + return ret; + } + } + Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); ret = vcam_->configure(&streamConfig_, size, v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), From patchwork Tue Jun 23 19:08:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4179 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DC748609A3 for ; Tue, 23 Jun 2020 21:09:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="N0Q6R0BQ"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 807692A9; Tue, 23 Jun 2020 21:09:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939353; bh=D/5CZ6AfrseLv45TLofZILMxLDBhy8pAbHCCBX/D3h4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N0Q6R0BQmN60yol2t2oZWnwYBCghRKujTVN5hZGohO4NahwLqWkBFgqyt748zZW/2 v1PxJhjsC56Uar9EYRBJ/5AHi9XWFtpmQjircnyUTBc7ofGKR/I9hAhiqJ5IPlmlVk iqxMqep3kTCK4o45wpAIncu1tynZ5ShGiqpOuSdM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:19 +0900 Message-Id: <20200623190836.53446-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 05/22] v4l2: v4l2_camera_proxy: Clear reserved field in reqbufs X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:14 -0000 Clear the reserved field in arg struct v4l2_reqbuffers of VIDIOC_REQBUFS. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New in v3 - split from a conglomerate of v4l2-compliance fixes patch --- src/v4l2/v4l2_camera_proxy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 7262453..5acb036 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -355,6 +355,7 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf return ret; arg->capabilities = V4L2_BUF_CAP_SUPPORTS_MMAP; + memset(arg->reserved, 0, sizeof(arg->reserved)); if (arg->count == 0) { release(file); From patchwork Tue Jun 23 19:08:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4180 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 00F27609C3 for ; Tue, 23 Jun 2020 21:09:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="GXt++Gq8"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 896FA2A9; Tue, 23 Jun 2020 21:09:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939355; bh=mOaDxI+VhvgVrVx0wE/lEduoiPrhhQ7setx7YMTuRzY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GXt++Gq8ruhgZ+JVfeFcKwmh2V1p3K08zpg5vKRZ8uOQZ/EbkSg+vs2oUqbvVuCWY DVqkti0L8/naUKf/q8Hg6WWr+n4ts+jp1HT4YmwcM2pmm+SYG8LnMWFLcVUZQpcA9w KarG+FHQ3B7T6OKy1XEvnSGh2jWj7UqBxoxVIfPA= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:20 +0900 Message-Id: <20200623190836.53446-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 06/22] v4l2: v4l2_camera_proxy: Set timestamp monotonic buffer flag on reqbufs X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:16 -0000 Set buffer flag V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC at VIDIOC_REQBUFS after the buffers have been allocated. Signed-off-by: Paul Elder --- New in v3 - split from a conglomerate of v4l2-compliance fixes patch --- src/v4l2/v4l2_camera_proxy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 5acb036..7d750c0 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -412,6 +412,7 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf buf.memory = V4L2_MEMORY_MMAP; buf.m.offset = i * curV4L2Format_.fmt.pix.sizeimage; buf.index = i; + buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; buffers_[i] = buf; } From patchwork Tue Jun 23 19:08:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4181 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7AFCF609A3 for ; Tue, 23 Jun 2020 21:09:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WlPdv04A"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AD68B2A9; Tue, 23 Jun 2020 21:09:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939358; bh=DW18lGH6us0b+lJPl0hAf5Plp+HlTwzy38ePiSRZExQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WlPdv04AA9IJo3WYLEMuMjfxW9f1RwA+HYeEbksnQ40iF6nwnlXnP20Txq1KjNwer z+mvGzJtuEYTt1VP1kuSGXtM1CRln5OUTsqkgqorhdI67I/ESvFmfMcIN09j6HIXe0 yA3gbOLJSQG45S9o7FI1RFuyMvFsZ1ZRf2sZ6JIw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:21 +0900 Message-Id: <20200623190836.53446-8-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 07/22] v4l2: v4l2_camera_proxy: Check for null arg values in main ioctl handler X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:18 -0000 The ioctl handlers currently don't check if arg is null, so if it ever is, it will cause a segfault. Check that arg is null and return -EFAULT in the main vidioc ioctl handler. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - check ioctl rw flags for proper return value error - cosmetic changes Changes in v2: - moved !arg check to main ioctl handler, and added a set of supported ioctls - use !arg instead of arg == nullptr --- src/v4l2/v4l2_camera_proxy.cpp | 30 ++++++++++++++++++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 7d750c0..b7d3644 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -527,8 +528,37 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) return ret; } +const std::set V4L2CameraProxy::supportedIoctls_ = { + VIDIOC_QUERYCAP, + VIDIOC_ENUM_FMT, + VIDIOC_G_FMT, + VIDIOC_S_FMT, + VIDIOC_TRY_FMT, + VIDIOC_REQBUFS, + VIDIOC_QUERYBUF, + VIDIOC_QBUF, + VIDIOC_DQBUF, + VIDIOC_STREAMON, + VIDIOC_STREAMOFF, +}; + int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg) { + if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) { + errno = EFAULT; + return -1; + } + + if (supportedIoctls_.find(request) == supportedIoctls_.end()) { + errno = ENOTTY; + return -1; + } + + if (!arg && (_IOC_DIR(request) & _IOC_READ)) { + errno = EFAULT; + return -1; + } + int ret; switch (request) { case VIDIOC_QUERYCAP: diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 2be46e6..2582eb5 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ private: static PixelFormat v4l2ToDrm(uint32_t format); static uint32_t drmToV4L2(const PixelFormat &format); + static const std::set supportedIoctls_; + unsigned int refcount_; unsigned int index_; From patchwork Tue Jun 23 19:08:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4182 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BC9D4609A5 for ; Tue, 23 Jun 2020 21:09:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="cvlTOY9Q"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 73F8F329; Tue, 23 Jun 2020 21:09:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939361; bh=rTkYKNzZAQg8jgKw/pjKFdDFqPXwMDAUOfcKZ/i7Ah4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cvlTOY9QvYjCUZuz5V8dpINudms2QhbtTocWsu9qRZjs3uXZOP30i3DwS8GeUd/h9 PM5fdjZzcjdL43uFrrBeFdXXa1ROXAsjA7aM+TxbxXSTy8HmB4uL3MB9vhdLx6M3df FH09u3Ml3MMiq6Z0eSmwqpUnFY/9b6XI5BH5wdgw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:22 +0900 Message-Id: <20200623190836.53446-9-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 08/22] v4l2: v4l2_camera_proxy: Fix v4l2-compliance support for extended formats X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:22 -0000 Fix the following v4l2-compliance error: fail: v4l2-compliance.cpp(652): !(caps & V4L2_CAP_EXT_PIX_FORMAT) Simply add V4L2_CAP_EXT_PIX_FORMAT to capabilities in querycap. In addition, populate the necessary fields in struct v4l2_pix_format to support extended pixel formats in try_fmt and g/s_fmt, and clear the reserved field for enum_fmt. Signed-off-by: Paul Elder Acked-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- Changes in v3: - also populate xfer_func Changes in v2: - squashed the "Fix v4l2-compliance format tests" into this one, since those fixes were a necessity of this fix (plus they're related) - use _DEFAULT for ycbcr_enc and quantization --- src/v4l2/v4l2_camera_proxy.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index b7d3644..bf14ba0 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -162,6 +162,10 @@ void V4L2CameraProxy::setFmtFromConfig(StreamConfiguration &streamConfig) curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); curV4L2Format_.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + curV4L2Format_.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + curV4L2Format_.fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + curV4L2Format_.fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; + curV4L2Format_.fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; } unsigned int V4L2CameraProxy::calculateSizeImage(StreamConfiguration &streamConfig) @@ -188,7 +192,9 @@ void V4L2CameraProxy::querycap(std::shared_ptr camera) sizeof(capabilities_.bus_info)); /* \todo Put this in a header/config somewhere. */ capabilities_.version = KERNEL_VERSION(5, 2, 0); - capabilities_.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + capabilities_.device_caps = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_STREAMING + | V4L2_CAP_EXT_PIX_FORMAT; capabilities_.capabilities = capabilities_.device_caps | V4L2_CAP_DEVICE_CAPS; memset(capabilities_.reserved, 0, sizeof(capabilities_.reserved)); @@ -237,11 +243,15 @@ int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc * arg->index >= streamConfig_.formats().pixelformats().size()) return -EINVAL; + /* \todo Set V4L2_FMT_FLAG_COMPRESSED for compressed formats. */ + arg->flags = 0; /* \todo Add map from format to description. */ - utils::strlcpy(reinterpret_cast(arg->description), "Video Format Description", - sizeof(arg->description)); + utils::strlcpy(reinterpret_cast(arg->description), + "Video Format Description", sizeof(arg->description)); arg->pixelformat = drmToV4L2(streamConfig_.formats().pixelformats()[arg->index]); + memset(arg->reserved, 0, sizeof(arg->reserved)); + return 0; } @@ -281,6 +291,10 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) arg->fmt.pix.width, arg->fmt.pix.height); arg->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + arg->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + arg->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + arg->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; + arg->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; } int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) From patchwork Tue Jun 23 19:08:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4183 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D96D8609A5 for ; Tue, 23 Jun 2020 21:09:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YRxFHLHk"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6CB4A2A9; Tue, 23 Jun 2020 21:09:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939363; bh=n7o4XaM0fCDtbM/j31SgrWj8rIrdPjMgnkXHZW9aiTI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YRxFHLHkBwC3Kz6ILgVJGZme8kf/x4DOUV9Czynsih1XRn37Tx29R5jzp81qNnKwr fOCFcTZuMNeaqCHvnnPhbdmWs8/EZho0lANQW9iwL444NmxFpjWekMkJkjLxOa9laq B4WYXvMeZZd4t88zq+zB+Ik/CEhjTM5K2FHnQZ+8= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:23 +0900 Message-Id: <20200623190836.53446-10-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 09/22] v4l2: v4l2_camera_proxy: Implement VIDIOC_G/S_PRIORITY X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:24 -0000 Implement VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY. The behaviour documented in the V4L2 specification doesn't match the implementation in the Linux kernel, implement the latter. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - save the priorities of every file - they're saved in V4L2CameraFile, so save a set of these in V4L2CameraProxy - they're unique from the perspective of the proxy so set is fine - actually check the priority for s_fmt, reqbufs, streamon, streamoff, s_input, and s_priority Changes in v2: - use V4L2CameraFile instead of fd and priorities map --- src/v4l2/v4l2_camera_proxy.cpp | 59 ++++++++++++++++++++++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 5 +++ 2 files changed, 64 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index bf14ba0..361abe4 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -45,6 +45,8 @@ int V4L2CameraProxy::open(V4L2CameraFile *file) { LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd(); + files_.insert(file); + if (refcount_++) return 0; @@ -75,6 +77,8 @@ void V4L2CameraProxy::close(V4L2CameraFile *file) { LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd(); + files_.erase(file); + release(file); if (--refcount_ > 0) @@ -304,6 +308,9 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) if (!validateBufferType(arg->type)) return -EINVAL; + if (file->priority() < maxPriority()) + return -EBUSY; + int ret = acquire(file); if (ret < 0) return ret; @@ -340,6 +347,41 @@ int V4L2CameraProxy::vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *ar return 0; } +enum v4l2_priority V4L2CameraProxy::maxPriority() +{ + enum v4l2_priority maxPrio = V4L2_PRIORITY_UNSET; + for (V4L2CameraFile *f : files_) + if (f->priority() > maxPrio) + maxPrio = f->priority(); + + return maxPrio; +} + +int V4L2CameraProxy::vidioc_g_priority(V4L2CameraFile *file, enum v4l2_priority *arg) +{ + LOG(V4L2Compat, Debug) << "Servicing vidioc_g_priority fd = " << file->efd(); + + *arg = maxPriority(); + + return 0; +} + +int V4L2CameraProxy::vidioc_s_priority(V4L2CameraFile *file, enum v4l2_priority *arg) +{ + LOG(V4L2Compat, Debug) + << "Servicing vidioc_s_priority fd = " << file->efd(); + + if (*arg > V4L2_PRIORITY_RECORD) + return -EINVAL; + + if (file->priority() < maxPriority()) + return -EBUSY; + + file->setPriority(*arg); + + return 0; +} + int V4L2CameraProxy::freeBuffers() { LOG(V4L2Compat, Debug) << "Freeing libcamera bufs"; @@ -365,6 +407,9 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf LOG(V4L2Compat, Debug) << arg->count << " buffers requested "; + if (file->priority() < maxPriority()) + return -EBUSY; + int ret = acquire(file); if (ret < 0) return ret; @@ -516,6 +561,9 @@ int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg) if (!validateBufferType(*arg)) return -EINVAL; + if (file->priority() < maxPriority()) + return -EBUSY; + if (!hasOwnership(file)) return -EBUSY; @@ -531,6 +579,9 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) if (!validateBufferType(*arg)) return -EINVAL; + if (file->priority() < maxPriority()) + return -EBUSY; + if (!hasOwnership(file) && owner_) return -EBUSY; @@ -548,6 +599,8 @@ const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_G_FMT, VIDIOC_S_FMT, VIDIOC_TRY_FMT, + VIDIOC_G_PRIORITY, + VIDIOC_S_PRIORITY, VIDIOC_REQBUFS, VIDIOC_QUERYBUF, VIDIOC_QBUF, @@ -590,6 +643,12 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar case VIDIOC_TRY_FMT: ret = vidioc_try_fmt(file, static_cast(arg)); break; + case VIDIOC_G_PRIORITY: + ret = vidioc_g_priority(file, static_cast(arg)); + break; + case VIDIOC_S_PRIORITY: + ret = vidioc_s_priority(file, static_cast(arg)); + break; case VIDIOC_REQBUFS: ret = vidioc_reqbufs(file, static_cast(arg)); break; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 2582eb5..a7293bf 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -43,6 +43,7 @@ private: unsigned int calculateSizeImage(StreamConfiguration &streamConfig); void querycap(std::shared_ptr camera); void tryFormat(struct v4l2_format *arg); + enum v4l2_priority maxPriority(); void updateBuffers(); int freeBuffers(); @@ -51,6 +52,8 @@ private: int vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg); int vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg); int vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg); + int vidioc_g_priority(V4L2CameraFile *file, enum v4l2_priority *arg); + int vidioc_s_priority(V4L2CameraFile *file, enum v4l2_priority *arg); int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg); int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg); int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); @@ -84,6 +87,8 @@ private: std::vector buffers_; std::map mmaps_; + std::set files_; + std::unique_ptr vcam_; /* From patchwork Tue Jun 23 19:08:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4184 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CECD3609C3 for ; Tue, 23 Jun 2020 21:09:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="N8i0RmsI"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9F6152A9; Tue, 23 Jun 2020 21:09:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939366; bh=Rt7cXXBzV5Dyi7Lxxxhj4w7g9NUdqVw3+OklPIf9pTM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N8i0RmsIcKIzAp0E+pRjZjw1qHOrJ/fUkCB1Kx56oURVSBIgUC8ZWEcscSI9rtFL5 TC3moosozU0mkMnZIyxW7AP7VHaW2UEHA6OiF2Yv0/vYWbbLDPMrNX8h87FVnpM9YP 4QTyR1kCo47csnFTn0SqfGKqzt8cMf8Zmi8wBEbk= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:24 +0900 Message-Id: <20200623190836.53446-11-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 10/22] v4l2: v4l2_camera_proxy: Implement VIDIOC_ENUMINPUT, VIDIOC_G/S_INPUT X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:27 -0000 Implement VIDIOC_ENUMINPUT, VIDIOC_G_INPUT, and VIDIOC_S_INPUT. Only the zeroth input device is supported, and the info returned by enuminput is hardcoded and basic. This is sufficient to pass v4l2-compliance. Signed-off-by: Paul Elder Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- Changes in v3: - cosmetic changes Changes in v2: - use V4L2CameraFile instead of fd - remove arg == nullptr check as it has been moved away to the main ioctl handler --- src/v4l2/v4l2_camera_proxy.cpp | 48 ++++++++++++++++++++++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 3 +++ 2 files changed, 51 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 361abe4..7925ed1 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -382,6 +382,42 @@ int V4L2CameraProxy::vidioc_s_priority(V4L2CameraFile *file, enum v4l2_priority return 0; } +int V4L2CameraProxy::vidioc_enuminput(V4L2CameraFile *file, struct v4l2_input *arg) +{ + LOG(V4L2Compat, Debug) << "Servicing vidioc_enuminput fd = " << file->efd(); + + if (arg->index != 0) + return -EINVAL; + + memset(arg, 0, sizeof(*arg)); + + utils::strlcpy(reinterpret_cast(arg->name), + reinterpret_cast(capabilities_.card), + sizeof(arg->name)); + arg->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +int V4L2CameraProxy::vidioc_g_input(V4L2CameraFile *file, int *arg) +{ + LOG(V4L2Compat, Debug) << "Servicing vidioc_g_input fd = " << file->efd(); + + *arg = 0; + + return 0; +} + +int V4L2CameraProxy::vidioc_s_input(V4L2CameraFile *file, int *arg) +{ + LOG(V4L2Compat, Debug) << "Servicing vidioc_s_input fd = " << file->efd(); + + if (*arg != 0) + return -EINVAL; + + return 0; +} + int V4L2CameraProxy::freeBuffers() { LOG(V4L2Compat, Debug) << "Freeing libcamera bufs"; @@ -601,6 +637,9 @@ const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_TRY_FMT, VIDIOC_G_PRIORITY, VIDIOC_S_PRIORITY, + VIDIOC_ENUMINPUT, + VIDIOC_G_INPUT, + VIDIOC_S_INPUT, VIDIOC_REQBUFS, VIDIOC_QUERYBUF, VIDIOC_QBUF, @@ -649,6 +688,15 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar case VIDIOC_S_PRIORITY: ret = vidioc_s_priority(file, static_cast(arg)); break; + case VIDIOC_ENUMINPUT: + ret = vidioc_enuminput(file, static_cast(arg)); + break; + case VIDIOC_G_INPUT: + ret = vidioc_g_input(file, static_cast(arg)); + break; + case VIDIOC_S_INPUT: + ret = vidioc_s_input(file, static_cast(arg)); + break; case VIDIOC_REQBUFS: ret = vidioc_reqbufs(file, static_cast(arg)); break; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index a7293bf..bc427d4 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -54,6 +54,9 @@ private: int vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *arg); int vidioc_g_priority(V4L2CameraFile *file, enum v4l2_priority *arg); int vidioc_s_priority(V4L2CameraFile *file, enum v4l2_priority *arg); + int vidioc_enuminput(V4L2CameraFile *file, struct v4l2_input *arg); + int vidioc_g_input(V4L2CameraFile *file, int *arg); + int vidioc_s_input(V4L2CameraFile *file, int *arg); int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg); int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg); int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); From patchwork Tue Jun 23 19:08:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4185 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 34765609C7 for ; Tue, 23 Jun 2020 21:09:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="G+5LgDij"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 70D152A9; Tue, 23 Jun 2020 21:09:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939369; bh=/LnaUCHTa0ygE/ypYIqNKSst20kVWIbdT9nSxSDmlyk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G+5LgDijXa1hfp2+La8dYYG9CGsqGjc4nnBxveAMA4XrpPua2XSzIOBm+FgPGh7++ hjljv1uGAZ8MkWcUvVSItM3P4uPMXcMuoAwjdmRHVtkifadgmJVdswap2u+RqoLHR1 Oqrt4bxvbYjeil3h9hPR/Jqviqwt7kDLh/xopuRw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:25 +0900 Message-Id: <20200623190836.53446-12-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 11/22] v4l2: v4l2_camera_proxy: Implement VIDIOC_ENUM_FRAMESIZES X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:29 -0000 Implement VIDIOC_ENUM_FRAMESIZES in the V4L2 compatibility layer. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - cosmetic changes Changes in v2: - use V4L2CameraFile instead of fd - added todo for not many pipeline handlers reporting StreamFormats --- src/v4l2/v4l2_camera_proxy.cpp | 26 ++++++++++++++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 1 + 2 files changed, 27 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 7925ed1..72b21ff 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -239,6 +239,28 @@ int V4L2CameraProxy::vidioc_querycap(struct v4l2_capability *arg) return 0; } +int V4L2CameraProxy::vidioc_enum_framesizes(V4L2CameraFile *file, struct v4l2_frmsizeenum *arg) +{ + LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_framesizes fd = " << file->efd(); + + PixelFormat argFormat = v4l2ToDrm(arg->pixel_format); + /* + * \todo This might need to be expanded as few pipeline handlers + * report StreamFormats. + */ + const std::vector &frameSizes = streamConfig_.formats().sizes(argFormat); + + if (arg->index >= frameSizes.size()) + return -EINVAL; + + arg->type = V4L2_FRMSIZE_TYPE_DISCRETE; + arg->discrete.width = frameSizes[arg->index].width; + arg->discrete.height = frameSizes[arg->index].height; + memset(arg->reserved, 0, sizeof(arg->reserved)); + + return 0; +} + int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg) { LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_fmt fd = " << file->efd(); @@ -631,6 +653,7 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_QUERYCAP, + VIDIOC_ENUM_FRAMESIZES, VIDIOC_ENUM_FMT, VIDIOC_G_FMT, VIDIOC_S_FMT, @@ -670,6 +693,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar case VIDIOC_QUERYCAP: ret = vidioc_querycap(static_cast(arg)); break; + case VIDIOC_ENUM_FRAMESIZES: + ret = vidioc_enum_framesizes(file, static_cast(arg)); + break; case VIDIOC_ENUM_FMT: ret = vidioc_enum_fmt(file, static_cast(arg)); break; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index bc427d4..041f536 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -48,6 +48,7 @@ private: int freeBuffers(); int vidioc_querycap(struct v4l2_capability *arg); + int vidioc_enum_framesizes(V4L2CameraFile *file, struct v4l2_frmsizeenum *arg); int vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *arg); int vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg); int vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg); From patchwork Tue Jun 23 19:08:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4186 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A44F4609A5 for ; Tue, 23 Jun 2020 21:09:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="UKTtFR8K"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E085E2A9; Tue, 23 Jun 2020 21:09:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939371; bh=U5/+jyVlGPMStPgLAhfZIOQqy375Z8q2+TWR+pjDrUE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UKTtFR8KgIzmBreYRu1lKW/3Mi78zpTLR4zPmnS3ilZxmGmvW+c3RpBs1VNOPbLj6 t8YBYuAOIDRQsvZc1Pu5tCkFPNAl/xjicbGFya35UFvAhp3JT/BpOj8joEpMRrLFgi gPcMo/UYDih0tsBHosPq1ekYpLTiKZFCKdJ6S0+4= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:26 +0900 Message-Id: <20200623190836.53446-13-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 12/22] v4l2: v4l2_camera: Add isRunning() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:31 -0000 Add a method isRunning() to V4L2Camera so that V4L2CameraProxy can use it for checks. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - cosmetic changes Changes in v2: - replace V4L2CameraProxy::streaming_ with V4L2CameraProxy::isRunning() - moved the checks to different patches --- src/v4l2/v4l2_camera.cpp | 5 +++++ src/v4l2/v4l2_camera.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 2557320..177b1ea 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -227,3 +227,8 @@ int V4L2Camera::qbuf(unsigned int index) return 0; } + +bool V4L2Camera::isRunning() +{ + return isRunning_; +} diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 30114ed..ee53c2b 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -57,6 +57,8 @@ public: int qbuf(unsigned int index); + bool isRunning(); + Semaphore bufferSema_; private: From patchwork Tue Jun 23 19:08:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4187 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 24813609A5 for ; Tue, 23 Jun 2020 21:09:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kUV9A4uk"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2A3402A9; Tue, 23 Jun 2020 21:09:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939373; bh=7CsqpJNAdoSYAzELZPfC53gO1IqhowOnp0ri2Jjm20Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kUV9A4ukag4uOirVAhWakMTeC49MzGz/n133YiUKc6m3PSTjnk5vofvIQi/qMREJP llm0w15ljoxd+jRE9uvbENd2/vh7sOGfhUHJA6EvTYlqgXMOEyUVBYsymS1Ah37jVe kmYdaIghy+hlGpk7pCra3zzcyYDuFxmGTEDuRZjY= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:27 +0900 Message-Id: <20200623190836.53446-14-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 13/22] v4l2: v4l2_camera_proxy: Disallow dqbuf when not streaming X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:34 -0000 Make VIDIOC_DQBUF return -EINVAL if the stream is not turned on. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - move isRunning check to after taking lock New in v2 (split from "v4l2: v4l2_camera: Add isRunning()") --- src/v4l2/v4l2_camera_proxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 72b21ff..0c7232d 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -585,6 +585,9 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) if (!hasOwnership(file)) return -EBUSY; + if (!vcam_->isRunning()) + return -EINVAL; + if (!validateBufferType(arg->type) || !validateMemoryType(arg->memory)) return -EINVAL; From patchwork Tue Jun 23 19:08:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4188 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9877C609A5 for ; Tue, 23 Jun 2020 21:09:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="p7uhQ8iL"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7C0A02A9; Tue, 23 Jun 2020 21:09:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939376; bh=GXpAoz46hAsjPUdtZVPdEf6WbB5+Y2BFhz0HiD/eles=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p7uhQ8iLHZbmK3qijYVNNR584+tfthIjc05cFCsuI7FnGizAbdv5KJonQynazpfD5 Kn2Vhn4e4y59h0GlNBoS5YnmtnGwwJVTyB5b5SNXwGBVwFJuRRIaZfsThz10lM++18 ckxhqlY7C8xaDd9RHbt8sL4fffcRAW6bje8rn/KA= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:28 +0900 Message-Id: <20200623190836.53446-15-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 14/22] v4l2: v4l2_camera_proxy: noop if streamon when stream is already on X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:36 -0000 If VIDIOC_STREMAON is called when the stream is already on, do a noop. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - move isRunning check to after ownership check New in v2: (split from "v4l2: v4l2_camera: Add isRunning()") --- src/v4l2/v4l2_camera_proxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 0c7232d..06fef21 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -628,6 +628,9 @@ int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg) if (!hasOwnership(file)) return -EBUSY; + if (vcam_->isRunning()) + return 0; + currentBuf_ = 0; return vcam_->streamOn(); From patchwork Tue Jun 23 19:08:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4189 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 99E98609A5 for ; Tue, 23 Jun 2020 21:09:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Sr52AgkZ"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0274E2A9; Tue, 23 Jun 2020 21:09:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939378; bh=Yyj4xtvYW+wee9Xuq3BHsxeamh1FqaAfROOsLOxumEY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Sr52AgkZNdJ/6cgyz0IJXVTiDAvRESHUwVlwCOzDoijEQuF7plT6Egdv1tqYkLSKM ln5b6K1T5U4/UAJmAbKX95mUuAr7exyzeekpdCg5rsN4qS70NSKCEylBUuRWpZdo+J 0IDoPJXAejVNrFBZ/1T5aI9AzfRg0taiSvSd79ew= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:29 +0900 Message-Id: <20200623190836.53446-16-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 15/22] v4l2: v4l2_camera_proxy: Reset buffer flags on reqbufs 0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:38 -0000 Clear the queued and done buffer flags on VIDIOC_REQBUFS with count = 0 if the stream is not on. If the stream is on and reqbufs is called with count = 0, return -EBUSY. Note that this is contrary to what the V4L2 docs say (reqbufs 0 when streaming should also streamoff), but it is how the V4L2 implementation works. v4l2-compliance doesn't seem to care either way, however, so we cater to the implementation. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - don't streamoff in reqbufs 0; return -EBUSY instead Changes in v2: - call only the necessary components, instead of V4L2CameraProxy::vidioc_streamoff --- src/v4l2/v4l2_camera_proxy.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 06fef21..fa58585 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -444,11 +444,6 @@ int V4L2CameraProxy::freeBuffers() { LOG(V4L2Compat, Debug) << "Freeing libcamera bufs"; - int ret = vcam_->streamOff(); - if (ret < 0) { - LOG(V4L2Compat, Error) << "Failed to stop stream"; - return ret; - } vcam_->freeBuffers(); bufferCount_ = 0; @@ -476,6 +471,12 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf memset(arg->reserved, 0, sizeof(arg->reserved)); if (arg->count == 0) { + if (vcam_->isRunning()) + return -EBUSY; + + for (struct v4l2_buffer &buf : buffers_) + buf.flags &= ~(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE); + release(file); return freeBuffers(); } From patchwork Tue Jun 23 19:08:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4190 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BE849609A7 for ; Tue, 23 Jun 2020 21:09:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="T/unOmDg"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5352D2A9; Tue, 23 Jun 2020 21:09:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939380; bh=PJuPRSLIbolB5zdksKwZDo2JO1oAETllrtU3Dicb9fM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T/unOmDgrOm6sA3gTi+rJy4yly5GMauOpSpU9NTsIpFwaKvPngYxMbeA0q9jgd9nb OcNLB5aXdqfMtqm5ZxqHQ8dD8uAaLoRUeki+TqfxdRQ4d/d8knXRk2Z/YWOKvbCSLt zH4vuzJ4LRM2uRsOlinpnljOkroKBE+C4xajIdkc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:30 +0900 Message-Id: <20200623190836.53446-17-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 16/22] v4l2: v4l2_camera: Don't use libcamera::Semaphore for available buffers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:41 -0000 In V4L2, a blocked dqbuf should not not also block a streamoff. This means that on streamoff, the blocked dqbuf must return (with error). We cannot do this with the libcamera semaphore, so pull out the necessary components of a semaphore, and put them into V4L2Camera, so that dqbuf from V4L2CameraProxy can wait on a disjunct condition of the availability of the semaphore or the stopping of the stream. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - don't notify all with the lock held Changes in v2: - remove mutex for isRunning_ - use V4L2Camera::isRunning() instead of V4L2CameraProxy::streaming_ in the dqbuf ioctl handler --- src/v4l2/v4l2_camera.cpp | 30 ++++++++++++++++++++++++++++-- src/v4l2/v4l2_camera.h | 9 +++++++-- src/v4l2/v4l2_camera_proxy.cpp | 11 +++++++++-- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 177b1ea..bdf0036 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -18,7 +18,7 @@ LOG_DECLARE_CATEGORY(V4L2Compat); V4L2Camera::V4L2Camera(std::shared_ptr camera) : camera_(camera), isRunning_(false), bufferAllocator_(nullptr), - efd_(-1) + efd_(-1), bufferAvailableCount_(0) { camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete); } @@ -100,7 +100,11 @@ void V4L2Camera::requestComplete(Request *request) if (ret != sizeof(data)) LOG(V4L2Compat, Error) << "Failed to signal eventfd POLLIN"; - bufferSema_.release(); + { + MutexLocker locker(bufferMutex_); + bufferAvailableCount_++; + } + bufferCV_.notify_all(); } int V4L2Camera::configure(StreamConfiguration *streamConfigOut, @@ -144,6 +148,7 @@ int V4L2Camera::allocBuffers(unsigned int count) void V4L2Camera::freeBuffers() { Stream *stream = *camera_->streams().begin(); + bufferAllocator_->free(stream); } @@ -193,6 +198,7 @@ int V4L2Camera::streamOff() return ret == -EACCES ? -EBUSY : ret; isRunning_ = false; + bufferCV_.notify_all(); return 0; } @@ -228,6 +234,26 @@ int V4L2Camera::qbuf(unsigned int index) return 0; } +void V4L2Camera::waitForBufferAvailable() +{ + MutexLocker locker(bufferMutex_); + bufferCV_.wait(locker, [&] { + return bufferAvailableCount_ >= 1 || !isRunning_; + }); + if (isRunning_) + bufferAvailableCount_--; +} + +bool V4L2Camera::isBufferAvailable() +{ + MutexLocker locker(bufferMutex_); + if (bufferAvailableCount_ < 1) + return false; + + bufferAvailableCount_--; + return true; +} + bool V4L2Camera::isRunning() { return isRunning_; diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index ee53c2b..515e906 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -57,9 +57,10 @@ public: int qbuf(unsigned int index); - bool isRunning(); + void waitForBufferAvailable(); + bool isBufferAvailable(); - Semaphore bufferSema_; + bool isRunning(); private: void requestComplete(Request *request); @@ -76,6 +77,10 @@ private: std::deque> completedBuffers_; int efd_; + + Mutex bufferMutex_; + std::condition_variable bufferCV_; + unsigned int bufferAvailableCount_; }; #endif /* __V4L2_CAMERA_H__ */ diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index fa58585..8420e23 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -594,10 +594,17 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) return -EINVAL; if (!(file->nonBlocking())) - vcam_->bufferSema_.acquire(); - else if (!vcam_->bufferSema_.tryAcquire()) + vcam_->waitForBufferAvailable(); + else if (!vcam_->isBufferAvailable()) return -EAGAIN; + /* + * We need to check here again in case stream was turned off while we + * were blocked on waitForBufferAvailable. + */ + if (!vcam_->isRunning()) + return -EINVAL; + updateBuffers(); struct v4l2_buffer &buf = buffers_[currentBuf_]; From patchwork Tue Jun 23 19:08:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4191 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 31BAB609A5 for ; Tue, 23 Jun 2020 21:09:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oLYKeXvp"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 325F32A9; Tue, 23 Jun 2020 21:09:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939382; bh=QmBzW44/c3Lij4lDlWVU4mFM2PpO79VTOgCFGg0oEWI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oLYKeXvpSI17CT6tLHdxmE8+VrJcqyJyqYXOkBIm4D6nEFRfWDDlIhHzmDYsoNpxR LwTrrclvdSgw7Cvm9B+5MeXS2MQzO9ISdLuwu3lmBEAq43f4mrF54RAXBQLJ9wX0uY UzwjIPTxCGDGFwzO4qZLbjuH826umDd4QqjoTZAQ= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:31 +0900 Message-Id: <20200623190836.53446-18-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 17/22] v4l2: v4l2_camera: Clear pending requests on freeBuffers and streamOff X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:43 -0000 V4L2 allows buffer queueing before streamon while libcamera does not. The compatibility layer thus saves these buffers in a pending queue until streamon, and then automatically queues them. However, this pending queue is not cleared when the buffers are freed, so the following sequence of actions will cause a use-after-free: 1. queue buffers 2. free buffers - buffers from 1. stay in pending queue but have been freed 3. queue buffers 4. streamon - buffers from 1. are enqueued, then the buffers from 3. are enqueued. Use-after-free segfault when libcamera tries to handle the enqueued buffers from 1. Fix this by clearing the pending request queue upon buffers being freed. Also clear the pending request queue on streamOff, for correctness. Signed-off-by: Paul Elder Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- Changes in v3: - reorder clearing the pending request queue, to before freeing buffers, and to after checking isRunning Changes in v2: - also clear pending request queue on streamOff - clarify the issue in changelog --- src/v4l2/v4l2_camera.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index bdf0036..ee6f907 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -149,6 +149,7 @@ void V4L2Camera::freeBuffers() { Stream *stream = *camera_->streams().begin(); + pendingRequests_.clear(); bufferAllocator_->free(stream); } @@ -189,10 +190,11 @@ int V4L2Camera::streamOn() int V4L2Camera::streamOff() { - /* \todo Restore buffers to reqbufs state? */ if (!isRunning_) return 0; + pendingRequests_.clear(); + int ret = camera_->stop(); if (ret < 0) return ret == -EACCES ? -EBUSY : ret; From patchwork Tue Jun 23 19:08:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4192 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C4E23609A5 for ; Tue, 23 Jun 2020 21:09:45 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KcjDk03h"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B5C562A9; Tue, 23 Jun 2020 21:09:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939385; bh=+ldAsMt5KhKmo97FB8zt46H9a0qCr0lrgG3IYiL9Zjw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KcjDk03h5GdrFzmueTdswJmd0S0v4uHkhfew2NggCT7ArOJ+3iaahEdosCTh1+OUK 9ICJth3jjHQj/gedg8XmJhkyPOufbDqoakpXS452pB00mK43u00iAJt9T9HlI6HIJP FfbLKNa7AuOPjkhW+m7Xco5o+zbQz8uzTxMIcq/U= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:32 +0900 Message-Id: <20200623190836.53446-19-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 18/22] v4l2: v4l2_camera_proxy: Check arg->index bounds for querybuf, qbuf, dqbuf X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:46 -0000 There were no bounds checks for the index argument for VIDIOC_QUERYBUF, VIDIOC_QBUF, and VIDIOC_DQBUF. Add them. Signed-off-by: Paul Elder Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- Changes in v3: - don't check for ownership on querybuf No change in v2 --- src/v4l2/v4l2_camera_proxy.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 8420e23..0e87631 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -545,6 +545,9 @@ int V4L2CameraProxy::vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *a { LOG(V4L2Compat, Debug) << "Servicing vidioc_querybuf fd = " << file->efd(); + if (arg->index >= bufferCount_) + return -EINVAL; + if (!validateBufferType(arg->type) || arg->index >= bufferCount_) return -EINVAL; @@ -561,6 +564,9 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) LOG(V4L2Compat, Debug) << "Servicing vidioc_qbuf, index = " << arg->index << " fd = " << file->efd(); + if (arg->index >= bufferCount_) + return -EINVAL; + if (!hasOwnership(file)) return -EBUSY; @@ -583,6 +589,9 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) { LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd(); + if (arg->index >= bufferCount_) + return -EINVAL; + if (!hasOwnership(file)) return -EBUSY; From patchwork Tue Jun 23 19:08:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4193 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 42696609C2 for ; Tue, 23 Jun 2020 21:09:48 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="pK7JdXso"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7C59F2A9; Tue, 23 Jun 2020 21:09:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939388; bh=fSqw4Rrx7dHPPbC9CZfMXAd8O7L37jaB/I/6nkIjnsQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pK7JdXsoqRyit/3Qdo7xs2T277/Pcm3UBFAdyu0FAbYcF6xXH3MM3ucax4byJitzu vo9aTBNeytAbnIEttu+3hUnCyILZNf36k7wkMBl1XYuUpIiFD2woWGNymGGFlBCYII O121b67SAof8orbojKjWCufRuFZmBcJ4eRdLvXog= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:33 +0900 Message-Id: <20200623190836.53446-20-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 19/22] v4l2: v4l2_camera_proxy: Don't allow streamon if no buffers have been requested X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:48 -0000 Make VIDIOC_STREAMON return -EINVAL if no buffers have been allocated with reqbufs. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v3 New in v2 - split from "Fix v4l2-compliance streaming tests" --- src/v4l2/v4l2_camera_proxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 0e87631..dd09951 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -636,6 +636,9 @@ int V4L2CameraProxy::vidioc_streamon(V4L2CameraFile *file, int *arg) { LOG(V4L2Compat, Debug) << "Servicing vidioc_streamon fd = " << file->efd(); + if (bufferCount_ == 0) + return -EINVAL; + if (!validateBufferType(*arg)) return -EINVAL; From patchwork Tue Jun 23 19:08:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4194 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 210D6609C6 for ; Tue, 23 Jun 2020 21:09:50 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ebzGfiRp"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A107E2A9; Tue, 23 Jun 2020 21:09:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939389; bh=8coaori1SrU/VypE8oAgozo2o4zk4NkUTpLhVNG6EHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ebzGfiRp0M/CmuD9iICE2ytESXq7CSXEvP9kFZoWLsJiMtCAdL+OC/ARE9MVh/WMp 91guBizbg6BQ0MkllVb3W4Ve/eHqn20SdQaa9Ml1mEQkUm33Lv2NmCHzwFh6DeCOVC rCjg6eXIUy5Zd7udqwKpXPF8Y5D+TFkb2bOVDiu0= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:34 +0900 Message-Id: <20200623190836.53446-21-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 20/22] v4l2: v4l2_camera_proxy: Don't allow buffers to be freed if still mmaped X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:50 -0000 In VIDIOC_REQBUFS with count = 0, if the buffers are still mmaped, they should not be allowed to be freed. Add a check for this. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v3 New in v2 - split from "Fix v4l2-compliance streaming tests" --- src/v4l2/v4l2_camera_proxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index dd09951..ce0d755 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -471,6 +471,9 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf memset(arg->reserved, 0, sizeof(arg->reserved)); if (arg->count == 0) { + if (!mmaps_.empty()) + return -EBUSY; + if (vcam_->isRunning()) return -EBUSY; From patchwork Tue Jun 23 19:08:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4195 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3D2B5609A5 for ; Tue, 23 Jun 2020 21:09:52 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="V4YTo6E0"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C5BBA2A9; Tue, 23 Jun 2020 21:09:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939392; bh=YnuCaXsqVm36dOyk1e01v9xta0LWWiU3MS4aW8ZpgyQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V4YTo6E09VrRIjXUhVsA/eso6iLplNxXMzbo03yc0lw/DOhHxWiPNvyOVc30uigL6 mtfDxW61NRWMEd1HIHTHZ3qElLTzEtYrqUpFtfyArFoSsUNobLmnDyzFatMFEvxSgN twCCiqzzAPbD7lUd1dggscuCqzZr6FjnYxmO0Me0= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:35 +0900 Message-Id: <20200623190836.53446-22-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 21/22] v4l2: v4l2_camera_proxy: Fix buffer flags related to queueing X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:52 -0000 Fix buffer flags related to queueing and dequeueing: - don't allow a buffer with the same index that is already in the queue to be enqueued again - don't set the done flag on dequeueing in V4L2CameraProxy::updateBuffers() - set the flags in V4L2CameraProxy's internal buffers, and not just in the buffers returned from qbuf Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v3: - remove "set the mapped flag on enqueueing" - clean up some logic - expand commit message very slightly New in v2 - split from "Fix v4l2-compliance streaming tests" --- src/v4l2/v4l2_camera_proxy.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index ce0d755..ed3bcbc 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -219,7 +219,6 @@ void V4L2CameraProxy::updateBuffers() buf.timestamp.tv_usec = fmd.timestamp % 1000000; buf.sequence = fmd.sequence; - buf.flags |= V4L2_BUF_FLAG_DONE; break; case FrameMetadata::FrameError: buf.flags |= V4L2_BUF_FLAG_ERROR; @@ -570,6 +569,9 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) if (arg->index >= bufferCount_) return -EINVAL; + if (buffers_[arg->index].flags & V4L2_BUF_FLAG_QUEUED) + return -EINVAL; + if (!hasOwnership(file)) return -EBUSY; @@ -582,8 +584,10 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) if (ret < 0) return ret; - arg->flags |= V4L2_BUF_FLAG_QUEUED; - arg->flags &= ~V4L2_BUF_FLAG_DONE; + buffers_[arg->index].flags |= V4L2_BUF_FLAG_QUEUED; + buffers_[arg->index].flags &= ~V4L2_BUF_FLAG_DONE; + + arg->flags = buffers_[arg->index].flags; return ret; } From patchwork Tue Jun 23 19:08:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 4196 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9DD28609A5 for ; Tue, 23 Jun 2020 21:09:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="aYFYKMfd"; dkim-atps=neutral Received: from jade.rasen.tech (unknown [IPv6:2400:4051:61:600:8147:f2a2:a8c6:9087]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D82D62A9; Tue, 23 Jun 2020 21:09:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1592939394; bh=k8o6WuWrzmBNrvXuH4vQNDxdWsdjieEbXQZDGJ4Tib8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aYFYKMfdizUdEB3LEj/WS9j4AU9LmiDaW2fM2FHpDHKnazmUj9Oj7xXEFIzQOgtQg dvILgj1TUHqiFDFUQCgU9XJmWfMf4BuKKaLeQuY8Eb+XPgCmM7enG/4E+kfuDRxadS /NQZXFDC49F8Z8z767+/CZKj8PtD4c85jipjs+ss= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 24 Jun 2020 04:08:36 +0900 Message-Id: <20200623190836.53446-23-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200623190836.53446-1-paul.elder@ideasonboard.com> References: <20200623190836.53446-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 22/22] v4l2: v4l2_camera_proxy: Serialize accesses to the proxy X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Jun 2020 19:09:54 -0000 Make the V4L2 compatibility layer thread-safe by serializing accesses to the V4L2CameraProxy with a lock. Release the lock when blocking for dqbuf. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New in v3 --- src/v4l2/v4l2_camera_proxy.cpp | 21 +++++++++++++++++---- src/v4l2/v4l2_camera_proxy.h | 5 ++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index ed3bcbc..fb3a1fc 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -43,6 +43,8 @@ V4L2CameraProxy::V4L2CameraProxy(unsigned int index, int V4L2CameraProxy::open(V4L2CameraFile *file) { + MutexLocker locker(proxyMutex_); + LOG(V4L2Compat, Debug) << "Servicing open fd = " << file->efd(); files_.insert(file); @@ -75,6 +77,8 @@ int V4L2CameraProxy::open(V4L2CameraFile *file) void V4L2CameraProxy::close(V4L2CameraFile *file) { + MutexLocker locker(proxyMutex_); + LOG(V4L2Compat, Debug) << "Servicing close fd = " << file->efd(); files_.erase(file); @@ -90,6 +94,8 @@ void V4L2CameraProxy::close(V4L2CameraFile *file) void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags, off64_t offset) { + MutexLocker locker(proxyMutex_); + LOG(V4L2Compat, Debug) << "Servicing mmap"; /* \todo Validate prot and flags properly. */ @@ -124,6 +130,8 @@ void *V4L2CameraProxy::mmap(void *addr, size_t length, int prot, int flags, int V4L2CameraProxy::munmap(void *addr, size_t length) { + MutexLocker locker(proxyMutex_); + LOG(V4L2Compat, Debug) << "Servicing munmap"; auto iter = mmaps_.find(addr); @@ -592,7 +600,8 @@ int V4L2CameraProxy::vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) return ret; } -int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) +int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, + struct v4l2_buffer *arg, MutexLocker &locker) { LOG(V4L2Compat, Debug) << "Servicing vidioc_dqbuf fd = " << file->efd(); @@ -609,9 +618,11 @@ int V4L2CameraProxy::vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg) !validateMemoryType(arg->memory)) return -EINVAL; - if (!(file->nonBlocking())) + if (!(file->nonBlocking())) { + locker.unlock(); vcam_->waitForBufferAvailable(); - else if (!vcam_->isBufferAvailable()) + locker.lock(); + } else if (!vcam_->isBufferAvailable()) return -EAGAIN; /* @@ -706,6 +717,8 @@ const std::set V4L2CameraProxy::supportedIoctls_ = { int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg) { + MutexLocker locker(proxyMutex_); + if (!arg && (_IOC_DIR(request) & _IOC_WRITE)) { errno = EFAULT; return -1; @@ -766,7 +779,7 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar ret = vidioc_qbuf(file, static_cast(arg)); break; case VIDIOC_DQBUF: - ret = vidioc_dqbuf(file, static_cast(arg)); + ret = vidioc_dqbuf(file, static_cast(arg), locker); break; case VIDIOC_STREAMON: ret = vidioc_streamon(file, static_cast(arg)); diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 041f536..b6d2c2c 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -61,7 +61,7 @@ private: int vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuffers *arg); int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg); int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); - int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); + int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg, MutexLocker &locker); int vidioc_streamon(V4L2CameraFile *file, int *arg); int vidioc_streamoff(V4L2CameraFile *file, int *arg); @@ -105,6 +105,9 @@ private: * g/s_priority, enum/g/s_input */ V4L2CameraFile *owner_; + + /* This mutex is to serialize access to the proxy. */ + Mutex proxyMutex_; }; #endif /* __V4L2_CAMERA_PROXY_H__ */