uvc_metadata.c 4.8 KB

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