diff options
Diffstat (limited to 'src/v4l2')
-rw-r--r-- | src/v4l2/v4l2_camera.cpp | 12 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.h | 8 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.cpp | 27 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.h | 1 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat.cpp | 76 | ||||
-rw-r--r-- | src/v4l2/v4l2_compat_manager.cpp | 1 |
6 files changed, 96 insertions, 29 deletions
diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 0f3b862f..94d138cd 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -12,13 +12,15 @@ #include <libcamera/base/log.h> +#include <libcamera/control_ids.h> + using namespace libcamera; LOG_DECLARE_CATEGORY(V4L2Compat) V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera) - : camera_(camera), isRunning_(false), bufferAllocator_(nullptr), - efd_(-1), bufferAvailableCount_(0) + : camera_(camera), controls_(controls::controls), isRunning_(false), + bufferAllocator_(nullptr), efd_(-1), bufferAvailableCount_(0) { camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete); } @@ -202,10 +204,12 @@ int V4L2Camera::streamOn() if (isRunning_) return 0; - int ret = camera_->start(); + int ret = camera_->start(&controls_); if (ret < 0) return ret == -EACCES ? -EBUSY : ret; + controls_.clear(); + isRunning_ = true; for (Request *req : pendingRequests_) { @@ -265,6 +269,8 @@ int V4L2Camera::qbuf(unsigned int index) return 0; } + request->controls().merge(std::move(controls_)); + ret = camera_->queueRequest(request); if (ret < 0) { LOG(V4L2Compat, Error) << "Can't queue request"; diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 278cc33e..e54371fb 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -8,13 +8,15 @@ #pragma once #include <deque> -#include <utility> +#include <memory> +#include <vector> #include <libcamera/base/mutex.h> #include <libcamera/base/semaphore.h> #include <libcamera/base/shared_fd.h> #include <libcamera/camera.h> +#include <libcamera/controls.h> #include <libcamera/framebuffer.h> #include <libcamera/framebuffer_allocator.h> @@ -49,6 +51,8 @@ public: const libcamera::Size &size, libcamera::StreamConfiguration *streamConfigOut); + libcamera::ControlList &controls() { return controls_; } + int allocBuffers(unsigned int count); void freeBuffers(); int getBufferFd(unsigned int index); @@ -70,6 +74,8 @@ private: std::shared_ptr<libcamera::Camera> camera_; std::unique_ptr<libcamera::CameraConfiguration> config_; + libcamera::ControlList controls_; + bool isRunning_; libcamera::Mutex bufferLock_; diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 3f7c00a2..5ac8df4c 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -8,7 +8,6 @@ #include "v4l2_camera_proxy.h" #include <algorithm> -#include <array> #include <errno.h> #include <numeric> #include <set> @@ -23,9 +22,11 @@ #include <libcamera/base/utils.h> #include <libcamera/camera.h> +#include <libcamera/control_ids.h> +#include <libcamera/controls.h> #include <libcamera/formats.h> -#include "libcamera/internal/formats.h" +#include "libcamera/internal/v4l2_pixelformat.h" #include "v4l2_camera.h" #include "v4l2_camera_file.h" @@ -34,6 +35,7 @@ #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) using namespace libcamera; +using namespace std::literals::chrono_literals; LOG_DECLARE_CATEGORY(V4L2Compat) @@ -756,6 +758,23 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) return ret; } +int V4L2CameraProxy::vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg) +{ + LOG(V4L2Compat, Debug) + << "[" << file->description() << "] " << __func__ << "()"; + + if (!validateBufferType(arg->type)) + return -EINVAL; + + struct v4l2_fract *timeperframe = &arg->parm.capture.timeperframe; + utils::Duration frameDuration = 1.0s * timeperframe->numerator / timeperframe->denominator; + + int64_t uDuration = frameDuration.get<std::micro>(); + vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration }); + + return 0; +} + const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = { VIDIOC_QUERYCAP, VIDIOC_ENUM_FRAMESIZES, @@ -776,6 +795,7 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = { VIDIOC_EXPBUF, VIDIOC_STREAMON, VIDIOC_STREAMOFF, + VIDIOC_S_PARM, }; int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void *arg) @@ -863,6 +883,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void case VIDIOC_STREAMOFF: ret = vidioc_streamoff(file, static_cast<int *>(arg)); break; + case VIDIOC_S_PARM: + ret = vidioc_s_parm(file, static_cast<struct v4l2_streamparm *>(arg)); + break; default: ret = -ENOTTY; break; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 3d8784df..c957db53 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -67,6 +67,7 @@ private: int vidioc_expbuf(V4L2CameraFile *file, struct v4l2_exportbuffer *arg); int vidioc_streamon(V4L2CameraFile *file, int *arg); int vidioc_streamoff(V4L2CameraFile *file, int *arg); + int vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg); bool hasOwnership(V4L2CameraFile *file); int acquire(V4L2CameraFile *file); diff --git a/src/v4l2/v4l2_compat.cpp b/src/v4l2/v4l2_compat.cpp index 8a44403e..ff833f57 100644 --- a/src/v4l2/v4l2_compat.cpp +++ b/src/v4l2/v4l2_compat.cpp @@ -7,12 +7,14 @@ #include "v4l2_compat_manager.h" -#include <errno.h> +#include <assert.h> #include <fcntl.h> #include <stdarg.h> +#include <sys/ioctl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> +#include <unistd.h> #include <libcamera/base/utils.h> @@ -28,71 +30,97 @@ using namespace libcamera; va_end(ap); \ } +namespace { + +/* + * Determine if the flags require a further mode arguments that needs to be + * parsed from va_args. + */ +bool needs_mode(int flags) +{ + return (flags & O_CREAT) || ((flags & O_TMPFILE) == O_TMPFILE); +} + +} /* namespace */ + extern "C" { LIBCAMERA_PUBLIC int open(const char *path, int oflag, ...) { mode_t mode = 0; - if (oflag & O_CREAT || oflag & O_TMPFILE) + if (needs_mode(oflag)) extract_va_arg(mode_t, mode, oflag); return V4L2CompatManager::instance()->openat(AT_FDCWD, path, oflag, mode); } -/* _FORTIFY_SOURCE redirects open to __open_2 */ -LIBCAMERA_PUBLIC int __open_2(const char *path, int oflag) -{ - return open(path, oflag); -} - #ifndef open64 LIBCAMERA_PUBLIC int open64(const char *path, int oflag, ...) { mode_t mode = 0; - if (oflag & O_CREAT || oflag & O_TMPFILE) + if (needs_mode(oflag)) extract_va_arg(mode_t, mode, oflag); return V4L2CompatManager::instance()->openat(AT_FDCWD, path, oflag | O_LARGEFILE, mode); } - -LIBCAMERA_PUBLIC int __open64_2(const char *path, int oflag) -{ - return open64(path, oflag); -} #endif LIBCAMERA_PUBLIC int openat(int dirfd, const char *path, int oflag, ...) { mode_t mode = 0; - if (oflag & O_CREAT || oflag & O_TMPFILE) + if (needs_mode(oflag)) extract_va_arg(mode_t, mode, oflag); return V4L2CompatManager::instance()->openat(dirfd, path, oflag, mode); } -LIBCAMERA_PUBLIC int __openat_2(int dirfd, const char *path, int oflag) -{ - return openat(dirfd, path, oflag); -} - #ifndef openat64 LIBCAMERA_PUBLIC int openat64(int dirfd, const char *path, int oflag, ...) { mode_t mode = 0; - if (oflag & O_CREAT || oflag & O_TMPFILE) + if (needs_mode(oflag)) extract_va_arg(mode_t, mode, oflag); return V4L2CompatManager::instance()->openat(dirfd, path, oflag | O_LARGEFILE, mode); } +#endif + +/* + * _FORTIFY_SOURCE redirects open* to __open*_2. Disable the + * -Wmissing-declarations warnings, as the functions won't be declared if + * _FORTIFY_SOURCE is not in use. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-declarations" + +LIBCAMERA_PUBLIC int __open_2(const char *path, int oflag) +{ + assert(!needs_mode(oflag)); + return open(path, oflag); +} + +LIBCAMERA_PUBLIC int __open64_2(const char *path, int oflag) +{ + assert(!needs_mode(oflag)); + return open64(path, oflag); +} + +LIBCAMERA_PUBLIC int __openat_2(int dirfd, const char *path, int oflag) +{ + assert(!needs_mode(oflag)); + return openat(dirfd, path, oflag); +} LIBCAMERA_PUBLIC int __openat64_2(int dirfd, const char *path, int oflag) { + assert(!needs_mode(oflag)); return openat64(dirfd, path, oflag); } -#endif + +#pragma GCC diagnostic pop LIBCAMERA_PUBLIC int dup(int oldfd) { @@ -125,7 +153,11 @@ LIBCAMERA_PUBLIC int munmap(void *addr, size_t length) return V4L2CompatManager::instance()->munmap(addr, length); } +#if HAVE_POSIX_IOCTL +LIBCAMERA_PUBLIC int ioctl(int fd, int request, ...) +#else LIBCAMERA_PUBLIC int ioctl(int fd, unsigned long request, ...) +#endif { void *arg; extract_va_arg(void *, arg, request); diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 6a00afb5..f53fb300 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -10,7 +10,6 @@ #include <dlfcn.h> #include <fcntl.h> #include <map> -#include <stdarg.h> #include <string.h> #include <sys/eventfd.h> #include <sys/mman.h> |