0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/list.h>
0011 #include <linux/module.h>
0012 #include <linux/usb.h>
0013 #include <linux/videodev2.h>
0014
0015 #include <media/v4l2-ioctl.h>
0016 #include <media/videobuf2-v4l2.h>
0017 #include <media/videobuf2-vmalloc.h>
0018
0019 #include "uvcvideo.h"
0020
0021
0022
0023
0024
0025 static int uvc_meta_v4l2_querycap(struct file *file, void *fh,
0026 struct v4l2_capability *cap)
0027 {
0028 struct v4l2_fh *vfh = file->private_data;
0029 struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
0030 struct uvc_video_chain *chain = stream->chain;
0031
0032 strscpy(cap->driver, "uvcvideo", sizeof(cap->driver));
0033 strscpy(cap->card, stream->dev->name, sizeof(cap->card));
0034 usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
0035 cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
0036 | chain->caps;
0037
0038 return 0;
0039 }
0040
0041 static int uvc_meta_v4l2_get_format(struct file *file, void *fh,
0042 struct v4l2_format *format)
0043 {
0044 struct v4l2_fh *vfh = file->private_data;
0045 struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
0046 struct v4l2_meta_format *fmt = &format->fmt.meta;
0047
0048 if (format->type != vfh->vdev->queue->type)
0049 return -EINVAL;
0050
0051 memset(fmt, 0, sizeof(*fmt));
0052
0053 fmt->dataformat = stream->meta.format;
0054 fmt->buffersize = UVC_METADATA_BUF_SIZE;
0055
0056 return 0;
0057 }
0058
0059 static int uvc_meta_v4l2_try_format(struct file *file, void *fh,
0060 struct v4l2_format *format)
0061 {
0062 struct v4l2_fh *vfh = file->private_data;
0063 struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
0064 struct uvc_device *dev = stream->dev;
0065 struct v4l2_meta_format *fmt = &format->fmt.meta;
0066 u32 fmeta = fmt->dataformat;
0067
0068 if (format->type != vfh->vdev->queue->type)
0069 return -EINVAL;
0070
0071 memset(fmt, 0, sizeof(*fmt));
0072
0073 fmt->dataformat = fmeta == dev->info->meta_format
0074 ? fmeta : V4L2_META_FMT_UVC;
0075 fmt->buffersize = UVC_METADATA_BUF_SIZE;
0076
0077 return 0;
0078 }
0079
0080 static int uvc_meta_v4l2_set_format(struct file *file, void *fh,
0081 struct v4l2_format *format)
0082 {
0083 struct v4l2_fh *vfh = file->private_data;
0084 struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
0085 struct v4l2_meta_format *fmt = &format->fmt.meta;
0086 int ret;
0087
0088 ret = uvc_meta_v4l2_try_format(file, fh, format);
0089 if (ret < 0)
0090 return ret;
0091
0092
0093
0094
0095
0096
0097 mutex_lock(&stream->mutex);
0098
0099 if (uvc_queue_allocated(&stream->queue))
0100 ret = -EBUSY;
0101 else
0102 stream->meta.format = fmt->dataformat;
0103
0104 mutex_unlock(&stream->mutex);
0105
0106 return ret;
0107 }
0108
0109 static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh,
0110 struct v4l2_fmtdesc *fdesc)
0111 {
0112 struct v4l2_fh *vfh = file->private_data;
0113 struct uvc_streaming *stream = video_get_drvdata(vfh->vdev);
0114 struct uvc_device *dev = stream->dev;
0115 u32 index = fdesc->index;
0116
0117 if (fdesc->type != vfh->vdev->queue->type ||
0118 index > 1U || (index && !dev->info->meta_format))
0119 return -EINVAL;
0120
0121 memset(fdesc, 0, sizeof(*fdesc));
0122
0123 fdesc->type = vfh->vdev->queue->type;
0124 fdesc->index = index;
0125 fdesc->pixelformat = index ? dev->info->meta_format : V4L2_META_FMT_UVC;
0126
0127 return 0;
0128 }
0129
0130 static const struct v4l2_ioctl_ops uvc_meta_ioctl_ops = {
0131 .vidioc_querycap = uvc_meta_v4l2_querycap,
0132 .vidioc_g_fmt_meta_cap = uvc_meta_v4l2_get_format,
0133 .vidioc_s_fmt_meta_cap = uvc_meta_v4l2_set_format,
0134 .vidioc_try_fmt_meta_cap = uvc_meta_v4l2_try_format,
0135 .vidioc_enum_fmt_meta_cap = uvc_meta_v4l2_enum_formats,
0136 .vidioc_reqbufs = vb2_ioctl_reqbufs,
0137 .vidioc_querybuf = vb2_ioctl_querybuf,
0138 .vidioc_qbuf = vb2_ioctl_qbuf,
0139 .vidioc_dqbuf = vb2_ioctl_dqbuf,
0140 .vidioc_create_bufs = vb2_ioctl_create_bufs,
0141 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
0142 .vidioc_streamon = vb2_ioctl_streamon,
0143 .vidioc_streamoff = vb2_ioctl_streamoff,
0144 };
0145
0146
0147
0148
0149
0150 static const struct v4l2_file_operations uvc_meta_fops = {
0151 .owner = THIS_MODULE,
0152 .unlocked_ioctl = video_ioctl2,
0153 .open = v4l2_fh_open,
0154 .release = vb2_fop_release,
0155 .poll = vb2_fop_poll,
0156 .mmap = vb2_fop_mmap,
0157 };
0158
0159 int uvc_meta_register(struct uvc_streaming *stream)
0160 {
0161 struct uvc_device *dev = stream->dev;
0162 struct video_device *vdev = &stream->meta.vdev;
0163 struct uvc_video_queue *queue = &stream->meta.queue;
0164
0165 stream->meta.format = V4L2_META_FMT_UVC;
0166
0167
0168
0169
0170
0171 vdev->queue = &queue->queue;
0172
0173 return uvc_register_video_device(dev, stream, vdev, queue,
0174 V4L2_BUF_TYPE_META_CAPTURE,
0175 &uvc_meta_fops, &uvc_meta_ioctl_ops);
0176 }