From nobody Tue Apr 7 04:33:35 2026 Received: from mail-lf1-f42.google.com (mail-lf1-f42.google.com [209.85.167.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D20E2399018 for ; Mon, 16 Mar 2026 13:34:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668090; cv=none; b=F6fvKFbcHrMSAhj6C9C+eaIytwFbpI9V/XLIHYzv9ViyDWM3FajN3nvtwW9R7p7pTRseXV7Y5d1QcT28lxTHEdgEHxfOlq58pOKoXPgbX5hv0ZLBw6x/ciOa0lfvgHDv5NMo8UCERsgaDm4nYOhroigDzm1h8lmTnweekXCp6SE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773668090; c=relaxed/simple; bh=j3lc1kn/wJoX+9cZrghmGTWwf9ptFSHlpETfxL8/X+g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FEcutgbYumMm9BBvsSZwwh/n5+uHgqSCjAuLRKKiws1Nmi0pfgySYx7y4dmob0GEi3uhtEYnODhgrG9y/3ixIVDRxwSsURCc+XOqgh0ayxVrC2JomRaDlMcoS/xVPYuKBVCGtJwTum4X175YgpZf3Q8gye4u9R+okUHS4elFmnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Mac0nOBh; arc=none smtp.client-ip=209.85.167.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Mac0nOBh" Received: by mail-lf1-f42.google.com with SMTP id 2adb3069b0e04-59e4989dacdso5161133e87.1 for ; Mon, 16 Mar 2026 06:34:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1773668087; x=1774272887; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=DulSoSsXGHcpQnyTZ9WUFnrdzO4ZXeWwNRNkWSs9pxw=; b=Mac0nOBheEOqgeYLVD2qN0okA6KPMeUJ+UHcDaxXTTyFDqb9cSEvSLt0D1J2lWXhg2 fMdQRw4CuVprGQXhw0DVXUJ86HodaraRoaAEZQpB6hIqO547xJ8Hq9nyYVoyrFW+IHMc tGNQFYlk3fKbITuM1FGh+RRcyENlFs8MxhfZs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773668087; x=1774272887; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=DulSoSsXGHcpQnyTZ9WUFnrdzO4ZXeWwNRNkWSs9pxw=; b=i79Zx4sZMb9JBSv5Gk/mgbLsKV3RRF270gIdAIpbzpizIz/lJRKlavXnc7wwPIopza XlngdVDiLSLmtvoaMflKqdkVO3TRonIaQz7ustzefUWA8R3iwVy9H7yohaoHU7mL2Ij8 ZlfhvXtUZCOSFKKk4m0G0y6oyFFzC9a28z0iGavUMZJZPp9enwawn5aHuTBcdEeVS4NI XNG3GXds2e1rMWOQQX6j8ZWE36pUuUtXLPxLnDlca92NmUZZO3xbbWwY6pP2mb3n3Lkr VL8fv7CTJwrA7Vztes9Y6oIY2qZod3+x6Nab73ax/WuS8fX/xVen7fqbQAeBDK5JApNe kPrg== X-Forwarded-Encrypted: i=1; AJvYcCWka1TlODTyVqTS8mEKVaok2hsrAn5src9b8os6x1kZ7NH8mPHJPT3TyeDcxKpJddCOZ33fEWDMD4TQzUY=@vger.kernel.org X-Gm-Message-State: AOJu0Yweg3M/+67YuANOQM27nNN/sdmNMaI5rR3U4GgsPHNaV4Jd1i/k d9pI+Dy45P4Bwgva/Zxki3yX6EMHkd1foXTwIPa6z2vZSuGb4/WkLv2SDJYJ1vL5EA== X-Gm-Gg: ATEYQzzTbYuoa3BoOmNSwZNtFnxPshJnKViC11PLC1ZLMa+TywU4P7UNwV5f5ciIhKE bj2E2XtNNsZ/0WQz6NibO5nsGYonFnVwhdcyS8g+S0EjH66c2HtDWx7Mb1Yaa9qxHU9w5KmqZ3Z kjrudhMMQta9jVwWk71eCd+cqAn/Q9DDEfkkPzNaB655KiaHWhD8dKHrWzyADu5daIukjB76/mA 72zFRzXqFJrNETo2YuZH8pwOy5WpLPXUVnyydHeWRpB+N/Q24qRZH0L+zF8fIL9yTaMve2NodRg r5RXnxxxsnbeTNpFId1ng4RxGkMFmTNeBC1zKkUQbAUp4Oze22Kd/4PfIAO7KEat/Qu5GaIgS55 f5Zuwd8R1NB704cy9v75cwsZnRJJYJXiDvca3jIY9TNSmTHBNnwZ0PSVFITgYyuTUS1q1QiIl9Y pc/HSKPbbZ720gWp0fhmUftNadIHoJVJ5Qe4/k1CX7b/25/ch+u6KCtvW+uFNhU5iW14kh1N5bD w== X-Received: by 2002:a05:6512:2c07:b0:5a1:45fc:34f4 with SMTP id 2adb3069b0e04-5a162ae9fc4mr3900183e87.22.1773668087000; Mon, 16 Mar 2026 06:34:47 -0700 (PDT) Received: from ribalda.c.googlers.com (27.69.88.34.bc.googleusercontent.com. [34.88.69.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5a156366a7fsm3481473e87.76.2026.03.16.06.34.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 06:34:46 -0700 (PDT) From: Ricardo Ribalda Date: Mon, 16 Mar 2026 13:34:44 +0000 Subject: [PATCH v3 1/4] media: uvcvideo: Import standard controls from uvcdynctrl Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260316-uvcdynctrl-v3-1-19cd4657e1f3@chromium.org> References: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> In-Reply-To: <20260316-uvcdynctrl-v3-0-19cd4657e1f3@chromium.org> To: Laurent Pinchart , Hans de Goede , Mauro Carvalho Chehab , Greg Kroah-Hartman Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Ricardo Ribalda , Manav Gautama , Martin Rubli X-Mailer: b4 0.14.3 The uvcdynctrl tool from libwebcam: https://sourceforge.net/projects/libwebcam/ maps proprietary controls into v4l2 controls using the UVCIOC_CTRL_MAP ioctl. The tool has not been updated for 10+ years now, and there is no reason for the UVC driver to not do the mapping by itself. This patch adds the mappings from the uvcdynctrl into the driver. Hopefully this effort can help in deprecating the UVCIOC_CTRL_MAP ioctl. Some background about UVCIOC_CTRL_MAP (thanks Laurent for the context): ``` this was envisioned as the base of a vibrant ecosystem where a large number of vendors would submit XML files that describe their XU control mappings, at a pace faster than could be supported by adding XU mappings to the driver. This vision failed to materialize and the tool has not been updated for 10+ years now. There is no reason to believe the situation will change. ``` During the porting, the following mappings where NOT imported because they were not using standard v4l2 IDs. It is recommended that userspace moves to UVCIOC_CTRL_QUERY for non standard controls. { .id =3D V4L2_CID_FLASH_MODE, .entity =3D UVC_GUID_SIS_LED_HW_CONTROL, .selector =3D 4, .size =3D 4, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0x3, .menu_mapping =3D { 0x20, 0x22 }, .menu_names =3D { "Off", "On" }, }, { .id =3D V4L2_CID_FLASH_FREQUENCY, .entity =3D UVC_GUID_SIS_LED_HW_CONTROL, .selector =3D 4, .size =3D 8, .offset =3D 16, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_LED1_MODE, .entity =3D UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector =3D 1, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0xF, .menu_mapping =3D { 0, 1, 2, 3 }, .menu_names =3D { "Off", "On", "Blinking", "Auto" }, }, { .id =3D V4L2_CID_LED1_FREQUENCY, .entity =3D UVC_GUID_LOGITECH_USER_HW_CONTROL_V1, .selector =3D 1, .size =3D 8, .offset =3D 16, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_DISABLE_PROCESSING, .entity =3D UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector =3D 5, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_BOOLEAN, .data_type =3D UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id =3D V4L2_CID_RAW_BITS_PER_PIXEL, .entity =3D UVC_GUID_LOGITECH_VIDEO_PIPE_V1, .selector =3D 8, .size =3D 8, .offset =3D 0, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id =3D V4L2_CID_LED1_MODE, .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, .selector =3D 0x09, .size =3D 2, .offset =3D 8, .v4l2_type =3D V4L2_CTRL_TYPE_MENU, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, .menu_mask =3D 0xF, .menu_mapping =3D { 0, 1, 2, 3 }, .menu_names =3D { "Off", "On", "Blink", "Auto" }, }, { .id =3D V4L2_CID_LED1_FREQUENCY, .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, .selector =3D 0x09, .size =3D 8, .offset =3D 24, .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, }, This script has been used to generate the mappings. They were then reformatted manually to follow the driver style. import sys import uuid import re import xml.etree.ElementTree as ET def get_namespace(root): return re.match(r"\{.*\}", root.tag).group(0) def get_single_guid(ns, constant): id =3D constant.find(ns + "id").text value =3D constant.find(ns + "value").text return (id, value) def get_constants(ns, root): out =3D dict() for constant in root.iter(ns + "constant"): attr =3D constant.attrib if attr["type"] =3D=3D "integer": id, value =3D get_single_guid(ns, constant) if id in out: print(f"dupe constant {id}") out[id] =3D value return out def get_guids(ns, root): out =3D dict() for constant in root.iter(ns + "constant"): attr =3D constant.attrib if attr["type"] =3D=3D "guid": id, value =3D get_single_guid(ns, constant) if id in out: print(f"dupe guid {id}") out[id] =3D value return out def get_single_control(ns, control): out =3D {} for id in "entity", "selector", "index", "size", "description": v =3D control.find(ns + id) if v is None and id =3D=3D "description": continue out[id] =3D v.text reqs =3D set() for r in control.find(ns + "requests"): reqs.add(r.text) out["requests"] =3D reqs return (control.attrib["id"], out) def get_controls(ns, root): out =3D dict() for control in root.iter(ns + "control"): id, value =3D get_single_control(ns, control) if id in out: print(f"Dupe control id {id}") out[id] =3D value return out def get_single_mapping(ns, mapping): out =3D {} out["name"] =3D mapping.find(ns + "name").text uvc =3D mapping.find(ns + "uvc") for id in "size", "offset", "uvc_type": out[id] =3D uvc.find(ns + id).text out["control_ref"] =3D uvc.find(ns + "control_ref").attrib["idref"] v4l2 =3D mapping.find(ns + "v4l2") for id in "id", "v4l2_type": out[id] =3D v4l2.find(ns + id).text menu =3D {} for entry in v4l2.iter(ns + "menu_entry"): menu[entry.attrib["name"]] =3D entry.attrib["value"] if menu: out["menu"] =3D menu return out def get_mapping(ns, root): out =3D [] for control in root.iter(ns + "mapping"): mapping =3D get_single_mapping(ns, control) out +=3D [mapping] return out def print_guids(guids): for g in guids: print(f"#define {g} \\") u_bytes =3D uuid.UUID(guids[g]).bytes_le u_bytes =3D [f"0x{b:02x}" for b in u_bytes] print("\t{ " + ", ".join(u_bytes) + " }") def print_flags(flags): get_range =3D {"GET_MIN", "GET_DEF", "GET_MAX", "GET_CUR", "GET_RES"} if get_range.issubset(flags): flags -=3D get_range flags.add("GET_RANGE") flags =3D list(flags) flags.sort() out =3D "" for f in flags[:-1]: out +=3D f"UVC_CTRL_FLAG_{f}\n\t\t\t\t| " out +=3D f"UVC_CTRL_FLAG_{flags[-1]}" return out def print_description(desc): print("/*") for line in desc.strip().splitlines(): print(f" * {line.strip()}") print("*/") def print_controls(controls, cons): for id in controls: c =3D controls[id] if "description" in c: print_description(c["description"]) print( f"""\t{{ \t\t.entity\t\t=3D {c["entity"]}, \t\t.selector\t=3D {cons[c["selector"]]}, \t\t.index\t\t=3D {c["index"]}, \t\t.size\t\t=3D {c["size"]}, \t\t.flags\t\t=3D {print_flags(c["requests"])}, \t}},""" ) def menu_mapping_txt(menu): out =3D f"\n\t\t.menu_mask\t=3D 0x{((1< Cc: Martin Rubli Reviewed-by: Laurent Pinchart Signed-off-by: Ricardo Ribalda --- drivers/media/usb/uvc/uvc_ctrl.c | 174 +++++++++++++++++++++++++++++++++++= ++++ include/linux/usb/uvc.h | 6 ++ 2 files changed, 180 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_c= trl.c index b9a3d9257a11..b6e020b41671 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -385,6 +385,99 @@ static const struct uvc_control_info uvc_ctrls[] =3D { | UVC_CTRL_FLAG_GET_RANGE | UVC_CTRL_FLAG_RESTORE, }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + * The unit of the pan/tilt values is 1/64th of a degree and the + * resolution is 1 degree. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .index =3D 0, + .size =3D 4, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + * + * Both bits can be set at the same time to reset both, pan and tilt, + * at the same time. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .index =3D 1, + .size =3D 1, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of focus motor movements for camera models that + * support mechanical focus. + * + * Bits 0 to 7 allow selection of the desired lens position. + * There are no physical units, instead, the focus range is spread over + * 256 logical units with 0 representing infinity focus and 255 being + * macro focus. + */ + { + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 3, + .index =3D 2, + .size =3D 6, + .flags =3D UVC_CTRL_FLAG_GET_CUR + | UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Allows the control of pan/tilt motor movements for camera models + * that support mechanical pan/tilt. + * + * Bits 0 to 15 control pan, bits 16 to 31 control tilt. + */ + { + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .index =3D 0, + .size =3D 4, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, + /* + * Reset the pan/tilt motors to their original position for camera + * models that support mechanical pan/tilt. + * + * Setting bit 0 resets the pan position. + * Setting bit 1 resets the tilt position. + */ + { + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .index =3D 1, + .size =3D 1, + .flags =3D UVC_CTRL_FLAG_GET_DEF + | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_MIN + | UVC_CTRL_FLAG_GET_RES + | UVC_CTRL_FLAG_SET_CUR, + }, }; =20 static const u32 uvc_control_classes[] =3D { @@ -1009,6 +1102,87 @@ static const struct uvc_control_mapping uvc_ctrl_map= pings[] =3D { .menu_mask =3D BIT(V4L2_COLORFX_VIVID) | BIT(V4L2_COLORFX_NONE), }, + { + .id =3D V4L2_CID_PAN_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .size =3D 16, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_TILT_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 1, + .size =3D 16, + .offset =3D 16, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_PAN_RESET, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .size =3D 1, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_TILT_RESET, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 2, + .size =3D 1, + .offset =3D 1, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_PAN_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .size =3D 16, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_TILT_RELATIVE, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 1, + .size =3D 16, + .offset =3D 16, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id =3D V4L2_CID_PAN_RESET, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .size =3D 1, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_TILT_RESET, + .entity =3D UVC_GUID_LOGITECH_PERIPHERAL, + .selector =3D 2, + .size =3D 1, + .offset =3D 1, + .v4l2_type =3D V4L2_CTRL_TYPE_BUTTON, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id =3D V4L2_CID_FOCUS_ABSOLUTE, + .entity =3D UVC_GUID_LOGITECH_MOTOR_CONTROL_V1, + .selector =3D 3, + .size =3D 8, + .offset =3D 0, + .v4l2_type =3D V4L2_CTRL_TYPE_INTEGER, + .data_type =3D UVC_CTRL_DATA_TYPE_UNSIGNED, + }, }; =20 /* ------------------------------------------------------------------------ diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index ea92ac623a45..dea23aabbad4 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -43,6 +43,12 @@ #define UVC_GUID_MSXU_1_5 \ {0xdc, 0x95, 0x3f, 0x0f, 0x32, 0x26, 0x4e, 0x4c, \ 0x92, 0xc9, 0xa0, 0x47, 0x82, 0xf4, 0x3b, 0xc8} +#define UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 \ + {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ + 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56 } +#define UVC_GUID_LOGITECH_PERIPHERAL \ + {0x21, 0x2d, 0xe5, 0xff, 0x30, 0x80, 0x2c, 0x4e, \ + 0x82, 0xd9, 0xf5, 0x87, 0xd0, 0x05, 0x40, 0xbd } =20 /* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-e= xtensions-1-5#222-extension-unit-controls */ #define UVC_MSXU_CONTROL_FOCUS 0x01 --=20 2.53.0.851.ga537e3e6e9-goog