|
@@ -1750,6 +1750,79 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * vb2_expbuf() - Export a buffer as a file descriptor
|
|
|
+ * @q: videobuf2 queue
|
|
|
+ * @eb: export buffer structure passed from userspace to vidioc_expbuf
|
|
|
+ * handler in driver
|
|
|
+ *
|
|
|
+ * The return values from this function are intended to be directly returned
|
|
|
+ * from vidioc_expbuf handler in driver.
|
|
|
+ */
|
|
|
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
|
|
|
+{
|
|
|
+ struct vb2_buffer *vb = NULL;
|
|
|
+ struct vb2_plane *vb_plane;
|
|
|
+ int ret;
|
|
|
+ struct dma_buf *dbuf;
|
|
|
+
|
|
|
+ if (q->memory != V4L2_MEMORY_MMAP) {
|
|
|
+ dprintk(1, "Queue is not currently set up for mmap\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!q->mem_ops->get_dmabuf) {
|
|
|
+ dprintk(1, "Queue does not support DMA buffer exporting\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eb->flags & ~O_CLOEXEC) {
|
|
|
+ dprintk(1, "Queue does support only O_CLOEXEC flag\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eb->type != q->type) {
|
|
|
+ dprintk(1, "qbuf: invalid buffer type\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (eb->index >= q->num_buffers) {
|
|
|
+ dprintk(1, "buffer index out of range\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ vb = q->bufs[eb->index];
|
|
|
+
|
|
|
+ if (eb->plane >= vb->num_planes) {
|
|
|
+ dprintk(1, "buffer plane out of range\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ vb_plane = &vb->planes[eb->plane];
|
|
|
+
|
|
|
+ dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
|
|
|
+ if (IS_ERR_OR_NULL(dbuf)) {
|
|
|
+ dprintk(1, "Failed to export buffer %d, plane %d\n",
|
|
|
+ eb->index, eb->plane);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = dma_buf_fd(dbuf, eb->flags);
|
|
|
+ if (ret < 0) {
|
|
|
+ dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
|
|
|
+ eb->index, eb->plane, ret);
|
|
|
+ dma_buf_put(dbuf);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
|
|
|
+ eb->index, eb->plane, ret);
|
|
|
+ eb->fd = ret;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(vb2_expbuf);
|
|
|
+
|
|
|
/**
|
|
|
* vb2_mmap() - map video buffers into application address space
|
|
|
* @q: videobuf2 queue
|
|
@@ -2456,6 +2529,16 @@ int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
|
|
|
|
|
|
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
|
|
|
+{
|
|
|
+ struct video_device *vdev = video_devdata(file);
|
|
|
+
|
|
|
+ if (vb2_queue_is_busy(vdev, file))
|
|
|
+ return -EBUSY;
|
|
|
+ return vb2_expbuf(vdev->queue, p);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
|
|
|
+
|
|
|
/* v4l2_file_operations helpers */
|
|
|
|
|
|
int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
|