Hi Ricardo, Thank you for the patch. On Mon, Mar 18, 2024 at 11:55:23PM +0000, Ricardo Ribalda wrote: > Some advanced controls might not be completely implemented by vendors. > > If the controls are a enumeration, UVC does not gives a way to probe > what is implemented and what is not. > > Lets create a new callback function where heuristics can be implemented s/Lets/Let's/ > to detect what is implemented and what not. > > Signed-off-by: Ricardo Ribalda <ribalda@xxxxxxxxxxxx> > --- > drivers/media/usb/uvc/uvc_ctrl.c | 15 ++++++++-- > drivers/media/usb/uvc/uvcvideo.h | 59 +++++++++++++++++++++------------------- > 2 files changed, 43 insertions(+), 31 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c > index e59a463c27618..3e939b4fbaaaf 100644 > --- a/drivers/media/usb/uvc/uvc_ctrl.c > +++ b/drivers/media/usb/uvc/uvc_ctrl.c > @@ -2434,6 +2434,14 @@ static int __uvc_ctrl_add_mapping(struct uvc_video_chain *chain, > return -ENOMEM; > } > > +static int __uvc_ctrl_add_custom_mapping(struct uvc_video_chain *chain, > + struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) The name isn't great is in most cases it doesn't add a custom mapping. > +{ > + if (mapping && mapping->add_mapping) > + return mapping->add_mapping(chain, ctrl, mapping); > + return __uvc_ctrl_add_mapping(chain, ctrl, mapping); > +} > + > int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, > const struct uvc_control_mapping *mapping) > { > @@ -2637,7 +2645,8 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, > > if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && > ctrl->info.selector == mapping->selector) { > - __uvc_ctrl_add_mapping(chain, ctrl, mapping); > + __uvc_ctrl_add_custom_mapping(chain, ctrl, > + mapping); > custom = true; > } > } > @@ -2652,7 +2661,7 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, > > if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && > ctrl->info.selector == mapping->selector) > - __uvc_ctrl_add_mapping(chain, ctrl, mapping); > + __uvc_ctrl_add_custom_mapping(chain, ctrl, mapping); > } > > /* Finally process version-specific mappings. */ > @@ -2664,7 +2673,7 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, > > if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && > ctrl->info.selector == mapping->selector) > - __uvc_ctrl_add_mapping(chain, ctrl, mapping); > + __uvc_ctrl_add_custom_mapping(chain, ctrl, mapping); > } > } > > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index 6fb0a78b1b009..611350a82c37f 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -101,34 +101,6 @@ struct uvc_control_info { > u32 flags; > }; > > -struct uvc_control_mapping { > - struct list_head list; > - struct list_head ev_subs; > - > - u32 id; > - char *name; > - u8 entity[16]; > - u8 selector; > - > - u8 size; > - u8 offset; > - enum v4l2_ctrl_type v4l2_type; > - u32 data_type; > - > - const u32 *menu_mapping; > - const char (*menu_names)[UVC_MENU_NAME_LEN]; > - unsigned long menu_mask; > - > - u32 master_id; > - s32 master_manual; > - u32 slave_ids[2]; > - > - s32 (*get)(struct uvc_control_mapping *mapping, u8 query, > - const u8 *data); > - void (*set)(struct uvc_control_mapping *mapping, s32 value, > - u8 *data); > -}; > - You can leave the structure here, close to the other related structuers, and add forward declarations of the uvc_video_chain and uvc_control structures just before the existing forward declaration of uvc_device. > struct uvc_control { > struct uvc_entity *entity; > struct uvc_control_info info; > @@ -336,6 +308,37 @@ struct uvc_video_chain { > u8 ctrl_class_bitmap; /* Bitmap of valid classes */ > }; > > +struct uvc_control_mapping { > + struct list_head list; > + struct list_head ev_subs; > + > + u32 id; > + char *name; > + u8 entity[16]; > + u8 selector; > + > + u8 size; > + u8 offset; > + enum v4l2_ctrl_type v4l2_type; > + u32 data_type; > + > + const u32 *menu_mapping; > + const char (*menu_names)[UVC_MENU_NAME_LEN]; > + unsigned long menu_mask; > + > + u32 master_id; > + s32 master_manual; > + u32 slave_ids[2]; > + > + int (*add_mapping)(struct uvc_video_chain *chain, > + struct uvc_control *ctrl, > + const struct uvc_control_mapping *mapping); > + s32 (*get)(struct uvc_control_mapping *mapping, u8 query, > + const u8 *data); > + void (*set)(struct uvc_control_mapping *mapping, s32 value, > + u8 *data); > +}; > + > struct uvc_stats_frame { > unsigned int size; /* Number of bytes captured */ > unsigned int first_data; /* Index of the first non-empty packet */ > -- Regards, Laurent Pinchart