[PATCH 1/1] libcamera: Add request API support for media controller device

Harvey Yang chenghaoyang at chromium.org
Mon Sep 23 08:02:35 CEST 2024


From: Han-Lin Chen <hanlinchen at chromium.org>

This patch adds `allocateRequests` with MEDIA_IOC_REQUEST_ALLOC
, `queueRequest` with MEDIA_REQUEST_IOC_QUEUE, and `reInitRequest`
with MEDIA_REQUEST_IOC_REINIT.

Signed-off-by: Han-Lin Chen <hanlinchen at chromium.org>
Co-developed-by: Harvey Yang <chenghaoyang at chromium.org>
---
 include/libcamera/internal/media_device.h |  4 ++
 src/libcamera/media_device.cpp            | 87 +++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/include/libcamera/internal/media_device.h b/include/libcamera/internal/media_device.h
index e412d3a0..8f54dd12 100644
--- a/include/libcamera/internal/media_device.h
+++ b/include/libcamera/internal/media_device.h
@@ -53,6 +53,10 @@ public:
 	MediaLink *link(const MediaPad *source, const MediaPad *sink);
 	int disableLinks();
 
+	int allocateRequests(unsigned int count, std::vector<UniqueFD> &requests);
+	int queueRequest(int requestFd);
+	int reInitRequest(int requestFd);
+
 	Signal<> disconnected;
 
 protected:
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index bd054552..47b75809 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -9,6 +9,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <stdint.h>
 #include <string>
 #include <string.h>
@@ -836,4 +837,90 @@ int MediaDevice::setupLink(const MediaLink *link, unsigned int flags)
 	return 0;
 }
 
+/**
+ * \brief Allocate \a count requests with ioctl
+ * \param[in] count The number of requests to be allocated
+ * \param[out] requests The request file descriptors to be returned
+ *
+ * This function returns request file descriptors if the MediaDevice supports
+ * requests. The file descriptors can then be queued and re-inited afterwards.
+ *
+ * \sa queueRequest(int requestFd)
+ * \sa reInitRequest(int requestFd)
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int MediaDevice::allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
+{
+	for (unsigned int i = 0; i < count; i++) {
+		int fd;
+		int ret = ioctl(fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &fd);
+		if (ret) {
+			LOG(MediaDevice, Error) << "Allocate request failed "
+						<< strerror(-ret);
+			return -EBUSY;
+		}
+		requests.emplace_back(fd);
+	}
+
+	return 0;
+}
+
+/**
+ * \brief Queue a request with ioctl
+ * \param[in] requestFd The request file descriptor
+ *
+ * This function queues a request that was allocated before.
+ *
+ * \sa allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
+ * \sa reInitRequest(int requestFd)
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int MediaDevice::queueRequest(int requestFd)
+{
+	int ret = ioctl(requestFd, MEDIA_REQUEST_IOC_QUEUE, NULL);
+	if (ret)
+		LOG(MediaDevice, Error) << "QueueRequest fd " << requestFd
+					<< "failed: " << strerror(-ret);
+	return ret;
+}
+
+/**
+ * \brief Re-init a request with ioctl
+ * \param[in] requestFd The request file descriptor
+ *
+ * This function recycles a request that was allocated and queued before. It
+ * polls on \a requestFd to ensure the request is completed, and reinits the
+ * request.
+ *
+ * \sa allocateRequests(unsigned int count, std::vector<UniqueFD> &requests)
+ * \sa queueRequest(int requestFd)
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int MediaDevice::reInitRequest(int requestFd)
+{
+	struct pollfd pfd;
+
+	pfd.fd = requestFd;
+	pfd.events = POLLPRI;
+
+	int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 300));
+	if (ret < 0)
+		LOG(MediaDevice, Error) << "The request " << requestFd
+					<< " polled failed: " << strerror(-ret);
+	else if (ret == 0)
+		LOG(MediaDevice, Error) << "The request " << requestFd
+					<< " polled timeout: " << strerror(-ret);
+
+	ret = ::ioctl(requestFd, MEDIA_REQUEST_IOC_REINIT, NULL);
+	if (ret)
+		LOG(MediaDevice, Error) << "The request " << requestFd
+					<< " is queued but not yet completed: "
+					<< strerror(-ret);
+
+	return ret;
+}
+
 } /* namespace libcamera */
-- 
2.46.0.792.g87dc391469-goog



More information about the libcamera-devel mailing list