diff mbox series

[v15,18/19] media: uvcvideo: implement UVC v1.5 ROI

Message ID 20241114-uvc-roi-v15-18-64cfeb56b6f8@chromium.org
State New
Headers show
Series media: uvcvideo: Implement UVC v1.5 ROI | expand

Commit Message

Ricardo Ribalda Nov. 14, 2024, 7:10 p.m. UTC
From: Yunke Cao <yunkec@google.com>

Implement support for ROI as described in UVC 1.5:
4.2.2.1.20 Digital Region of Interest (ROI) Control

ROI control is implemented using V4L2 control API as
two UVC-specific controls:
V4L2_CID_UVC_REGION_OF_INTEREST_RECT and
V4L2_CID_UVC_REGION_OF_INTEREST_AUTO.

Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Yunke Cao <yunkec@google.com>
---
 drivers/media/usb/uvc/uvc_ctrl.c   | 81 ++++++++++++++++++++++++++++++++++++++
 drivers/media/usb/uvc/uvcvideo.h   |  7 ++++
 include/uapi/linux/usb/video.h     |  1 +
 include/uapi/linux/uvcvideo.h      | 13 ++++++
 include/uapi/linux/v4l2-controls.h |  9 +++++
 5 files changed, 111 insertions(+)

Comments

Ricardo Ribalda Nov. 14, 2024, 8:03 p.m. UTC | #1
Hi Gergo

Sorry, I forgot to reply to your comment in v14.

On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
>
> Hi Ricardo,
>
> On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
> >
> > +     },
> > +     {
> > +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> > +             .entity         = UVC_GUID_UVC_CAMERA,
> > +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > +             .size           = 16,
> > +             .offset         = 64,
> > +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> > +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> > +             .name           = "Region Of Interest Auto Controls",
> > +     },
> >  };
> >
>
> Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?

If I create 8 Booleans, they will always be shown in the device. And
the user will not have a way to know which values are available and
which are not.

We will also fail the v4l2-compliance test, because there will be up
to 7 boolean controls that will not be able to be set to 1, eventhough
they are writable.

Thanks for the prompt review.
>
> Thanks,
> Gergo
>



--
Ricardo Ribalda
Ricardo Ribalda Nov. 14, 2024, 8:28 p.m. UTC | #2
Hi

On Thu, 14 Nov 2024 at 21:16, Gergo Koteles <soyer@irl.hu> wrote:
>
> Hi Ricardo,
>
> On Thu, 2024-11-14 at 21:03 +0100, Ricardo Ribalda wrote:
> > Hi Gergo
> >
> > Sorry, I forgot to reply to your comment in v14.
> >
> > On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
> > >
> > > Hi Ricardo,
> > >
> > > On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
> > > >
> > > > +     },
> > > > +     {
> > > > +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> > > > +             .entity         = UVC_GUID_UVC_CAMERA,
> > > > +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > > +             .size           = 16,
> > > > +             .offset         = 64,
> > > > +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> > > > +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> > > > +             .name           = "Region Of Interest Auto Controls",
> > > > +     },
> > > >  };
> > > >
> > >
> > > Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
> >
> > If I create 8 Booleans, they will always be shown in the device. And
> > the user will not have a way to know which values are available and
> > which are not.
> >
> > We will also fail the v4l2-compliance test, because there will be up
> > to 7 boolean controls that will not be able to be set to 1, eventhough
> > they are writable.
> >
>
> And can't it be that only those returned by GET_MAX be added?
>
> ```
> The bmAutoControls bitmask determines which, if any, on board features
> should track to the region of interest. To detect if a device supports
> a particular Auto Control, use GET_MAX which returns a mask indicating
> all supported Auto Controls.
> ```
>
> Sorry for the misunderstanding, I just don't quite understand.

I guess we could, but we would have to make a big change in the way
the controls are probed today. uvc does not use the control framework.

What will be the benefit of using 8 controls?
- Applications still have to know what those controls do, they should
not rely on the control name.
- Changing from lets say AUTO_EXPOSURE to AUTO_FOCUS, will require to
send at least 2 controls via v4l2_s_ext_control... I think it is more
practical and less prone to errrors to send just one control

If the number of autos were unknown, then having multiple controls
could be a good idea, but they are part of the uvc standard and
unlikely to be changed.


Thanks!
>
> Thanks,
>
> Gergo
Gergo Koteles Nov. 15, 2024, 12:04 a.m. UTC | #3
Hi Ricardo,

