[linux-uvc-devel] [PATCH 1/1] media: uvcvideo: Add quirk for exponential exposure
Linux UVC driver and tools
Brought to you by:
pinchartl
|
From: Scott K L. <lo...@co...> - 2021-05-04 19:03:45
|
At least some of the Microsoft LifeCam series of webcams exhibit a
behavior which requires a 'quirk' to be handled properly. When
configuring he absolute exposure value of the image, there are only a
handful of values which will result in a consistent change to the image
exposure, while all other values appear to result in a maximum
exposure.
The valid values appear to follow an exponential pattern from the
maximum value (10000) down to the minimum, yielding less than 15
possible values depending on the device's reported minimum.
Signed-off-by: Scott K Logan <lo...@co...>
---
drivers/media/usb/uvc/uvc_ctrl.c | 42 ++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvc_driver.c | 18 +++++++++++++
drivers/media/usb/uvc/uvcvideo.h | 1 +
3 files changed, 61 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c
b/drivers/media/usb/uvc/uvc_ctrl.c
index 011e69427b7c..767c4032c35a 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -2010,6 +2010,40 @@ int uvc_ctrl_restore_values(struct uvc_device
*dev)
return 0;
}
+/* -------------------------------------------------------------------
-------
+ * Quirks
+ */
+
+static s32 uvc_ctrl_get_abs_exposure_exponential(
+ struct uvc_control_mapping *mapping, u8 query, const u8 *data)
+{
+ s32 i;
+ s32 value = uvc_get_le_value(mapping, query, data);
+
+ switch (query) {
+ case UVC_GET_CUR:
+ case UVC_GET_MIN:
+ case UVC_GET_MAX:
+ case UVC_GET_DEF:
+ for (i = 0; i < 14; ++i) {
+ if (10000 >> i <= value)
+ break;
+ }
+ return 14 - i;
+ case UVC_GET_RES:
+ return 1;
+ default:
+ return value;
+ }
+}
+
+static void uvc_ctrl_set_abs_exposure_exponential(
+ struct uvc_control_mapping *mapping, s32 value, u8 *data)
+{
+ value = 10000 >> (14 - value);
+ uvc_set_le_value(mapping, value, data);
+}
+
/* -------------------------------------------------------------------
-------
* Control and mapping handling
*/
@@ -2069,6 +2103,14 @@ static int __uvc_ctrl_add_mapping(struct
uvc_device *dev,
if (map->set == NULL)
map->set = uvc_set_le_value;
+ if ((dev->quirks & UVC_QUIRK_EXPONENTIAL_EXPOSURE) &&
+ ctrl->info.selector ==
UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL) {
+ uvc_trace(UVC_TRACE_CONTROL,
+ "Applying exponential exposure quirk\n");
+ map->get = uvc_ctrl_get_abs_exposure_exponential;
+ map->set = uvc_ctrl_set_abs_exposure_exponential;
+ }
+
list_add_tail(&map->list, &ctrl->info.mappings);
uvc_trace(UVC_TRACE_CONTROL,
"Adding mapping '%s' to control %pUl/%u.\n",
diff --git a/drivers/media/usb/uvc/uvc_driver.c
b/drivers/media/usb/uvc/uvc_driver.c
index ddb9eaa11be7..f823b201395a 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2530,6 +2530,24 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info =
(kernel_ulong_t)&uvc_quirk_probe_minmax },
+ /* Microsoft Lifecam HD-5000 */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x045e,
+ .idProduct = 0x076d,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info =
UVC_INFO_QUIRK(UVC_QUIRK_EXPONENTIAL_EXPOSURE) },
+ /* Microsoft Lifecam Studio */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x045e,
+ .idProduct = 0x0772,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info =
UVC_INFO_QUIRK(UVC_QUIRK_EXPONENTIAL_EXPOSURE) },
/* Logitech Quickcam Fusion */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/usb/uvc/uvcvideo.h
b/drivers/media/usb/uvc/uvcvideo.h
index a3dfacf069c4..16e9ecbb2946 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -203,6 +203,7 @@
#define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400
#define UVC_QUIRK_FORCE_Y8 0x00000800
#define UVC_QUIRK_FORCE_BPP 0x00001000
+#define UVC_QUIRK_EXPONENTIAL_EXPOSURE 0x00002000
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
--
2.30.2
|