static int uvc_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream; unsigned int size; switch (vq->type) { case V4L2_BUF_TYPE_META_CAPTURE: size = UVC_METATADA_BUF_SIZE; break; default: stream = uvc_queue_to_stream(queue); size = stream->ctrl.dwMaxVideoFrameSize; break; } /* * When called with plane sizes, validate them. The driver supports * single planar formats only, and requires buffers to be large enough * to store a complete frame. */ if (*nplanes) return *nplanes != 1 || sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; return 0; }
static void uvc_buffer_finish(struct vb2_buffer *vb) { struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); struct uvc_streaming *stream = uvc_queue_to_stream(queue); struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); if (vb->state == VB2_BUF_STATE_DONE) uvc_video_clock_update(stream, &vb->v4l2_buf, buf); }
static void uvc_stop_streaming(struct vb2_queue *vq) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; uvc_video_enable(stream, 0); spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); spin_unlock_irqrestore(&queue->irqlock, flags); }
static void uvc_stop_streaming(struct vb2_queue *vq) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); /* Prevent new buffers coming in. */ spin_lock_irq(&queue->irqlock); queue->flags |= UVC_QUEUE_STOPPING; spin_unlock_irq(&queue->irqlock); /* * All pending work should be completed before disabling the stream, as * all URBs will be free'd during uvc_video_enable(s, 0). */ flush_workqueue(stream->async_wq); if (vq->type != V4L2_BUF_TYPE_META_CAPTURE) uvc_video_enable(uvc_queue_to_stream(queue), 0); spin_lock_irq(&queue->irqlock); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); queue->flags &= ~UVC_QUEUE_STOPPING; spin_unlock_irq(&queue->irqlock); }
static int uvc_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned size = stream->ctrl.dwMaxVideoFrameSize; /* Make sure the image size is large enough. */ if (*nplanes) return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; return 0; }
static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); /* Make sure the image size is large enough. */ if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize) return -EINVAL; *nplanes = 1; sizes[0] = fmt ? fmt->fmt.pix.sizeimage : stream->ctrl.dwMaxVideoFrameSize; return 0; }
static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; int ret; queue->buf_used = 0; ret = uvc_video_enable(stream, 1); if (ret == 0) return 0; spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_QUEUED); spin_unlock_irqrestore(&queue->irqlock, flags); return ret; }