On Thu, 2024-11-14 at 21:28 +0100, Ricardo Ribalda wrote:
> Hi
> 
> On Thu, 14 Nov 2024 at 21:16, Gergo Koteles <soyer@irl.hu> wrote:
> > 
> > Hi Ricardo,
> > 
> > On Thu, 2024-11-14 at 21:03 +0100, Ricardo Ribalda wrote:
> > > Hi Gergo
> > > 
> > > Sorry, I forgot to reply to your comment in v14.
> > > 
> > > On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
> > > > 
> > > > Hi Ricardo,
> > > > 
> > > > On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
> > > > > 
> > > > > +     },
> > > > > +     {
> > > > > +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> > > > > +             .entity         = UVC_GUID_UVC_CAMERA,
> > > > > +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > > > +             .size           = 16,
> > > > > +             .offset         = 64,
> > > > > +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> > > > > +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> > > > > +             .name           = "Region Of Interest Auto Controls",
> > > > > +     },
> > > > >  };
> > > > > 
> > > > 
> > > > Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
> > > 
> > > If I create 8 Booleans, they will always be shown in the device. And
> > > the user will not have a way to know which values are available and
> > > which are not.
> > > 
> > > We will also fail the v4l2-compliance test, because there will be up
> > > to 7 boolean controls that will not be able to be set to 1, eventhough
> > > they are writable.
> > > 
> > 
> > And can't it be that only those returned by GET_MAX be added?
> > 
> > ```
> > The bmAutoControls bitmask determines which, if any, on board features
> > should track to the region of interest. To detect if a device supports
> > a particular Auto Control, use GET_MAX which returns a mask indicating
> > all supported Auto Controls.
> > ```
> > 
> > Sorry for the misunderstanding, I just don't quite understand.
> 
> I guess we could, but we would have to make a big change in the way
> the controls are probed today. uvc does not use the control framework.
> 
> What will be the benefit of using 8 controls?
> - Applications still have to know what those controls do, they should
> not rely on the control name.

Applications like v4l2-ctl are not aware of every controls, work by
control type, and let the user decide what to do, based on the name.

To avoid having to know each bitmask type control, they need to be able
to query which bit means what and what to display to the user.

Could VIDIOC_QUERYMENU be supplemented with this?


> - Changing from lets say AUTO_EXPOSURE to AUTO_FOCUS, will require to
> send at least 2 controls via v4l2_s_ext_control... I think it is more
> practical and less prone to errrors to send just one control
> 

Yes, that could be a good reason.

Thanks,
Gergo
Ricardo Ribalda Nov. 15, 2024, 8:22 a.m. UTC | #4
On Fri, 15 Nov 2024 at 01:04, Gergo Koteles <soyer@irl.hu> wrote:
>
> Hi Ricardo,
>
> On Thu, 2024-11-14 at 21:28 +0100, Ricardo Ribalda wrote:
> > Hi
> >
> > On Thu, 14 Nov 2024 at 21:16, Gergo Koteles <soyer@irl.hu> wrote:
> > >
> > > Hi Ricardo,
> > >
> > > On Thu, 2024-11-14 at 21:03 +0100, Ricardo Ribalda wrote:
> > > > Hi Gergo
> > > >
> > > > Sorry, I forgot to reply to your comment in v14.
> > > >
> > > > On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
> > > > >
> > > > > Hi Ricardo,
> > > > >
> > > > > On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
> > > > > >
> > > > > > +     },
> > > > > > +     {
> > > > > > +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> > > > > > +             .entity         = UVC_GUID_UVC_CAMERA,
> > > > > > +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > > > > +             .size           = 16,
> > > > > > +             .offset         = 64,
> > > > > > +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> > > > > > +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> > > > > > +             .name           = "Region Of Interest Auto Controls",
> > > > > > +     },
> > > > > >  };
> > > > > >
> > > > >
> > > > > Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
> > > >
> > > > If I create 8 Booleans, they will always be shown in the device. And
> > > > the user will not have a way to know which values are available and
> > > > which are not.
> > > >
> > > > We will also fail the v4l2-compliance test, because there will be up
> > > > to 7 boolean controls that will not be able to be set to 1, eventhough
> > > > they are writable.
> > > >
> > >
> > > And can't it be that only those returned by GET_MAX be added?
> > >
> > > ```
> > > The bmAutoControls bitmask determines which, if any, on board features
> > > should track to the region of interest. To detect if a device supports
> > > a particular Auto Control, use GET_MAX which returns a mask indicating
> > > all supported Auto Controls.
> > > ```
> > >
> > > Sorry for the misunderstanding, I just don't quite understand.
> >
> > I guess we could, but we would have to make a big change in the way
> > the controls are probed today. uvc does not use the control framework.
> >
> > What will be the benefit of using 8 controls?
> > - Applications still have to know what those controls do, they should
> > not rely on the control name.
>
> Applications like v4l2-ctl are not aware of every controls, work by
> control type, and let the user decide what to do, based on the name.
>
> To avoid having to know each bitmask type control, they need to be able
> to query which bit means what and what to display to the user.
>
> Could VIDIOC_QUERYMENU be supplemented with this?

I believe that violates compliance. VIDIOC_QUERYMENU should only be
used on menus.
https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-compliance/v4l2-test-controls.cpp?h=v4l-utils-1.28.1#n143

>
>
> > - Changing from lets say AUTO_EXPOSURE to AUTO_FOCUS, will require to
> > send at least 2 controls via v4l2_s_ext_control... I think it is more
> > practical and less prone to errrors to send just one control
> >
>
> Yes, that could be a good reason.
>
> Thanks,
> Gergo
>
>
Hans de Goede Nov. 18, 2024, 3:59 p.m. UTC | #5
Hi Ricardo,

