All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Tretter <m.tretter@pengutronix.de>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Daniel Scally <dan.scally@ideasonboard.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Michael Grzeschik <m.grzeschik@pengutronix.de>,
	linux-usb@vger.kernel.org, linux-media@vger.kernel.org,
	kernel@pengutronix.de, Michael Tretter <m.tretter@pengutronix.de>
Subject: [PATCH 8/8] usb: gadget: uvc: implement s/g_parm
Date: Thu, 23 Mar 2023 12:41:16 +0100	[thread overview]
Message-ID: <20230323-uvc-gadget-cleanup-v1-8-e41f0c5d9d8e@pengutronix.de> (raw)
In-Reply-To: <20230323-uvc-gadget-cleanup-v1-0-e41f0c5d9d8e@pengutronix.de>

As the UVC gadget implements ENUM_FRAMEINTERVALS it should also
implement S_PARM and G_PARM to allow to get and set the frame interval.
While the driver doesn't actually do something with the frame interval,
it should still handle and store the interval correctly, if the user
space request it.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/usb/gadget/function/uvc.h      |  1 +
 drivers/usb/gadget/function/uvc_v4l2.c | 94 ++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 6b4ab3e07173..a9a5a9d2f554 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -96,6 +96,7 @@ struct uvc_video {
 	unsigned int width;
 	unsigned int height;
 	unsigned int imagesize;
+	struct v4l2_fract timeperframe;
 	enum v4l2_colorspace colorspace;
 	enum v4l2_ycbcr_encoding ycbcr_enc;
 	enum v4l2_quantization quantization;
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index 673532ff0faa..a9564dc2445d 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -185,6 +185,9 @@ void uvc_init_default_format(struct uvc_device *uvc)
 		video->xfer_func = V4L2_XFER_FUNC_SRGB;
 		video->ycbcr_enc = V4L2_YCBCR_ENC_601;
 
+		video->timeperframe.numerator = 1;
+		video->timeperframe.denominator = 30;
+
 		return;
 	}
 
@@ -209,6 +212,11 @@ void uvc_init_default_format(struct uvc_device *uvc)
 	video->quantization = V4L2_QUANTIZATION_FULL_RANGE;
 	video->xfer_func = V4L2_XFER_FUNC_SRGB;
 	video->ycbcr_enc = V4L2_YCBCR_ENC_601;
