diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-22 11:42:47 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-22 11:42:47 +0300 |
commit | 117cd47e08db4e31d2f966cb4b22987d3e5d6bb7 (patch) | |
tree | 4fb5396cd3c3d063aec59ef1e9e1066325f33a71 /v4l2.c | |
parent | ab92702a44f8521d5deef3e2ac9f35514bbe7c9a (diff) |
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 <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'v4l2.c')
-rw-r--r-- | v4l2.c | 92 |
1 files changed, 45 insertions, 47 deletions
@@ -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; |