Index | Thread | Search

From:
"Kirill A. Korinsky" <kirill@korins.ky>
Subject:
sys/uvideo: support pre UVC 1.5 devices
To:
OpenBSD tech <tech@openbsd.org>
Cc:
Marcus Glocker <mglocker@openbsd.org>
Date:
Fri, 08 Aug 2025 19:34:29 +0200

Download raw body.

Thread
tech@,

my call for testing USB cameras leads to a bug report that old devices
may not work.

Why? Because UVC has a few different definition of probe structure.

Basic probe contains 26 bytes, and extended one 34 bytes. And UVC 1.5
extends it to 48 bytes.

When old device is attached, usbd_do_request() returns USBD_SHORT_XFER,
and we discard this device.

Instead I track actual len, reset not used memory and forward it to a
consumer, because it may know how to work with it.

This diff doesn't introduce any regression on my devices.

It was reported and tested by Daniel Konnoff on his Quanta ACER HD.

Ok?

Index: sys/dev/usb/uvideo.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/uvideo.c,v
diff -u -p -r1.260 uvideo.c
--- sys/dev/usb/uvideo.c	3 Aug 2025 20:00:11 -0000	1.260
+++ sys/dev/usb/uvideo.c	8 Aug 2025 12:41:35 -0000
@@ -2032,6 +2032,7 @@ uvideo_vs_get_probe(struct uvideo_softc 
 	usb_device_request_t req;
 	usbd_status error;
 	uint16_t tmp;
+	int actlen;
 	struct usb_video_probe_commit *pc;
 
 	req.bmRequestType = UVIDEO_GET_IF;
@@ -2044,13 +2045,18 @@ uvideo_vs_get_probe(struct uvideo_softc 
 
 	pc = (struct usb_video_probe_commit *)probe_data;
 
-	error = usbd_do_request(sc->sc_udev, &req, probe_data);
-	if (error) {
+	error = usbd_do_request_flags(sc->sc_udev, &req, probe_data, 0,
+	    &actlen, USBD_DEFAULT_TIMEOUT);
+	if (error != USBD_NORMAL_COMPLETION && error != USBD_SHORT_XFER) {
 		printf("%s: could not GET probe request: %s\n",
 		    DEVNAME(sc), usbd_errstr(error));
 		return (USBD_INVAL);
 	}
 
+	/* Different UVC version defines different length of a probe */
+	bzero(probe_data + actlen,
+	    sizeof(struct usb_video_probe_commit ) - actlen);
+
 	if (sc->sc_quirk &&
 	    sc->sc_quirk->flags & UVIDEO_FLAG_FORMAT_INDEX_IN_BMHINT &&
 	    UGETW(pc->bmHint) > 255) {
@@ -2065,7 +2071,8 @@ uvideo_vs_get_probe(struct uvideo_softc 
 		USETW(pc->bmHint, 1);
 	}
 
-	DPRINTF(1, "%s: GET probe request successfully\n", DEVNAME(sc));
+	DPRINTF(1, "%s: GET probe request successfully, length: %d\n",
+	    DEVNAME(sc), actlen);
 
 	DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint));
 	DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex);
@@ -2081,6 +2088,26 @@ uvideo_vs_get_probe(struct uvideo_softc 
 	    UGETDW(pc->dwMaxVideoFrameSize));
 	DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n",
 	    UGETDW(pc->dwMaxPayloadTransferSize));
+	DPRINTF(1, "dwClockFrequency=%d (Hz)\n",
+	    UGETDW(pc->dwClockFrequency));
+	DPRINTF(1, "bmFramingInfo=0x%02x\n", pc->bmFramingInfo);
+	DPRINTF(1, "bPreferedVersion=%d\n", pc->bPreferedVersion);
+	DPRINTF(1, "bMinVersion=%d\n", pc->bMinVersion);
+	DPRINTF(1, "bMaxVersion=%d\n", pc->bMaxVersion);
+	DPRINTF(1, "bUsage=%d\n", pc->bUsage);
+	DPRINTF(1, "bBitDepthLuma=%d\n", pc->bBitDepthLuma);
+	DPRINTF(1, "bmSettings=0x%02x\n", pc->bmSettings);
+	DPRINTF(1, "bMaxNumberOfRefFramesPlus1=%d\n",
+	    pc->bMaxNumberOfRefFramesPlus1);
+	DPRINTF(1, "bmRateControlModes=%d\n",
+	    UGETW(pc->bmRateControlModes));
+#ifdef UVIDEO_DEBUG
+	if (1 <= uvideo_debug) {
+		printf("bmLayoutPerStream=0x");
+		uvideo_hexdump(pc->bmLayoutPerStream,
+		    sizeof(pc->bmLayoutPerStream), 1);
+	}
+#endif
 
 	return (USBD_NORMAL_COMPLETION);
 }
Index: sys/dev/usb/uvideo.h
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/uvideo.h,v
diff -u -p -r1.67 uvideo.h
--- sys/dev/usb/uvideo.h	3 Aug 2025 20:00:11 -0000	1.67
+++ sys/dev/usb/uvideo.h	8 Aug 2025 12:18:43 -0000
@@ -275,7 +275,7 @@ struct usb_video_color_matching_descr {
 	uByte	bMatrixCoefficients;
 } __packed;
 
-/* Table 4-47: Video Probe and Commit Controls */
+/* Table 4-75: Video Probe and Commit Controls */
 struct usb_video_probe_commit {
 	uWord	bmHint;
 	uByte	bFormatIndex;
@@ -293,6 +293,12 @@ struct usb_video_probe_commit {
 	uByte	bPreferedVersion;
 	uByte	bMinVersion;
 	uByte	bMaxVersion;
+	uByte	bUsage;
+	uByte	bBitDepthLuma;
+	uByte	bmSettings;
+	uByte	bMaxNumberOfRefFramesPlus1;
+	uWord	bmRateControlModes;
+	uByte	bmLayoutPerStream[8];
 } __packed;
 
 /*