/**
* 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);