brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · 82de778 Raw
177 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *      uvc_metadata.c  --  USB Video Class driver - Metadata handling4 *5 *      Copyright (C) 20166 *          Guennadi Liakhovetski (guennadi.liakhovetski@intel.com)7 */8 9#include <linux/kernel.h>10#include <linux/list.h>11#include <linux/module.h>12#include <linux/usb.h>13#include <linux/videodev2.h>14 15#include <media/v4l2-ioctl.h>16#include <media/videobuf2-v4l2.h>17#include <media/videobuf2-vmalloc.h>18 19#include "uvcvideo.h"20 21/* -----------------------------------------------------------------------------22 * V4L2 ioctls23 */24 25static int uvc_meta_v4l2_querycap(struct file *file, void *fh,26				  struct v4l2_capability *cap)27{28	struct v4l2_fh *vfh = file->private_data;29	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);30	struct uvc_video_chain *chain = stream->chain;31 32	strscpy(cap->driver, "uvcvideo", sizeof(cap->driver));33	strscpy(cap->card, stream->dev->name, sizeof(cap->card));34	usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));35	cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING36			  | chain->caps;37 38	return 0;39}40 41static int uvc_meta_v4l2_get_format(struct file *file, void *fh,42				    struct v4l2_format *format)43{44	struct v4l2_fh *vfh = file->private_data;45	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);46	struct v4l2_meta_format *fmt = &format->fmt.meta;47 48	if (format->type != vfh->vdev->queue->type)49		return -EINVAL;50 51	memset(fmt, 0, sizeof(*fmt));52 53	fmt->dataformat = stream->meta.format;54	fmt->buffersize = UVC_METADATA_BUF_SIZE;55 56	return 0;57}58 59static int uvc_meta_v4l2_try_format(struct file *file, void *fh,60				    struct v4l2_format *format)61{62	struct v4l2_fh *vfh = file->private_data;63	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);64	struct uvc_device *dev = stream->dev;65	struct v4l2_meta_format *fmt = &format->fmt.meta;66	u32 fmeta = fmt->dataformat;67 68	if (format->type != vfh->vdev->queue->type)69		return -EINVAL;70 71	memset(fmt, 0, sizeof(*fmt));72 73	fmt->dataformat = fmeta == dev->info->meta_format74			? fmeta : V4L2_META_FMT_UVC;75	fmt->buffersize = UVC_METADATA_BUF_SIZE;76 77	return 0;78}79 80static int uvc_meta_v4l2_set_format(struct file *file, void *fh,81				    struct v4l2_format *format)82{83	struct v4l2_fh *vfh = file->private_data;84	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);85	struct v4l2_meta_format *fmt = &format->fmt.meta;86	int ret;87 88	ret = uvc_meta_v4l2_try_format(file, fh, format);89	if (ret < 0)90		return ret;91 92	/*93	 * We could in principle switch at any time, also during streaming.94	 * Metadata buffers would still be perfectly parseable, but it's more95	 * consistent and cleaner to disallow that.96	 */97	mutex_lock(&stream->mutex);98 99	if (uvc_queue_allocated(&stream->queue))100		ret = -EBUSY;101	else102		stream->meta.format = fmt->dataformat;103 104	mutex_unlock(&stream->mutex);105 106	return ret;107}108 109static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh,110				      struct v4l2_fmtdesc *fdesc)111{112	struct v4l2_fh *vfh = file->private_data;113	struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);114	struct uvc_device *dev = stream->dev;115	u32 index = fdesc->index;116 117	if (fdesc->type != vfh->vdev->queue->type ||118	    index > 1U || (index && !dev->info->meta_format))119		return -EINVAL;120 121	memset(fdesc, 0, sizeof(*fdesc));122 123	fdesc->type = vfh->vdev->queue->type;124	fdesc->index = index;125	fdesc->pixelformat = index ? dev->info->meta_format : V4L2_META_FMT_UVC;126 127	return 0;128}129 130static const struct v4l2_ioctl_ops uvc_meta_ioctl_ops = {131	.vidioc_querycap		= uvc_meta_v4l2_querycap,132	.vidioc_g_fmt_meta_cap		= uvc_meta_v4l2_get_format,133	.vidioc_s_fmt_meta_cap		= uvc_meta_v4l2_set_format,134	.vidioc_try_fmt_meta_cap	= uvc_meta_v4l2_try_format,135	.vidioc_enum_fmt_meta_cap	= uvc_meta_v4l2_enum_formats,136	.vidioc_reqbufs			= vb2_ioctl_reqbufs,137	.vidioc_querybuf		= vb2_ioctl_querybuf,138	.vidioc_qbuf			= vb2_ioctl_qbuf,139	.vidioc_dqbuf			= vb2_ioctl_dqbuf,140	.vidioc_create_bufs		= vb2_ioctl_create_bufs,141	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,142	.vidioc_streamon		= vb2_ioctl_streamon,143	.vidioc_streamoff		= vb2_ioctl_streamoff,144};145 146/* -----------------------------------------------------------------------------147 * V4L2 File Operations148 */149 150static const struct v4l2_file_operations uvc_meta_fops = {151	.owner = THIS_MODULE,152	.unlocked_ioctl = video_ioctl2,153	.open = v4l2_fh_open,154	.release = vb2_fop_release,155	.poll = vb2_fop_poll,156	.mmap = vb2_fop_mmap,157};158 159int uvc_meta_register(struct uvc_streaming *stream)160{161	struct uvc_device *dev = stream->dev;162	struct video_device *vdev = &stream->meta.vdev;163	struct uvc_video_queue *queue = &stream->meta.queue;164 165	stream->meta.format = V4L2_META_FMT_UVC;166 167	/*168	 * The video interface queue uses manual locking and thus does not set169	 * the queue pointer. Set it manually here.170	 */171	vdev->queue = &queue->queue;172 173	return uvc_register_video_device(dev, stream, vdev, queue,174					 V4L2_BUF_TYPE_META_CAPTURE,175					 &uvc_meta_fops, &uvc_meta_ioctl_ops);176}177