+
+	video->timeperframe.numerator = uframe->frame.dw_default_frame_interval;
+	video->timeperframe.denominator = 10000000;
+	v4l2_simplify_fraction(&video->timeperframe.numerator,
+			       &video->timeperframe.denominator, 8, 333);
 }
 
 static struct uvcg_frame *find_closest_frame_by_size(struct uvc_device *uvc,
@@ -255,6 +263,46 @@ static struct uvcg_frame *find_closest_frame_by_size(struct uvc_device *uvc,
 	return uframe;
 }
 
+static void find_closest_timeperframe(struct uvc_device *uvc,
+				      struct v4l2_fract *timeperframe)
+{
+	struct uvc_video *video = &uvc->video;
+	struct uvcg_format *uformat;
+	struct uvcg_frame *uframe;
+	unsigned long interval;
+	unsigned int best_interval;
+	unsigned int curr;
+	unsigned int dist;
+	unsigned int best_dist = UINT_MAX;
+	int i;
+
+	if (timeperframe->denominator == 0)
+		timeperframe->denominator = video->timeperframe.denominator;
+	if (timeperframe->numerator == 0)
+		timeperframe->numerator = video->timeperframe.numerator;
+
+	uformat = find_format_by_pix(uvc, video->fcc);
+	uframe = find_closest_frame_by_size(uvc, uformat,
+					    video->width, video->height);
+
+	interval = timeperframe->numerator * 10000000;
+	do_div(interval, timeperframe->denominator);
+
+	for (i = 0; i < uframe->frame.b_frame_interval_type; i++) {
+		curr = uframe->dw_frame_interval[i];
+		dist = interval > curr ? interval - curr : curr - interval;
+		if (dist < best_dist) {
+			best_dist = dist;
+			best_interval = curr;
+		}
+	}
+
+	timeperframe->numerator = best_interval;
+	timeperframe->denominator = 10000000;
+	v4l2_simplify_fraction(&timeperframe->numerator,
+			       &timeperframe->denominator, 8, 333);
+}
+
 /* --------------------------------------------------------------------------
  * Requests handling
  */
@@ -456,6 +504,50 @@ uvc_v4l2_enum_framesizes(struct file *file, void *fh,
 	return 0;
 }
 
+static int
+uvc_v4l2_s_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct uvc_device *uvc = video_get_drvdata(vdev);
+	struct uvc_video *video = &uvc->video;
+	struct v4l2_outputparm *out;
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	out = &parm->parm.output;
+
+	memset(out->reserved, 0, sizeof(out->reserved));
+
+	out->capability = V4L2_CAP_TIMEPERFRAME;
+	find_closest_timeperframe(uvc, &out->timeperframe);
+
+	video->timeperframe = out->timeperframe;
+
+	return 0;
+}
+
+static int
+uvc_v4l2_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct uvc_device *uvc = video_get_drvdata(vdev);
+	struct uvc_video *video = &uvc->video;
+	struct v4l2_outputparm *out;
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	out = &parm->parm.output;
+
+	out->capability |= V4L2_CAP_TIMEPERFRAME;
+	out->timeperframe = video->timeperframe;
+
+	return 0;
+}
+
 static int
 uvc_v4l2_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
 {
@@ -671,6 +763,8 @@ const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
 	.vidioc_s_fmt_vid_out = uvc_v4l2_set_format,
 	.vidioc_enum_frameintervals = uvc_v4l2_enum_frameintervals,
 	.vidioc_enum_framesizes = uvc_v4l2_enum_framesizes,
+	.vidioc_g_parm = uvc_v4l2_g_parm,
+	.vidioc_s_parm = uvc_v4l2_s_parm,
 	.vidioc_enum_fmt_vid_out = uvc_v4l2_enum_format,
 	.vidioc_enum_output = uvc_v4l2_enum_output,
 	.vidioc_g_output = uvc_v4l2_g_output,

-- 
2.30.2

  parent reply	other threads:[~2023-03-23 11:41 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-23 11:41 [PATCH 0/8] usb: gadget: uvc: fix errors reported by v4l2-compliance Michael Tretter
2023-03-23 11:41 ` [PATCH 1/8] usb: gadget: uvc: use fourcc printk helper Michael Tretter
2023-03-24  7:44   ` Dan Scally
2023-03-24  9:21   ` Laurent Pinchart
2023-03-23 11:41 ` [PATCH 2/8] usb: gadget: uvc: fix return code of REQBUFS Michael Tretter
2023-03-24  7:50   ` Dan Scally
2023-03-24  9:25     ` Laurent Pinchart
2023-03-23 11:41 ` [PATCH 3/8] usb: gadget: uvc: implement s/g_output ioctl Michael Tretter
2023-03-24  9:20   ` Laurent Pinchart
2023-03-24  9:21     ` Dan Scally
2023-03-24  9:39       ` Hans Verkuil
2023-03-24  9:49         ` Laurent Pinchart
2023-03-23 11:41 ` [PATCH 4/8] usb: gadget: uvc: move video format initialization to uvc_v4l2 Michael Tretter
2023-03-24  9:31   ` Laurent Pinchart
2023-03-23 11:41 ` [PATCH 5/8] usb: gadget: uvc: initialize video format using configfs Michael Tretter
2023-03-23 11:41 ` [PATCH 6/8] usb: gadget: uvc: try harder to find a valid format Michael Tretter
2023-03-24  9:35   ` Laurent Pinchart
2023-03-23 11:41 ` [PATCH 7/8] usb: gadget: uvc: add colorspace handling Michael Tretter
2023-03-24  9:33   ` Laurent Pinchart
2023-03-23 11:41 ` Michael Tretter [this message]
2023-03-23 18:02   ` [PATCH 8/8] usb: gadget: uvc: implement s/g_parm kernel test robot
2023-03-24  9:32   ` Laurent Pinchart
2023-03-24  9:38 ` [PATCH 0/8] usb: gadget: uvc: fix errors reported by v4l2-compliance Laurent Pinchart
2023-03-27 12:26   ` Michael Tretter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230323-uvc-gadget-cleanup-v1-8-e41f0c5d9d8e@pengutronix.de \
    --to=m.tretter@pengutronix.de \
    --cc=dan.scally@ideasonboard.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kernel@pengutronix.de \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=m.grzeschik@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.