From 117cd47e08db4e31d2f966cb4b22987d3e5d6bb7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 May 2018 11:42:47 +0300 Subject: v4l2: Split buffer allocation and mapping Not all use cases of V4L2_MEMORY_MMAP require mapping buffers to userspace. Separate the allocation and mapping to allow usage of unmapped buffers. Signed-off-by: Laurent Pinchart --- v4l2.c | 92 ++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'v4l2.c') diff --git a/v4l2.c b/v4l2.c index 8d5e847..4484acb 100644 --- a/v4l2.c +++ b/v4l2.c @@ -506,13 +506,15 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype, unsigned int nbufs) { struct v4l2_requestbuffers rb; - struct v4l2_buffer buf; unsigned int i; int ret; if (dev->nbufs != 0) return -EBUSY; + if (memtype != V4L2_MEMORY_MMAP && memtype != V4L2_MEMORY_USERPTR) + return -EINVAL; + /* Request the buffers from the driver. */ memset(&rb, 0, sizeof rb); rb.count = nbufs; @@ -551,52 +553,6 @@ int v4l2_alloc_buffers(struct v4l2_device *dev, enum v4l2_memory memtype, for (i = 0; i < dev->nbufs; ++i) dev->buffers[i].index = i; - /* Map the buffers. */ - for (i = 0; i < rb.count; ++i) { - memset(&buf, 0, sizeof buf); - buf.index = i; - buf.type = dev->type; - buf.memory = memtype; - ret = ioctl(dev->fd, VIDIOC_QUERYBUF, &buf); - if (ret < 0) { - printf("%s: unable to query buffer %u (%d).\n", - dev->name, i, errno); - ret = -errno; - goto done; - } - - switch (memtype) { - case V4L2_MEMORY_MMAP: - dev->buffers[i].mem = mmap(0, buf.length, PROT_READ | PROT_WRITE, - MAP_SHARED, dev->fd, buf.m.offset); - if (dev->buffers[i].mem == MAP_FAILED) { - printf("%s: unable to map buffer %u (%d)\n", - dev->name, i, errno); - ret = -errno; - goto done; - } - dev->buffers[i].size = buf.length; - printf("%s: buffer %u mapped at address %p.\n", - dev->name, i, dev->buffers[i].mem); - break; - - case V4L2_MEMORY_USERPTR: - if (dev->buffers[i].size < buf.length) { - printf("%s: buffer %u too small (%u bytes required, " - "%u bytes available.\n", dev->name, i, - buf.length, dev->buffers[i].size); - ret = -EINVAL; - goto done; - } - - printf("%s: buffer %u valid.\n", dev->name, i); - break; - - default: - break; - } - } - ret = 0; done: @@ -653,6 +609,48 @@ int v4l2_free_buffers(struct v4l2_device *dev) return 0; } +int v4l2_mmap_buffers(struct v4l2_device *dev) +{ + unsigned int i; + int ret; + + if (dev->memtype != V4L2_MEMORY_MMAP) + return -EINVAL; + + for (i = 0; i < dev->nbufs; ++i) { + struct v4l2_video_buffer *buffer = &dev->buffers[i]; + struct v4l2_buffer buf = { + .index = i, + .type = dev->type, + .memory = dev->memtype, + }; + void *mem; + + ret = ioctl(dev->fd, VIDIOC_QUERYBUF, &buf); + if (ret < 0) { + printf("%s: unable to query buffer %u (%d).\n", + dev->name, i, errno); + return -errno; + } + + mem = mmap(0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, + dev->fd, buf.m.offset); + if (mem == MAP_FAILED) { + printf("%s: unable to map buffer %u (%d)\n", + dev->name, i, errno); + return -errno; + } + + buffer->mem = mem; + buffer->size = buf.length; + + printf("%s: buffer %u mapped at address %p.\n", dev->name, i, + mem); + } + + return 0; +} + int v4l2_dequeue_buffer(struct v4l2_device *dev, struct v4l2_video_buffer *buffer) { struct v4l2_buffer buf; -- cgit v1.2.3