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 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) +{ + 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); -}; - 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 */ -- 2.44.0.291.gc1ea87d7ee-goog