Hi, on my Lenovo X395 the uvideo(4) follows the current UVC 1.5 spec. The message length was increased with each specification, so now the buffer for probe messages is up to 48 bytes. On that particular device the camera sends a USB stall if we only supply the 26 bytes from the original UVC 1.0 spec. By increasing the length depending on the UVC version, and the other diff I sent, my webcam works fine.
Patrick diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c index 1a9dfc733fa..3cb93158955 100644 --- a/sys/dev/usb/uvideo.c +++ b/sys/dev/usb/uvideo.c @@ -67,6 +67,7 @@ struct uvideo_softc { struct device *sc_videodev; int sc_enabled; + int sc_max_ctrl_size; int sc_max_fbuf_size; int sc_negotiated_flag; int sc_frame_rate; @@ -725,6 +726,12 @@ uvideo_vc_parse_desc_header(struct uvideo_softc *sc, sc->sc_desc_vc_header.fix = d; sc->sc_desc_vc_header.baInterfaceNr = (uByte *)(d + 1); + if (UGETW(d->bcdUVC) < 0x0110) + sc->sc_max_ctrl_size = 26; + else if (UGETW(d->bcdUVC) < 0x0150) + sc->sc_max_ctrl_size = 34; + else + sc->sc_max_ctrl_size = 48; return (USBD_NORMAL_COMPLETION); } @@ -1438,7 +1445,7 @@ uvideo_vs_negotiation(struct uvideo_softc *sc, int commit) struct usb_video_header_desc *hd; struct usb_video_frame_desc *frame; uint8_t *p, *cur; - uint8_t probe_data[34]; + uint8_t probe_data[48]; uint32_t frame_ival, nivals, min, max, step, diff; usbd_status error; int i, ival_bytes, changed = 0; @@ -1622,7 +1629,7 @@ uvideo_vs_set_probe(struct uvideo_softc *sc, uint8_t *probe_data) tmp = tmp << 8; USETW(req.wValue, tmp); USETW(req.wIndex, sc->sc_vs_cur->iface); - USETW(req.wLength, 26); + USETW(req.wLength, sc->sc_max_ctrl_size); pc = (struct usb_video_probe_commit *)probe_data; @@ -1667,7 +1674,7 @@ uvideo_vs_get_probe(struct uvideo_softc *sc, uint8_t *probe_data, tmp = tmp << 8; USETW(req.wValue, tmp); USETW(req.wIndex, sc->sc_vs_cur->iface); - USETW(req.wLength, 26); + USETW(req.wLength, sc->sc_max_ctrl_size); pc = (struct usb_video_probe_commit *)probe_data; @@ -1710,7 +1717,7 @@ uvideo_vs_set_commit(struct uvideo_softc *sc, uint8_t *probe_data) tmp = tmp << 8; USETW(req.wValue, tmp); USETW(req.wIndex, sc->sc_vs_cur->iface); - USETW(req.wLength, 26); + USETW(req.wLength, sc->sc_max_ctrl_size); error = usbd_do_request(sc->sc_udev, &req, probe_data); if (error) {