aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorRicardo Ribalda2022-06-07 14:43:59 +0100
committerMauro Carvalho Chehab2022-07-16 08:50:27 +0100
commit86f7ef77315687df144042762325c53d9a3a28c9 (patch)
tree4231fc14c843742b1ec1ad58b55232bd9b27caef /drivers/media/usb
parent710871163510cd78948a095e929e28c1434b4506 (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.c27
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h1
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 {