On 14-Nov-24 9:03 PM, Ricardo Ribalda wrote:
> Hi Gergo
> 
> Sorry, I forgot to reply to your comment in v14.
> 
> On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
>>
>> Hi Ricardo,
>>
>> On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
>>>
>>> +     },
>>> +     {
>>> +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
>>> +             .entity         = UVC_GUID_UVC_CAMERA,
>>> +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
>>> +             .size           = 16,
>>> +             .offset         = 64,
>>> +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
>>> +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
>>> +             .name           = "Region Of Interest Auto Controls",
>>> +     },
>>>  };
>>>
>>
>> Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
> 
> If I create 8 Booleans, they will always be shown in the device. And
> the user will not have a way to know which values are available and
> which are not.
> 
> We will also fail the v4l2-compliance test, because there will be up
> to 7 boolean controls that will not be able to be set to 1, eventhough
> they are writable.

So why can't these other controls be set to 1? Because only one
of the options in the bitmask can be selected at a time ?

If only 1 bit in the UVC_CTRL_DATA_TYPE_BITMASK for this can be one
at the time, then this should be mapped to a V4L2_CTRL_TYPE_MENU
just like how that is done for V4L2_CID_EXPOSURE_AUTO already.

Actually looking at existing comments about UVC_CTRL_DATA_TYPE_BITMASK
in the driver there is this comment on top of uvc_mapping_get_menu_value()

 * For controls of type UVC_CTRL_DATA_TYPE_BITMASK, the UVC control value is
 * expressed as a bitmask and is thus guaranteed to have a single bit set.

Assuming this "guaranteed to have a single bit set" comment is valid for
the V4L2_CID_UVC_REGION_OF_INTEREST_AUTO part of UVC_CT_REGION_OF_INTEREST_CONTROL
too then I think we should simply map this to a menu similar to how
this is done for V4L2_CID_EXPOSURE_AUTO.

Note V4L2_CID_EXPOSURE_AUTO is the only existing user of UVC_CTRL_DATA_TYPE_BITMASK
at the moment.

Mapping this to a menu should nicely address Gergo's concerns here.

Regards,

Hans
Ricardo Ribalda Delgado Nov. 18, 2024, 4:16 p.m. UTC | #6
Hi

On Mon, Nov 18, 2024 at 4:59 PM Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi Ricardo,
>
> On 14-Nov-24 9:03 PM, Ricardo Ribalda wrote:
> > Hi Gergo
> >
> > Sorry, I forgot to reply to your comment in v14.
> >
> > On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
> >>
> >> Hi Ricardo,
> >>
> >> On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
> >>>
> >>> +     },
> >>> +     {
> >>> +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> >>> +             .entity         = UVC_GUID_UVC_CAMERA,
> >>> +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> >>> +             .size           = 16,
> >>> +             .offset         = 64,
> >>> +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> >>> +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> >>> +             .name           = "Region Of Interest Auto Controls",
> >>> +     },
> >>>  };
> >>>
> >>
> >> Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
> >
> > If I create 8 Booleans, they will always be shown in the device. And
> > the user will not have a way to know which values are available and
> > which are not.
> >
> > We will also fail the v4l2-compliance test, because there will be up
> > to 7 boolean controls that will not be able to be set to 1, eventhough
> > they are writable.
>
> So why can't these other controls be set to 1? Because only one
> of the options in the bitmask can be selected at a time ?
>
> If only 1 bit in the UVC_CTRL_DATA_TYPE_BITMASK for this can be one
> at the time, then this should be mapped to a V4L2_CTRL_TYPE_MENU
> just like how that is done for V4L2_CID_EXPOSURE_AUTO already.
>
> Actually looking at existing comments about UVC_CTRL_DATA_TYPE_BITMASK
> in the driver there is this comment on top of uvc_mapping_get_menu_value()
>
>  * For controls of type UVC_CTRL_DATA_TYPE_BITMASK, the UVC control value is
>  * expressed as a bitmask and is thus guaranteed to have a single bit set.
>
> Assuming this "guaranteed to have a single bit set" comment is valid for
> the V4L2_CID_UVC_REGION_OF_INTEREST_AUTO part of UVC_CT_REGION_OF_INTEREST_CONTROL
> too then I think we should simply map this to a menu similar to how
> this is done for V4L2_CID_EXPOSURE_AUTO.
>
> Note V4L2_CID_EXPOSURE_AUTO is the only existing user of UVC_CTRL_DATA_TYPE_BITMASK
> at the moment.
>
> Mapping this to a menu should nicely address Gergo's concerns here.

The UVC standard is not very clear re bmAutoControls. It says:
"""
The bmAutoControls bitmask determines which, if any, on board features
should track to the region of interest. To detect if a device supports
a particular Auto Control, use GET_MAX which returns a mask indicating
all supported Auto Controls.
GET_CUR returns the current Region of Interest (RoI) being employed by
the device. This RoI should be the same as specified in most recent
SET_CUR except in the case where the ‘Auto Detect and Track’ and/or
‘Image Stabilization’ bit have been set.
"""

