int fimc_is_video_dqbuf(struct file *file, struct fimc_is_video_ctx *vctx, struct v4l2_buffer *buf) { int ret = 0; bool blocking; struct fimc_is_video *video; struct fimc_is_queue *queue; BUG_ON(!file); BUG_ON(!vctx); BUG_ON(!GET_VIDEO(vctx)); BUG_ON(!buf); blocking = file->f_flags & O_NONBLOCK; video = GET_VIDEO(vctx); queue = GET_QUEUE(vctx); if (!queue->vbq) { mverr("vbq is NULL", vctx, video); ret = -EINVAL; goto p_err; } if (buf->type != queue->vbq->type) { mverr("buf type is invalid(%d != %d)", vctx, video, buf->type, queue->vbq->type); ret = -EINVAL; goto p_err; } if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) { mverr("queue is not streamon(%ld)", vctx, video, queue->state); ret = -EINVAL; goto p_err; } queue->buf_dqe++; ret = vb2_dqbuf(queue->vbq, buf, blocking); if (ret) { mverr("vb2_dqbuf is fail(%d)", vctx, video, ret); goto p_err; } #ifdef DBG_IMAGE_DUMP if ((vctx->video->id == DBG_IMAGE_DUMP_VIDEO) && (buf->index == DBG_IMAGE_DUMP_INDEX)) imgdump_request(queue->buf_box[buf->index][0], queue->buf_kva[buf->index][0], queue->framecfg.size[0]); #endif p_err: return ret; }
/* Dequeue a buffer */ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret; if (ctx->state == MFCINST_ERROR) { mfc_err("Call on DQBUF after unrecoverable error\n"); return -EIO; } if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); if (ret == 0 && ctx->state == MFCINST_FINISHED && list_empty(&ctx->vq_dst.done_list)) v4l2_event_queue_fh(&ctx->fh, &ev); } else { ret = -EINVAL; } return ret; }
static int camera_v4l2_dqbuf(struct file *filep, void *fh, struct v4l2_buffer *pb) { int ret; struct msm_session *session; struct camera_v4l2_private *sp = fh_to_private(fh); struct msm_video_device *pvdev = video_drvdata(filep); unsigned int session_id = pvdev->vdev->num; session = msm_session_find(session_id); if (WARN_ON(!session)) return -EIO; mutex_lock(&session->lock); ret = vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK); mutex_unlock(&session->lock); return ret; }
static int xvip_dma_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct v4l2_fh *vfh = file->private_data; struct xvip_dma *dma = to_xvip_dma(vfh->vdev); int ret; mutex_lock(&dma->lock); if (dma->queue.owner && dma->queue.owner != vfh) { ret = -EBUSY; goto done; } ret = vb2_dqbuf(&dma->queue, buf, file->f_flags & O_NONBLOCK); done: mutex_unlock(&dma->lock); return ret; }
/** * __vb2_perform_fileio() - perform a single file io (read or write) operation * @q: videobuf2 queue * @data: pointed to target userspace buffer * @count: number of bytes to read or write * @ppos: file handle position tracking pointer * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking) * @read: access mode selector (1 means read, 0 means write) */ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblock, int read) { struct vb2_fileio_data *fileio; struct vb2_fileio_buf *buf; int ret, index; dprintk(3, "file io: mode %s, offset %ld, count %zd, %sblocking\n", read ? "read" : "write", (long)*ppos, count, nonblock ? "non" : ""); if (!data) return -EINVAL; /* * Initialize emulator on first call. */ if (!q->fileio) { ret = __vb2_init_fileio(q, read); dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); if (ret) return ret; } fileio = q->fileio; /* * Hack fileio context to enable direct calls to vb2 ioctl interface. * The pointer will be restored before returning from this function. */ q->fileio = NULL; index = fileio->index; buf = &fileio->bufs[index]; /* * Check if we need to dequeue the buffer. */ if (buf->queued) { struct vb2_buffer *vb; /* * Call vb2_dqbuf to get buffer back. */ memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; ret = vb2_dqbuf(q, &fileio->b, nonblock); dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); if (ret) goto end; fileio->dq_count += 1; /* * Get number of bytes filled by the driver */ vb = q->bufs[index]; buf->size = vb2_get_plane_payload(vb, 0); buf->queued = 0; } /* * Limit count on last few bytes of the buffer. */ if (buf->pos + count > buf->size) { count = buf->size - buf->pos; dprintk(5, "reducing read count: %zd\n", count); } /* * Transfer data to userspace. */ dprintk(3, "file io: copying %zd bytes - buffer %d, offset %u\n", count, index, buf->pos); if (read) ret = copy_to_user(data, buf->vaddr + buf->pos, count); else ret = copy_from_user(buf->vaddr + buf->pos, data, count); if (ret) { dprintk(3, "file io: error copying data\n"); ret = -EFAULT; goto end; } /* * Update counters. */ buf->pos += count; *ppos += count; /* * Queue next buffer if required. */ if (buf->pos == buf->size || (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) { /* * Check if this is the last buffer to read. */ if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) && fileio->dq_count == 1) { dprintk(3, "file io: read limit reached\n"); /* * Restore fileio pointer and release the context. */ q->fileio = fileio; return __vb2_cleanup_fileio(q); } /* * Call vb2_qbuf and give buffer to the driver. */ memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; fileio->b.bytesused = buf->pos; ret = vb2_qbuf(q, &fileio->b); dprintk(5, "file io: vb2_dbuf result: %d\n", ret); if (ret) goto end; /* * Buffer has been queued, update the status */ buf->pos = 0; buf->queued = 1; buf->size = q->bufs[0]->v4l2_planes[0].length; fileio->q_count += 1; /* * Switch to the next buffer */ fileio->index = (index + 1) % q->num_buffers; /* * Start streaming if required. */ if (!read && !q->streaming) { ret = vb2_streamon(q, q->type); if (ret) goto end; } } /* * Return proper number of bytes processed. */ if (ret == 0) ret = count; end: /* * Restore the fileio context and block vb2 ioctl interface. */ q->fileio = fileio; return ret; }
/* * Dequeue a video buffer. If nonblocking is false, block until a buffer is * available. */ int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, int nonblocking) { return vb2_dqbuf(&queue->queue, buf, nonblocking); }
/* 将buffer从队列取出 */ static int myvivi_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { return vb2_dqbuf(&myvivi_vb_vidqueue, p, file->f_flags & O_NONBLOCK); }
static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblock, int read) { struct vb2_fileio_data *fileio; struct vb2_fileio_buf *buf; int ret, index; dprintk(3, "file io: mode %s, offset %ld, count %zd, %sblocking\n", read ? "read" : "write", (long)*ppos, count, nonblock ? "non" : ""); if (!data) return -EINVAL; if (!q->fileio) { ret = __vb2_init_fileio(q, read); dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); if (ret) return ret; } fileio = q->fileio; q->fileio = NULL; index = fileio->index; buf = &fileio->bufs[index]; if (buf->queued) { struct vb2_buffer *vb; memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; ret = vb2_dqbuf(q, &fileio->b, nonblock); dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); if (ret) goto end; fileio->dq_count += 1; vb = q->bufs[index]; buf->size = vb2_get_plane_payload(vb, 0); buf->queued = 0; } if (buf->pos + count > buf->size) { count = buf->size - buf->pos; dprintk(5, "reducing read count: %zd\n", count); } dprintk(3, "file io: copying %zd bytes - buffer %d, offset %u\n", count, index, buf->pos); if (read) ret = copy_to_user(data, buf->vaddr + buf->pos, count); else ret = copy_from_user(buf->vaddr + buf->pos, data, count); if (ret) { dprintk(3, "file io: error copying data\n"); ret = -EFAULT; goto end; } buf->pos += count; *ppos += count; if (buf->pos == buf->size || (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) { if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) && fileio->dq_count == 1) { dprintk(3, "file io: read limit reached\n"); q->fileio = fileio; return __vb2_cleanup_fileio(q); } memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; fileio->b.bytesused = buf->pos; ret = vb2_qbuf(q, &fileio->b); dprintk(5, "file io: vb2_dbuf result: %d\n", ret); if (ret) goto end; buf->pos = 0; buf->queued = 1; buf->size = q->bufs[0]->v4l2_planes[0].length; fileio->q_count += 1; fileio->index = (index + 1) % q->num_buffers; if (!read && !q->streaming) { ret = vb2_streamon(q, q->type); if (ret) goto end; } } if (ret == 0) ret = count; end: q->fileio = fileio; return ret; }
static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { struct mxr_layer *layer = video_drvdata(file); return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK); }