Download raw body.
sys/uvideo: clarify bulk endpoint stream closure
On Tue, Feb 11, 2025 at 09:13:08AM GMT, Kirill A. Korinsky wrote:
> tech@,
>
> Right now, we're using the same method to close the video stream for
> both bulk and non-bulk endpoints. This approach switches back to the
> default (zero) interface and turns off the camera LED. While this logic
> is valid for non-bulk endpoints, bulk endpoints always use the default
> interface. As a result, the switch is likely ignored by the device or
> may trigger a reset.
>
> Some devices can enter a broken state and won't function until they are
> reattached. One such example is the Elgato Game Capture HD60 S+. After
> the user presses 'q' in ffmpeg to stop the stream, the device becomes
> unusable until it is reattached. For embedded USB webcams, this issue
> could require a reboot to resolve.
>
> UVC does not specify how to notify a bulk-based device when the video
> stream stops. Both Linux and Windows send a CLEAR_FEATURE(HALT) request
> to the video streaming bulk endpoint.
>
> I've implemented the same logic in our codebase.
>
> I've tested it on my bulk webcams, and no regressions were observed, and by
> Laurence (cc'ed) who has access to Elgato device and it fixed the issue.
>
> Tests? Ok?
Seems reasonable to me. No regression found with my cams.
ok mglocker@
> Index: sys/dev/usb/uvideo.c
> ===================================================================
> RCS file: /home/cvs/src/sys/dev/usb/uvideo.c,v
> diff -u -p -r1.237 uvideo.c
> --- sys/dev/usb/uvideo.c 6 Feb 2025 13:15:50 -0000 1.237
> +++ sys/dev/usb/uvideo.c 8 Feb 2025 22:14:19 -0000
> @@ -2031,15 +2031,27 @@ uvideo_vs_close(struct uvideo_softc *sc)
> sc->sc_vs_cur->pipeh = NULL;
> }
>
> - /*
> - * Some devices need time to shutdown before we switch back to
> - * the default interface (0). Not doing so can leave the device
> - * back in a undefined condition.
> - */
> - usbd_delay_ms(sc->sc_udev, 100);
> + if (sc->sc_vs_cur->bulk_endpoint) {
> + /*
> + * UVC doesn't specify how to inform a bulk-based device
> + * when the video stream is stopped. Both, Linux and
> + * Windows send a CLEAR_FEATURE(HALT) request to the
> + * video streaming bulk endpoint.
> + */
> + if (usbd_clear_endpoint_feature(sc->sc_udev,
> + sc->sc_vs_cur->endpoint, UF_ENDPOINT_HALT))
> + printf("%s: clear endpoints failed!\n", __func__);
> + } else {
> + /*
> + * Some devices need time to shutdown before we switch back to
> + * the default interface (0). Not doing so can leave the device
> + * back in a undefined condition.
> + */
> + usbd_delay_ms(sc->sc_udev, 100);
>
> - /* switch back to default interface (turns off cam LED) */
> - (void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
> + /* switch back to default interface (turns off cam LED) */
> + (void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
> + }
> }
>
> usbd_status
>
> --
> wbr, Kirill
>
sys/uvideo: clarify bulk endpoint stream closure