Which makes me believe that you can set another Auto value + one of
these ones. So I do not think that we can assume "guaranteed to have a
single bit set".

The behaviour will vary module to module. So I'd rather take a
conservative approach here and let the hardware clamp the value and
not us.

>
> Regards,
>
> Hans
>
Hans de Goede Nov. 25, 2024, 2:27 p.m. UTC | #7
Hi Ricardo,

On 18-Nov-24 5:16 PM, Ricardo Ribalda Delgado wrote:
> Hi
> 
> On Mon, Nov 18, 2024 at 4:59 PM Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi Ricardo,
>>
>> On 14-Nov-24 9:03 PM, Ricardo Ribalda wrote:
>>> Hi Gergo
>>>
>>> Sorry, I forgot to reply to your comment in v14.
>>>
>>> On Thu, 14 Nov 2024 at 20:53, Gergo Koteles <soyer@irl.hu> wrote:
>>>>
>>>> Hi Ricardo,
>>>>
>>>> On Thu, 2024-11-14 at 19:10 +0000, Ricardo Ribalda wrote:
>>>>>
>>>>> +     },
>>>>> +     {
>>>>> +             .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
>>>>> +             .entity         = UVC_GUID_UVC_CAMERA,
>>>>> +             .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
>>>>> +             .size           = 16,
>>>>> +             .offset         = 64,
>>>>> +             .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
>>>>> +             .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
>>>>> +             .name           = "Region Of Interest Auto Controls",
>>>>> +     },
>>>>>  };
>>>>>
>>>>
>>>> Wouldn't be better to use 8 V4L2_CTRL_TYPE_BOOLEAN controls for this?
>>>
>>> If I create 8 Booleans, they will always be shown in the device. And
>>> the user will not have a way to know which values are available and
>>> which are not.
>>>
>>> We will also fail the v4l2-compliance test, because there will be up
>>> to 7 boolean controls that will not be able to be set to 1, eventhough
>>> they are writable.
>>
>> So why can't these other controls be set to 1? Because only one
>> of the options in the bitmask can be selected at a time ?
>>
>> If only 1 bit in the UVC_CTRL_DATA_TYPE_BITMASK for this can be one
>> at the time, then this should be mapped to a V4L2_CTRL_TYPE_MENU
>> just like how that is done for V4L2_CID_EXPOSURE_AUTO already.
>>
>> Actually looking at existing comments about UVC_CTRL_DATA_TYPE_BITMASK
>> in the driver there is this comment on top of uvc_mapping_get_menu_value()
>>
>>  * For controls of type UVC_CTRL_DATA_TYPE_BITMASK, the UVC control value is
>>  * expressed as a bitmask and is thus guaranteed to have a single bit set.
>>
>> Assuming this "guaranteed to have a single bit set" comment is valid for
>> the V4L2_CID_UVC_REGION_OF_INTEREST_AUTO part of UVC_CT_REGION_OF_INTEREST_CONTROL
>> too then I think we should simply map this to a menu similar to how
>> this is done for V4L2_CID_EXPOSURE_AUTO.
>>
>> Note V4L2_CID_EXPOSURE_AUTO is the only existing user of UVC_CTRL_DATA_TYPE_BITMASK
>> at the moment.
>>
>> Mapping this to a menu should nicely address Gergo's concerns here.
> 
> The UVC standard is not very clear re bmAutoControls. It says:
> """
> The bmAutoControls bitmask determines which, if any, on board features
> should track to the region of interest. To detect if a device supports
> a particular Auto Control, use GET_MAX which returns a mask indicating
> all supported Auto Controls.
> GET_CUR returns the current Region of Interest (RoI) being employed by
> the device. This RoI should be the same as specified in most recent
> SET_CUR except in the case where the ‘Auto Detect and Track’ and/or
> ‘Image Stabilization’ bit have been set.
> """
> 
> Which makes me believe that you can set another Auto value + one of
> these ones. So I do not think that we can assume "guaranteed to have a
> single bit set".

I see I already was afraid it would be something like this but
it would have been nice if we could have turned this into a menu control.

> The behaviour will vary module to module. So I'd rather take a
> conservative approach here and let the hardware clamp the value and
> not us.

Agreed.

Regards,

