v4l2: v4l2_compat: Add eventfd signaling to support polling
To support polling, we need to be able to signal when data is available to be read (POLLIN), as well as events (POLLPRI). Add the necessary calls to eventfd to allow signaling POLLIN. We signal POLLIN by writing writing to the eventfd, and clear it by reading from the eventfd, upon VIDIOC_DQBUF. Note that eventfd does not support signaling POLLPRI, so we don't yet support V4L2 events. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
5c5481911a
commit
8df593841d
5 changed files with 32 additions and 1 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include "v4l2_camera.h"
|
#include "v4l2_camera.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libcamera/internal/log.h"
|
#include "libcamera/internal/log.h"
|
||||||
|
|
||||||
|
@ -53,6 +54,11 @@ void V4L2Camera::close()
|
||||||
camera_->release();
|
camera_->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V4L2Camera::bind(int efd)
|
||||||
|
{
|
||||||
|
efd_ = efd;
|
||||||
|
}
|
||||||
|
|
||||||
void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig)
|
void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig)
|
||||||
{
|
{
|
||||||
*streamConfig = config_->at(0);
|
*streamConfig = config_->at(0);
|
||||||
|
@ -84,6 +90,9 @@ void V4L2Camera::requestComplete(Request *request)
|
||||||
completedBuffers_.push_back(std::move(metadata));
|
completedBuffers_.push_back(std::move(metadata));
|
||||||
bufferLock_.unlock();
|
bufferLock_.unlock();
|
||||||
|
|
||||||
|
uint64_t data = 1;
|
||||||
|
::write(efd_, &data, sizeof(data));
|
||||||
|
|
||||||
bufferSema_.release();
|
bufferSema_.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
int open();
|
int open();
|
||||||
void close();
|
void close();
|
||||||
|
void bind(int efd);
|
||||||
void getStreamConfig(StreamConfiguration *streamConfig);
|
void getStreamConfig(StreamConfiguration *streamConfig);
|
||||||
std::vector<Buffer> completedBuffers();
|
std::vector<Buffer> completedBuffers();
|
||||||
|
|
||||||
|
@ -70,6 +71,8 @@ private:
|
||||||
|
|
||||||
std::deque<std::unique_ptr<Request>> pendingRequests_;
|
std::deque<std::unique_ptr<Request>> pendingRequests_;
|
||||||
std::deque<std::unique_ptr<Buffer>> completedBuffers_;
|
std::deque<std::unique_ptr<Buffer>> completedBuffers_;
|
||||||
|
|
||||||
|
int efd_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __V4L2_CAMERA_H__ */
|
#endif /* __V4L2_CAMERA_H__ */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/object.h>
|
#include <libcamera/object.h>
|
||||||
|
@ -451,6 +452,9 @@ int V4L2CameraProxy::vidioc_dqbuf(struct v4l2_buffer *arg)
|
||||||
|
|
||||||
currentBuf_ = (currentBuf_ + 1) % bufferCount_;
|
currentBuf_ = (currentBuf_ + 1) % bufferCount_;
|
||||||
|
|
||||||
|
uint64_t data;
|
||||||
|
::read(efd_, &data, sizeof(data));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,6 +533,12 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V4L2CameraProxy::bind(int fd)
|
||||||
|
{
|
||||||
|
efd_ = fd;
|
||||||
|
vcam_->bind(fd);
|
||||||
|
}
|
||||||
|
|
||||||
struct PixelFormatPlaneInfo {
|
struct PixelFormatPlaneInfo {
|
||||||
unsigned int bitsPerPixel;
|
unsigned int bitsPerPixel;
|
||||||
unsigned int hSubSampling;
|
unsigned int hSubSampling;
|
||||||
|
|
|
@ -33,6 +33,8 @@ public:
|
||||||
|
|
||||||
int ioctl(unsigned long request, void *arg);
|
int ioctl(unsigned long request, void *arg);
|
||||||
|
|
||||||
|
void bind(int fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool validateBufferType(uint32_t type);
|
bool validateBufferType(uint32_t type);
|
||||||
bool validateMemoryType(uint32_t memory);
|
bool validateMemoryType(uint32_t memory);
|
||||||
|
@ -77,6 +79,8 @@ private:
|
||||||
std::map<void *, unsigned int> mmaps_;
|
std::map<void *, unsigned int> mmaps_;
|
||||||
|
|
||||||
std::unique_ptr<V4L2Camera> vcam_;
|
std::unique_ptr<V4L2Camera> vcam_;
|
||||||
|
|
||||||
|
int efd_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __V4L2_CAMERA_PROXY_H__ */
|
#endif /* __V4L2_CAMERA_PROXY_H__ */
|
||||||
|
|
|
@ -155,12 +155,17 @@ int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mod
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
int efd = eventfd(0, oflag & (O_CLOEXEC | O_NONBLOCK));
|
int efd = eventfd(0, EFD_SEMAPHORE |
|
||||||
|
((oflag & O_CLOEXEC) ? EFD_CLOEXEC : 0) |
|
||||||
|
((oflag & O_NONBLOCK) ? EFD_NONBLOCK : 0));
|
||||||
if (efd < 0) {
|
if (efd < 0) {
|
||||||
|
int err = errno;
|
||||||
proxy->close();
|
proxy->close();
|
||||||
|
errno = err;
|
||||||
return efd;
|
return efd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy->bind(efd);
|
||||||
devices_.emplace(efd, proxy);
|
devices_.emplace(efd, proxy);
|
||||||
|
|
||||||
return efd;
|
return efd;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue