drivers/media/usb/uvc/uvc_queue.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/uvc/uvc_queue.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/uvc/uvc_queue.c
Extension
.c
Size
10997 bytes
Lines
399
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
		uvc_dbg(queue->stream->dev, CAPTURE,
			"[E] Bytes used out of bounds\n");
		return -EINVAL;
	}

	if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
		return -ENODEV;

	buf->state = UVC_BUF_STATE_QUEUED;
	buf->error = 0;
	buf->mem = vb2_plane_vaddr(vb, 0);
	buf->length = vb2_plane_size(vb, 0);
	if (vb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
		buf->bytesused = 0;
	else
		buf->bytesused = vb2_get_plane_payload(vb, 0);

	return 0;
}

static void uvc_buffer_queue(struct vb2_buffer *vb)
{
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
	struct uvc_buffer *buf = uvc_vbuf_to_buffer(vbuf);
	unsigned long flags;

	spin_lock_irqsave(&queue->irqlock, flags);
	if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
		kref_init(&buf->ref);
		list_add_tail(&buf->queue, &queue->irqqueue);
	} else {
		/*
		 * If the device is disconnected return the buffer to userspace
		 * directly. The next QBUF call will fail with -ENODEV.
		 */
		buf->state = UVC_BUF_STATE_ERROR;
		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
	}

	spin_unlock_irqrestore(&queue->irqlock, flags);
}

static void uvc_buffer_finish(struct vb2_buffer *vb)
{
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
	struct uvc_buffer *buf = uvc_vbuf_to_buffer(vbuf);

	if (vb->state == VB2_BUF_STATE_DONE)
		uvc_video_clock_update(queue->stream, vbuf, buf);
}

static int uvc_start_streaming_video(struct vb2_queue *vq, unsigned int count)
{
	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
	struct uvc_streaming *stream = queue->stream;
	int ret;

	lockdep_assert_irqs_enabled();

	ret = uvc_pm_get(stream->dev);
	if (ret)
		goto err_buffers;

	queue->buf_used = 0;

	ret = uvc_video_start_streaming(stream);
	if (ret)
		goto err_pm;

	return 0;

err_pm:
	uvc_pm_put(stream->dev);
err_buffers:
	uvc_queue_return_buffers(queue, UVC_BUF_STATE_QUEUED);
	return ret;
}

static void uvc_stop_streaming_video(struct vb2_queue *vq)
{
	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
	struct uvc_streaming *stream = queue->stream;

	lockdep_assert_irqs_enabled();

	uvc_video_stop_streaming(stream);

Annotation

Implementation Notes