Hans
Yunke Cao Dec. 6, 2024, 7:50 a.m. UTC | #8
On Mon, Dec 2, 2024 at 6:26 PM Ricardo Ribalda <ribalda@chromium.org> wrote:
>
> On Mon, 2 Dec 2024 at 09:02, Yunke Cao <yunkec@google.com> wrote:
> >
> > Hi Ricardo,
> >
> > Thanks for the new version!!
> >
> > On Fri, Nov 15, 2024 at 4:11 AM Ricardo Ribalda <ribalda@chromium.org> wrote:
> > >
> > > From: Yunke Cao <yunkec@google.com>
> > >
> > > Implement support for ROI as described in UVC 1.5:
> > > 4.2.2.1.20 Digital Region of Interest (ROI) Control
> > >
> > > ROI control is implemented using V4L2 control API as
> > > two UVC-specific controls:
> > > V4L2_CID_UVC_REGION_OF_INTEREST_RECT and
> > > V4L2_CID_UVC_REGION_OF_INTEREST_AUTO.
> > >
> > > Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
> > > Signed-off-by: Yunke Cao <yunkec@google.com>
> > > ---
> > >  drivers/media/usb/uvc/uvc_ctrl.c   | 81 ++++++++++++++++++++++++++++++++++++++
> > >  drivers/media/usb/uvc/uvcvideo.h   |  7 ++++
> > >  include/uapi/linux/usb/video.h     |  1 +
> > >  include/uapi/linux/uvcvideo.h      | 13 ++++++
> > >  include/uapi/linux/v4l2-controls.h |  9 +++++
> > >  5 files changed, 111 insertions(+)
> > >
> > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
> > > index f262e05ad3a8..5b619ef40dd3 100644
> > > --- a/drivers/media/usb/uvc/uvc_ctrl.c
> > > +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> > > @@ -358,6 +358,24 @@ static const struct uvc_control_info uvc_ctrls[] = {
> > >                 .flags          = UVC_CTRL_FLAG_GET_CUR
> > >                                 | UVC_CTRL_FLAG_AUTO_UPDATE,
> > >         },
> > > +       /*
> > > +        * UVC_CTRL_FLAG_AUTO_UPDATE is needed because the RoI may get updated
> > > +        * by sensors.
> > > +        * "This RoI should be the same as specified in most recent SET_CUR
> > > +        * except in the case where the ‘Auto Detect and Track’ and/or
> > > +        * ‘Image Stabilization’ bit have been set."
> > > +        * 4.2.2.1.20 Digital Region of Interest (ROI) Control
> > > +        */
> > > +       {
> > > +               .entity         = UVC_GUID_UVC_CAMERA,
> > > +               .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > +               .index          = 21,
> > > +               .size           = 10,
> > > +               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
> > > +                               | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
> > > +                               | UVC_CTRL_FLAG_GET_DEF
> > > +                               | UVC_CTRL_FLAG_AUTO_UPDATE,
> > > +       },
> > >  };
> > >
> > >  static const u32 uvc_control_classes[] = {
> > > @@ -603,6 +621,44 @@ static const struct uvc_control_mapping *uvc_ctrl_filter_plf_mapping(
> > >         return out_mapping;
> > >  }
> > >
> > > +static int uvc_get_rect(struct uvc_control_mapping *mapping, u8 query,
> > > +                       const void *uvc_in, size_t v4l2_size, void *v4l2_out)
> > > +{
> > > +       const struct uvc_rect *uvc_rect = uvc_in;
> > > +       struct v4l2_rect *v4l2_rect = v4l2_out;
> > > +
> > > +       if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
> > > +               return -EINVAL;
> > > +
> > > +       if (uvc_rect->left > uvc_rect->right ||
> > > +           uvc_rect->top > uvc_rect->bottom)
> > > +               return -EIO;
> > > +
> > > +       v4l2_rect->top = uvc_rect->top;
> > > +       v4l2_rect->left = uvc_rect->left;
> > > +       v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1;
> > > +       v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int uvc_set_rect(struct uvc_control_mapping *mapping, size_t v4l2_size,
> > > +                       const void *v4l2_in, void *uvc_out)
> > > +{
> > > +       struct uvc_rect *uvc_rect = uvc_out;
> > > +       const struct v4l2_rect *v4l2_rect = v4l2_in;
> > > +
> > > +       if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
> > > +               return -EINVAL;
> > > +
> > > +       uvc_rect->top = max(0xffff, v4l2_rect->top);
> > > +       uvc_rect->left = max(0xffff, v4l2_rect->left);
> > > +       uvc_rect->bottom = max(0xffff, v4l2_rect->height + v4l2_rect->top - 1);
> > > +       uvc_rect->right = max(0xffff, v4l2_rect->width + v4l2_rect->left - 1);
> >
> > Should these be min()?
>
> Ups :).
>
> Fixed in the next version.
>
> Thanks!

I've tested the patchset with this fix on Chrome OS and verified ROI
works as expected.

Reviewed-by: Yunke Cao <yunkec@google.com>
Tested-by: Yunke Cao <yunkec@google.com>

>
> >
> > >
> > > +
> > > +       return 0;
> > > +}
> > > +
> > >  static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
> > >         {
> > >                 .id             = V4L2_CID_BRIGHTNESS,
> > > @@ -897,6 +953,28 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
> > >                 .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
> > >                 .filter_mapping = uvc_ctrl_filter_plf_mapping,
> > >         },
> > > +       {
> > > +               .id             = V4L2_CID_UVC_REGION_OF_INTEREST_RECT,
> > > +               .entity         = UVC_GUID_UVC_CAMERA,
> > > +               .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > +               .size           = sizeof(struct uvc_rect) * 8,
> > > +               .offset         = 0,
> > > +               .v4l2_type      = V4L2_CTRL_TYPE_RECT,
> > > +               .data_type      = UVC_CTRL_DATA_TYPE_RECT,
> > > +               .get            = uvc_get_rect,
> > > +               .set            = uvc_set_rect,
> > > +               .name           = "Region Of Interest Rectangle",
> > > +       },
> > > +       {
> > > +               .id             = V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
> > > +               .entity         = UVC_GUID_UVC_CAMERA,
> > > +               .selector       = UVC_CT_REGION_OF_INTEREST_CONTROL,
> > > +               .size           = 16,
> > > +               .offset         = 64,
> > > +               .v4l2_type      = V4L2_CTRL_TYPE_BITMASK,
> > > +               .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
> > > +               .name           = "Region Of Interest Auto Controls",
> > > +       },
> > >  };
> > >
> > >  /* ------------------------------------------------------------------------
> > > @@ -1465,6 +1543,9 @@ static int __uvc_queryctrl_boundaries(struct uvc_video_chain *chain,
> > >
> > >  static size_t uvc_mapping_v4l2_size(struct uvc_control_mapping *mapping)
> > >  {
> > > +       if (mapping->v4l2_type == V4L2_CTRL_TYPE_RECT)
> > > +               return sizeof(struct v4l2_rect);
> > > +
> > >         if (uvc_ctrl_mapping_is_compound(mapping))
> > >                 return DIV_ROUND_UP(mapping->size, 8);
> > >
> > > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> > > index 8aca1a2fe587..d910a5e5b514 100644
> > > --- a/drivers/media/usb/uvc/uvcvideo.h
> > > +++ b/drivers/media/usb/uvc/uvcvideo.h
> > > @@ -294,6 +294,13 @@ struct uvc_streaming_header {
> > >         u8 bTriggerUsage;
> > >  };
> > >
> > > +struct uvc_rect {
> > > +       u16 top;
> > > +       u16 left;
> > > +       u16 bottom;
> > > +       u16 right;
> > > +} __packed;
> > > +
> > >  enum uvc_buffer_state {
> > >         UVC_BUF_STATE_IDLE      = 0,
> > >         UVC_BUF_STATE_QUEUED    = 1,
> > > diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
> > > index 2ff0e8a3a683..2afb4420e6c4 100644
> > > --- a/include/uapi/linux/usb/video.h
> > > +++ b/include/uapi/linux/usb/video.h
> > > @@ -104,6 +104,7 @@
> > >  #define UVC_CT_ROLL_ABSOLUTE_CONTROL                   0x0f
> > >  #define UVC_CT_ROLL_RELATIVE_CONTROL                   0x10
> > >  #define UVC_CT_PRIVACY_CONTROL                         0x11
> > > +#define UVC_CT_REGION_OF_INTEREST_CONTROL              0x14
> > >
> > >  /* A.9.5. Processing Unit Control Selectors */
> > >  #define UVC_PU_CONTROL_UNDEFINED                       0x00
> > > diff --git a/include/uapi/linux/uvcvideo.h b/include/uapi/linux/uvcvideo.h
> > > index f86185456dc5..cbe15bca9569 100644
> > > --- a/include/uapi/linux/uvcvideo.h
> > > +++ b/include/uapi/linux/uvcvideo.h
> > > @@ -16,6 +16,7 @@
> > >  #define UVC_CTRL_DATA_TYPE_BOOLEAN     3
> > >  #define UVC_CTRL_DATA_TYPE_ENUM                4
> > >  #define UVC_CTRL_DATA_TYPE_BITMASK     5
> > > +#define UVC_CTRL_DATA_TYPE_RECT                6
> > >
> > >  /* Control flags */
> > >  #define UVC_CTRL_FLAG_SET_CUR          (1 << 0)
> > > @@ -38,6 +39,18 @@
> > >
> > >  #define UVC_MENU_NAME_LEN 32
> > >
> > > +/* V4L2 driver-specific controls */
> > > +#define V4L2_CID_UVC_REGION_OF_INTEREST_RECT   (V4L2_CID_USER_UVC_BASE + 1)
> > > +#define V4L2_CID_UVC_REGION_OF_INTEREST_AUTO   (V4L2_CID_USER_UVC_BASE + 2)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE              (1 << 0)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS                  (1 << 1)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE         (1 << 2)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS                 (1 << 3)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT           (1 << 4)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK      (1 << 5)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION   (1 << 6)
> > > +#define V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY                (1 << 7)
> > > +
> > >  struct uvc_menu_info {
> > >         __u32 value;
> > >         __u8 name[UVC_MENU_NAME_LEN];
> > > diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> > > index 974fd254e573..6c91d6fa4708 100644
> > > --- a/include/uapi/linux/v4l2-controls.h
> > > +++ b/include/uapi/linux/v4l2-controls.h
> > > @@ -215,6 +215,13 @@ enum v4l2_colorfx {
> > >   */
> > >  #define V4L2_CID_USER_THP7312_BASE             (V4L2_CID_USER_BASE + 0x11c0)
> > >
> > > +/*
> > > + * The base for the uvc driver controls.
> > > + * See linux/uvcvideo.h for the list of controls.
> > > + * We reserve 64 controls for this driver.
> > > + */
> > > +#define V4L2_CID_USER_UVC_BASE                 (V4L2_CID_USER_BASE + 0x11e0)
> > > +
> > >  /* MPEG-class control IDs */
> > >  /* The MPEG controls are applicable to all codec controls
> > >   * and the 'MPEG' part of the define is historical */
> > > @@ -1089,6 +1096,8 @@ enum v4l2_auto_focus_range {
> > >
> > >  #define V4L2_CID_HDR_SENSOR_MODE               (V4L2_CID_CAMERA_CLASS_BASE+36)
> > >
> > > +/* CAMERA-class private control IDs */
> > > +
> >
> > Do we still need this comment?
> >
> > Best,
> > Yunke
> >
> > >  /* FM Modulator class control IDs */
> > >
> > >  #define V4L2_CID_FM_TX_CLASS_BASE              (V4L2_CTRL_CLASS_FM_TX | 0x900)
> > >
> > > --
> > > 2.47.0.338.g60cca15819-goog
> > >
>
>
>
> --
> Ricardo Ribalda
diff mbox series

Patch

diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index f262e05ad3a8..5b619ef40dd3 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -358,6 +358,24 @@  static const struct uvc_control_info uvc_ctrls[] = {
 		.flags		= UVC_CTRL_FLAG_GET_CUR
 				| UVC_CTRL_FLAG_AUTO_UPDATE,
 	},
+	/*
+	 * UVC_CTRL_FLAG_AUTO_UPDATE is needed because the RoI may get updated
+	 * by sensors.
+	 * "This RoI should be the same as specified in most recent SET_CUR
+	 * except in the case where the ‘Auto Detect and Track’ and/or
+	 * ‘Image Stabilization’ bit have been set."
+	 * 4.2.2.1.20 Digital Region of Interest (ROI) Control
+	 */
+	{
+		.entity		= UVC_GUID_UVC_CAMERA,
+		.selector	= UVC_CT_REGION_OF_INTEREST_CONTROL,
+		.index		= 21,
+		.size		= 10,
+		.flags		= UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+				| UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
+				| UVC_CTRL_FLAG_GET_DEF
+				| UVC_CTRL_FLAG_AUTO_UPDATE,
+	},
 };
 
 static const u32 uvc_control_classes[] = {
@@ -603,6 +621,44 @@  static const struct uvc_control_mapping *uvc_ctrl_filter_plf_mapping(
 	return out_mapping;
 }
 
+static int uvc_get_rect(struct uvc_control_mapping *mapping, u8 query,
+			const void *uvc_in, size_t v4l2_size, void *v4l2_out)
+{
+	const struct uvc_rect *uvc_rect = uvc_in;
+	struct v4l2_rect *v4l2_rect = v4l2_out;
+
+	if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
+		return -EINVAL;
+
+	if (uvc_rect->left > uvc_rect->right ||
+	    uvc_rect->top > uvc_rect->bottom)
+		return -EIO;
+
+	v4l2_rect->top = uvc_rect->top;
+	v4l2_rect->left = uvc_rect->left;
+	v4l2_rect->height = uvc_rect->bottom - uvc_rect->top + 1;
+	v4l2_rect->width = uvc_rect->right - uvc_rect->left + 1;
+
+	return 0;
+}
+
+static int uvc_set_rect(struct uvc_control_mapping *mapping, size_t v4l2_size,
+			const void *v4l2_in, void *uvc_out)
+{
+	struct uvc_rect *uvc_rect = uvc_out;
+	const struct v4l2_rect *v4l2_rect = v4l2_in;
+
+	if (WARN_ON(v4l2_size != sizeof(struct v4l2_rect)))
+		return -EINVAL;
+
+	uvc_rect->top = max(0xffff, v4l2_rect->top);
+	uvc_rect->left = max(0xffff, v4l2_rect->left);
+	uvc_rect->bottom = max(0xffff, v4l2_rect->height + v4l2_rect->top - 1);
+	uvc_rect->right = max(0xffff, v4l2_rect->width + v4l2_rect->left - 1);
+
+	return 0;
+}
+
 static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
 	{
 		.id		= V4L2_CID_BRIGHTNESS,
@@ -897,6 +953,28 @@  static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.selector	= UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
 		.filter_mapping	= uvc_ctrl_filter_plf_mapping,
 	},
+	{
+		.id		= V4L2_CID_UVC_REGION_OF_INTEREST_RECT,
+		.entity		= UVC_GUID_UVC_CAMERA,
+		.selector	= UVC_CT_REGION_OF_INTEREST_CONTROL,
+		.size		= sizeof(struct uvc_rect) * 8,
+		.offset		= 0,
+		.v4l2_type	= V4L2_CTRL_TYPE_RECT,
+		.data_type	= UVC_CTRL_DATA_TYPE_RECT,
+		.get		= uvc_get_rect,
+		.set		= uvc_set_rect,
+		.name		= "Region Of Interest Rectangle",
+	},
+	{
+		.id		= V4L2_CID_UVC_REGION_OF_INTEREST_AUTO,
+		.entity		= UVC_GUID_UVC_CAMERA,
+		.selector	= UVC_CT_REGION_OF_INTEREST_CONTROL,
+		.size		= 16,
+		.offset		= 64,
+		.v4l2_type	= V4L2_CTRL_TYPE_BITMASK,
+		.data_type	= UVC_CTRL_DATA_TYPE_BITMASK,
+		.name		= "Region Of Interest Auto Controls",
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -1465,6 +1543,9 @@  static int __uvc_queryctrl_boundaries(struct uvc_video_chain *chain,
 
 static size_t uvc_mapping_v4l2_size(struct uvc_control_mapping *mapping)
 {
+	if (mapping->v4l2_type == V4L2_CTRL_TYPE_RECT)
+		return sizeof(struct v4l2_rect);
+
 	if (uvc_ctrl_mapping_is_compound(mapping))
 		return DIV_ROUND_UP(mapping->size, 8);
 
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 8aca1a2fe587..d910a5e5b514 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -294,6 +294,13 @@  struct uvc_streaming_header {
 	u8 bTriggerUsage;
 };
 
+struct uvc_rect {
+	u16 top;
+	u16 left;
+	u16 bottom;
+	u16 right;
+} __packed;
+
 enum uvc_buffer_state {
 	UVC_BUF_STATE_IDLE	= 0,
 	UVC_BUF_STATE_QUEUED	= 1,
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
index 2ff0e8a3a683..2afb4420e6c4 100644
--- a/include/uapi/linux/usb/video.h
+++ b/include/uapi/linux/usb/video.h
@@ -104,6 +104,7 @@ 
 #define UVC_CT_ROLL_ABSOLUTE_CONTROL			0x0f
 #define UVC_CT_ROLL_RELATIVE_CONTROL			0x10
 #define UVC_CT_PRIVACY_CONTROL				0x11
+#define UVC_CT_REGION_OF_INTEREST_CONTROL		0x14
 
 /* A.9.5. Processing Unit Control Selectors */
 #define UVC_PU_CONTROL_UNDEFINED			0x00
diff --git a/include/uapi/linux/uvcvideo.h b/include/uapi/linux/uvcvideo.h
index f86185456dc5..cbe15bca9569 100644
--- a/include/uapi/linux/uvcvideo.h
+++ b/include/uapi/linux/uvcvideo.h
@@ -16,6 +16,7 @@ 
 #define UVC_CTRL_DATA_TYPE_BOOLEAN	3
 #define UVC_CTRL_DATA_TYPE_ENUM		4
 #define UVC_CTRL_DATA_TYPE_BITMASK	5
+#define UVC_CTRL_DATA_TYPE_RECT		6
 
 /* Control flags */
 #define UVC_CTRL_FLAG_SET_CUR		(1 << 0)
@@ -38,6 +39,18 @@ 
 
 #define UVC_MENU_NAME_LEN 32
 
+/* V4L2 driver-specific controls */
+#define V4L2_CID_UVC_REGION_OF_INTEREST_RECT	(V4L2_CID_USER_UVC_BASE + 1)
+#define V4L2_CID_UVC_REGION_OF_INTEREST_AUTO	(V4L2_CID_USER_UVC_BASE + 2)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_EXPOSURE		(1 << 0)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IRIS			(1 << 1)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_WHITE_BALANCE		(1 << 2)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FOCUS			(1 << 3)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_FACE_DETECT		(1 << 4)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_DETECT_AND_TRACK	(1 << 5)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_IMAGE_STABILIZATION	(1 << 6)
+#define V4L2_UVC_REGION_OF_INTEREST_AUTO_HIGHER_QUALITY		(1 << 7)
+
 struct uvc_menu_info {
 	__u32 value;
 	__u8 name[UVC_MENU_NAME_LEN];
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 974fd254e573..6c91d6fa4708 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -215,6 +215,13 @@  enum v4l2_colorfx {
  */
 #define V4L2_CID_USER_THP7312_BASE		(V4L2_CID_USER_BASE + 0x11c0)
 
+/*
+ * The base for the uvc driver controls.
+ * See linux/uvcvideo.h for the list of controls.
+ * We reserve 64 controls for this driver.
+ */
+#define V4L2_CID_USER_UVC_BASE			(V4L2_CID_USER_BASE + 0x11e0)
+
 /* MPEG-class control IDs */
 /* The MPEG controls are applicable to all codec controls
  * and the 'MPEG' part of the define is historical */
@@ -1089,6 +1096,8 @@  enum v4l2_auto_focus_range {
 
 #define V4L2_CID_HDR_SENSOR_MODE		(V4L2_CID_CAMERA_CLASS_BASE+36)
 
+/* CAMERA-class private control IDs */
+
 /* FM Modulator class control IDs */
 
 #define V4L2_CID_FM_TX_CLASS_BASE		(V4L2_CTRL_CLASS_FM_TX | 0x900)