Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5977a58 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

[media] uvcvideo: Fix bogus XU controls information



XU control information is supposed to be entirely discoverable using
standard UVC queries. As some devices report bogus information (such as
reporting a read-only control as being read-write), add a fixup table
for XU controls.

This table can also be used to selectively disable requests supposed to
be supported by all XU controls (GET_MIN, GET_MAX, GET_DEF, GET_RES) but
not correctly (or at all) supported by the device.

The table currently disables GET_CUR on the Logitech motor control XU
pan/tilt controls.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 52c58ad6
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -1164,6 +1164,45 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
 * Dynamic controls
 */

static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
	const struct uvc_control *ctrl, struct uvc_control_info *info)
{
	struct uvc_ctrl_fixup {
		struct usb_device_id id;
		u8 entity;
		u8 selector;
		u8 flags;
	};

	static const struct uvc_ctrl_fixup fixups[] = {
		{ { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
			UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
			UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR |
			UVC_CONTROL_AUTO_UPDATE },
		{ { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
			UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
			UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR |
			UVC_CONTROL_AUTO_UPDATE },
		{ { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
			UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
			UVC_CONTROL_GET_DEF | UVC_CONTROL_SET_CUR |
			UVC_CONTROL_AUTO_UPDATE },
	};

	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
		if (!usb_match_one_id(dev->intf, &fixups[i].id))
			continue;

		if (fixups[i].entity == ctrl->entity->id &&
		    fixups[i].selector == info->selector) {
			info->flags = fixups[i].flags;
			return;
		}
	}
}

/*
 * Query control information (size and flags) for XU controls.
 */
@@ -1211,6 +1250,8 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
		    | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
		       UVC_CONTROL_AUTO_UPDATE : 0);

	uvc_ctrl_fixup_xu_info(dev, ctrl, info);

	uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
		  "flags { get %u set %u auto %u }.\n",
		  info->entity, info->selector, info->size,