From patchwork Wed Jun 3 14:16:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 3909 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2F9996116F for ; Wed, 3 Jun 2020 16:16:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="iLSk7tfQ"; dkim-atps=neutral Received: from emerald.amanokami.net (fs76eef344.knge213.ap.nuro.jp [118.238.243.68]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 093B027C; Wed, 3 Jun 2020 16:16:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1591193789; bh=R0WJ9U03iK+gB9VcUQHl5r54uddRL1IDSrncqefwfms=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iLSk7tfQ3WRXePchZlLXpIDhncKJxg3y+mvLrKMFIGJU5e/ow6mDZiLM832IMMJbo 5J6hwAwoC8C/emrdOl2g0grMC6O3RzqKJ5JCIQwy6ZesI3sFmMZz6ZmKkA5N7FU1Ys g4B/VUz+SBRcQ/Qsr77xgMfrcIPOZNF5V+IVqojs= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Jun 2020 23:16:09 +0900 Message-Id: <20200603141609.18584-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200603141609.18584-1-paul.elder@ideasonboard.com> References: <20200603141609.18584-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/5] v4l2: v4l2_compat: Add sockets to support polling 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: Wed, 03 Jun 2020 14:16:30 -0000 To support polling, we need to be able to signal when data is available to be read (POLLIN), as well as events (POLLPRI). To allow signaling POLLPRI specifically, change eventfd to a pair of sockets. After adding the socketpair, use the socketpair to signal POLLIN by writing a byte to the socket, and read the byte away upon VIDIOC_DQBUF to clear the handled POLLIN. Although POLLPRI is not actually implemented, since we don't support events, the facilities are in place. The implementation for signaling and clearing POLLPRI is the same as for POLLIN, except that we would send and receive an out-of-band byte through the socket. Signed-off-by: Paul Elder --- src/v4l2/v4l2_camera.cpp | 13 +++++++++++++ src/v4l2/v4l2_camera.h | 3 +++ src/v4l2/v4l2_camera_proxy.cpp | 14 ++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 4 ++++ src/v4l2/v4l2_compat_manager.cpp | 22 ++++++++++++++++------ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 4da01a45..ecbc87ec 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -8,6 +8,9 @@ #include "v4l2_camera.h" #include +#include +#include +#include #include "libcamera/internal/log.h" @@ -51,6 +54,13 @@ void V4L2Camera::close() bufferAllocator_ = nullptr; camera_->release(); + + ::close(sockfd_); +} + +void V4L2Camera::bind(int sockfd) +{ + sockfd_ = sockfd; } void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig) @@ -85,6 +95,9 @@ void V4L2Camera::requestComplete(Request *request) bufferLock_.unlock(); bufferSema_.release(); + + char tmp = 0; + ::send(sockfd_, &tmp, 1, 0); } int V4L2Camera::configure(StreamConfiguration *streamConfigOut, diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 303eda44..1ad040c1 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -39,6 +39,7 @@ public: int open(); void close(); + void bind(int sockfd); void getStreamConfig(StreamConfiguration *streamConfig); std::vector completedBuffers(); @@ -70,6 +71,8 @@ private: std::deque> pendingRequests_; std::deque> completedBuffers_; + + int sockfd_; }; #endif /* __V4L2_CAMERA_H__ */ diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index f84982a2..c9d7945a 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include #include @@ -451,6 +454,11 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg) currentBuf_ = (currentBuf_ + 1) % bufferCount_; + char tmp; + int ret = ::recv(sockfd_, &tmp, 1, 0); + if (ret < 1) + return -EBUSY; + return 0; } @@ -529,6 +537,12 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg) return ret; } +void V4L2CameraProxy::bind(int sockfds[2]) +{ + sockfd_ = sockfds[0]; + vcam_->bind(sockfds[1]); +} + struct PixelFormatPlaneInfo { unsigned int bitsPerPixel; unsigned int hSubSampling; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index af9f9bbe..251b14a8 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -33,6 +33,8 @@ public: int ioctl(unsigned long request, void *arg); + void bind(int sockfds[2]); + private: bool validateBufferType(uint32_t type); bool validateMemoryType(uint32_t memory); @@ -77,6 +79,8 @@ private: std::map mmaps_; std::unique_ptr vcam_; + + int sockfd_; }; #endif /* __V4L2_CAMERA_PROXY_H__ */ diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 2338a0ee..b6e84866 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -155,15 +155,25 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod if (ret < 0) return ret; - int efd = eventfd(0, oflag & (O_CLOEXEC | O_NONBLOCK)); - if (efd < 0) { + int sockets[2]; + ret = socketpair(AF_UNIX, + SOCK_STREAM + | ((oflag & O_CLOEXEC) ? SOCK_CLOEXEC : 0) + | ((oflag & O_NONBLOCK) ? SOCK_NONBLOCK : 0), + 0, sockets); + if (ret) { + int err = errno; proxy->close(); - return efd; + errno = err; + + return ret; } - devices_.emplace(efd, proxy); + proxy->bind(sockets); + + devices_.emplace(sockets[0], proxy); - return efd; + return sockets[0]; } int V4L2CompatManager::dup(int oldfd)