/** * vb2_core_expbuf() - Export a buffer as a file descriptor * @q: videobuf2 queue * @fd: file descriptor associated with DMABUF (set by driver) * * @type: buffer type * @index: id number of the buffer * @plane: index of the plane to be exported, 0 for single plane queues * @flags: flags for newly created file, currently only O_CLOEXEC is * supported, refer to manual of open syscall for more details * * The return values from this function are intended to be directly returned * from vidioc_expbuf handler in driver. */ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type, unsigned int index, unsigned int plane, unsigned int flags) { struct vb2_buffer *vb = NULL; struct vb2_plane *vb_plane; int ret; struct dma_buf *dbuf;
if (q->memory != VB2_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 (flags & ~(O_CLOEXEC | O_ACCMODE)) { dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n"); return -EINVAL; } if (type != q->type) { dprintk(1, "invalid buffer type\n"); return -EINVAL; } if (index >= q->num_buffers) { dprintk(1, "buffer index out of range\n"); return -EINVAL; } vb = q->bufs[index];
if (plane >= vb->num_planes) { dprintk(1, "buffer plane out of range\n"); return -EINVAL; } if (vb2_fileio_is_active(q)) { dprintk(1, "expbuf: file io in progress\n"); return -EBUSY; }
vb_plane = &vb->planes[plane];
dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, flags & O_ACCMODE);
if (IS_ERR_OR_NULL(dbuf)) { dprintk(1, "failed to export buffer %d, plane %d\n", index, plane); return -EINVAL; }
ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); if (ret < 0) { dprintk(3, "buffer %d, plane %d failed to export (%d)\n", index, plane, ret); dma_buf_put(dbuf); return ret; }
dprintk(3, "buffer %d, plane %d exported as %d descriptor\n", index, plane, ret); *fd = ret;
return 0;
} EXPORT_SYMBOL_GPL(vb2_core_expbuf);