From a1e04617f81a8b5c8b3103b509117bb672a3603b Mon Sep 17 00:00:00 2001 From: jihandong Date: Tue, 31 Jan 2023 17:23:28 +0800 Subject: [PATCH] drivers/video/video: add poll support to capture support part of Linux std: https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/func-poll.html Capture devices set the POLLIN and POLLRDNORM flags in the revents field Signed-off-by: jihandong --- drivers/video/video.c | 54 +++++++++++++++++++++++++++++++++ drivers/video/video_framebuff.c | 5 +++ drivers/video/video_framebuff.h | 2 ++ 3 files changed, 61 insertions(+) diff --git a/drivers/video/video.c b/drivers/video/video.c index ad7d20cc6f..4c8ee4c6a3 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -119,6 +119,7 @@ struct video_type_inf_s struct v4l2_fract frame_interval; video_framebuff_t bufinf; FAR uint8_t *bufheap; /* for V4L2_MEMORY_MMAP buffers */ + FAR struct pollfd *fds; uint32_t seqnum; }; @@ -200,6 +201,8 @@ static ssize_t video_write(FAR struct file *filep, static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int video_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map); +static int video_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); /* Common function */ @@ -290,6 +293,8 @@ static const struct file_operations g_video_fops = NULL, /* seek */ video_ioctl, /* ioctl */ video_mmap, /* mmap */ + NULL, /* truncate */ + video_poll, /* poll */ }; static bool g_video_initialized = false; @@ -3154,6 +3159,53 @@ static int video_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map) return ret; } +static int video_poll(FAR struct file *filep, struct pollfd *fds, bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR video_mng_t *priv = (FAR video_mng_t *)inode->i_private; + FAR video_type_inf_t *type_inf; + enum v4l2_buf_type buf_type; + irqstate_t flags; + + buf_type = priv->still_inf.state == VIDEO_STATE_CAPTURE ? + V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; + + type_inf = get_video_type_inf(priv, buf_type); + if (type_inf == NULL) + { + return -EINVAL; + } + + flags = enter_critical_section(); + + if (setup) + { + if (type_inf->fds == NULL) + { + type_inf->fds = fds; + fds->priv = &type_inf->fds; + if (!video_framebuff_is_empty(&type_inf->bufinf)) + { + poll_notify(&type_inf->fds, 1, POLLIN); + } + } + else + { + leave_critical_section(flags); + return -EBUSY; + } + } + else if (fds->priv) + { + type_inf->fds = NULL; + fds->priv = NULL; + } + + leave_critical_section(flags); + + return OK; +} + static FAR void *video_register(FAR const char *devpath) { FAR video_mng_t *priv; @@ -3259,6 +3311,8 @@ static int video_complete_capture(uint8_t err_code, uint32_t datasize, return -EINVAL; } + poll_notify(&type_inf->fds, 1, POLLIN); + if (err_code == 0) { type_inf->bufinf.vbuf_curr->buf.flags = 0; diff --git a/drivers/video/video_framebuff.c b/drivers/video/video_framebuff.c index bb4a2ecf9f..fc66745e9f 100644 --- a/drivers/video/video_framebuff.c +++ b/drivers/video/video_framebuff.c @@ -120,6 +120,11 @@ int video_framebuff_realloc_container(video_framebuff_t *fbuf, int sz) return OK; } +int video_framebuff_is_empty(video_framebuff_t *fbuf) +{ + return fbuf->vbuf_top == NULL || fbuf->vbuf_top == fbuf->vbuf_next; +} + vbuf_container_t *video_framebuff_get_container(video_framebuff_t *fbuf) { vbuf_container_t *ret; diff --git a/drivers/video/video_framebuff.h b/drivers/video/video_framebuff.h index cf2bbbb4bb..a4183a5f9c 100644 --- a/drivers/video/video_framebuff.h +++ b/drivers/video/video_framebuff.h @@ -71,6 +71,8 @@ vbuf_container_t *video_framebuff_get_container (video_framebuff_t *fbuf); void video_framebuff_free_container (video_framebuff_t *fbuf, vbuf_container_t *cnt); +int video_framebuff_is_empty + (video_framebuff_t *fbuf); void video_framebuff_queue_container (video_framebuff_t *fbuf, vbuf_container_t *tgt); vbuf_container_t *video_framebuff_dq_valid_container