On Tue, Aug 13, 2024 at 12:22:55PM +0300, Laurent Pinchart wrote: > On Tue, Aug 13, 2024 at 11:09:31AM +0200, Michael Grzeschik wrote: > > The uvc gadget driver is lacking the information which frame interval > > was set by the host. We add this information by implementing the g_parm > > and s_parm callbacks. > > As I've said countless times, this kind of hack is not the right way to > pass information that the kernel has no use for between two userspace > components. Please stop butchering this driver. Reading further patches in the series I see that you would like to get more precise bandwidth information from userspace. That is fine, but I don't think s_parm is the right option. This is not a regular V4L2 driver, pass it the exat information it needs instead, through a dedicated API that will provide all the needed data. > > Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> > > --- > > v3 -> v4: - > > v2 -> v3: - > > v1 -> v2: - > > --- > > drivers/usb/gadget/function/uvc.h | 1 + > > drivers/usb/gadget/function/uvc_v4l2.c | 52 ++++++++++++++++++++++++++++++++++ > > 2 files changed, 53 insertions(+) > > > > diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h > > index b3a5165ac70ec..f6bc58fb02b84 100644 > > --- a/drivers/usb/gadget/function/uvc.h > > +++ b/drivers/usb/gadget/function/uvc.h > > @@ -100,6 +100,7 @@ struct uvc_video { > > unsigned int width; > > unsigned int height; > > unsigned int imagesize; > > + unsigned int interval; > > struct mutex mutex; /* protects frame parameters */ > > > > unsigned int uvc_num_requests; > > diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c > > index de41519ce9aa0..392fb400aad14 100644 > > --- a/drivers/usb/gadget/function/uvc_v4l2.c > > +++ b/drivers/usb/gadget/function/uvc_v4l2.c > > @@ -307,6 +307,56 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt) > > return ret; > > } > > > > +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_fract timeperframe; > > + > > + if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; > > + > > + /* Return the actual frame period. */ > > + timeperframe.numerator = video->interval; > > + timeperframe.denominator = 10000000; > > + v4l2_simplify_fraction(&timeperframe.numerator, > > + &timeperframe.denominator, 8, 333); > > + > > + uvcg_dbg(&uvc->func, "Getting frame interval of %u/%u (%u)\n", > > + timeperframe.numerator, timeperframe.denominator, > > + video->interval); > > + > > + parm->parm.output.timeperframe = timeperframe; > > + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; > > + > > + 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_fract timeperframe; > > + > > + if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) > > + return -EINVAL; > > + > > + timeperframe = parm->parm.output.timeperframe; > > + > > + video->interval = v4l2_fraction_to_interval(timeperframe.numerator, > > + timeperframe.denominator); > > + > > + uvcg_dbg(&uvc->func, "Setting frame interval to %u/%u (%u)\n", > > + timeperframe.numerator, timeperframe.denominator, > > + video->interval); > > + > > + return 0; > > +} > > + > > static int > > uvc_v4l2_enum_frameintervals(struct file *file, void *fh, > > struct v4l2_frmivalenum *fival) > > @@ -577,6 +627,8 @@ const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = { > > .vidioc_dqbuf = uvc_v4l2_dqbuf, > > .vidioc_streamon = uvc_v4l2_streamon, > > .vidioc_streamoff = uvc_v4l2_streamoff, > > + .vidioc_s_parm = uvc_v4l2_s_parm, > > + .vidioc_g_parm = uvc_v4l2_g_parm, > > .vidioc_subscribe_event = uvc_v4l2_subscribe_event, > > .vidioc_unsubscribe_event = uvc_v4l2_unsubscribe_event, > > .vidioc_default = uvc_v4l2_ioctl_default, -- Regards, Laurent Pinchart