diff options
author | Ricardo Ribalda | 2022-06-07 14:43:59 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab | 2022-07-16 08:50:27 +0100 |
commit | 86f7ef77315687df144042762325c53d9a3a28c9 (patch) | |
tree | 4231fc14c843742b1ec1ad58b55232bd9b27caef /drivers/media/usb | |
parent | 710871163510cd78948a095e929e28c1434b4506 (diff) |
media: uvcvideo: Add support for per-device control mapping overrides
Some devices do not implement all their controls in a way that complies
with the UVC specification. This is for instance the case for several
devices that do not support the disabled mode for the power line
frequency control. Add a mechanism to allow per-device control mapping
overrides to avoid errors when accessing non-compliant controls.
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r-- | drivers/media/usb/uvc/uvc_ctrl.c | 27 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvcvideo.h | 1 |
2 files changed, 26 insertions, 2 deletions
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 95fdd41ab20b..e4826a846861 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -2444,14 +2444,37 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, if (!ctrl->initialized) return; - /* Process common mappings first. */ + /* + * First check if the device provides a custom mapping for this control, + * used to override standard mappings for non-conformant devices. Don't + * process standard mappings if a custom mapping is found. This + * mechanism doesn't support combining standard and custom mappings for + * a single control. + */ + if (chain->dev->info->mappings) { + bool custom = false; + unsigned int i; + + for (i = 0; (mapping = chain->dev->info->mappings[i]); ++i) { + if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && + ctrl->info.selector == mapping->selector) { + __uvc_ctrl_add_mapping(chain, ctrl, mapping); + custom = true; + } + } + + if (custom) + return; + } + + /* Process common mappings next. */ for (; mapping < mend; ++mapping) { if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && ctrl->info.selector == mapping->selector) __uvc_ctrl_add_mapping(chain, ctrl, mapping); } - /* And then version-specific mappings. */ + /* Finally process version-specific mappings. */ if (chain->dev->uvc_version < 0x0150) { mapping = uvc_ctrl_mappings_uvc11; mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings_uvc11); diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index d2eb107347ea..24c911aeebce 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -668,6 +668,7 @@ struct uvc_device_info { u32 quirks; u32 meta_format; u16 uvc_version; + const struct uvc_control_mapping **mappings; }; struct uvc_device { |