Marcus,
Below diff works, in similar way like previous diff. With the diff
opening and closing ugen(4) results in consistent behaviour.
Setting SANE_CUSTOM_LIBUSB_TIMEOUT between 6 and 10 seconds makes my
scanner work. I'm gonna test your diff, which you sent for sane
backends.
On Wed, Jan 06, 2021 at 08:56:55AM +0100, Marcus Glocker wrote:
>
> Improved diff without the need for HC specific checks.
>
>
> Index: dev/usb/ugen.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/ugen.c,v
> retrieving revision 1.109
> diff -u -p -u -p -r1.109 ugen.c
> --- dev/usb/ugen.c 25 Dec 2020 12:59:52 -0000 1.109
> +++ dev/usb/ugen.c 6 Jan 2021 07:19:32 -0000
> @@ -46,9 +46,12 @@
> #include <sys/vnode.h>
> #include <sys/poll.h>
>
> +#include <machine/bus.h>
> +
> #include <dev/usb/usb.h>
> #include <dev/usb/usbdi.h>
> #include <dev/usb/usbdi_util.h>
> +#include <dev/usb/usbdivar.h>
>
> #ifdef UGEN_DEBUG
> #define DPRINTF(x) do { if (ugendebug) printf x; } while (0)
> @@ -114,6 +117,7 @@ int ugen_do_close(struct ugen_softc *, i
> int ugen_set_config(struct ugen_softc *sc, int configno);
> int ugen_set_interface(struct ugen_softc *, int, int);
> int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx);
> +int ugen_clear_endpoint_toggle(struct ugen_softc *, struct usbd_interface *);
>
> #define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
> #define UGENENDPOINT(n) (minor(n) & 0xf)
> @@ -302,6 +306,8 @@ ugenopen(dev_t dev, int flag, int mode,
> DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
> sc, endpt, dir, sce));
> edesc = sce->edesc;
> + /* Clear device endpoint toggle. */
> + ugen_clear_endpoint_toggle(sc, sce->iface);
> switch (UE_GET_XFERTYPE(edesc->bmAttributes)) {
> case UE_INTERRUPT:
> if (dir == OUT) {
> @@ -329,6 +335,8 @@ ugenopen(dev_t dev, int flag, int mode,
> clfree(&sce->q);
> return (EIO);
> }
> + /* Clear HC endpoint toggle. */
> + usbd_clear_endpoint_toggle(sce->pipeh);
> DPRINTFN(5, ("ugenopen: interrupt open done\n"));
> break;
> case UE_BULK:
> @@ -336,6 +344,8 @@ ugenopen(dev_t dev, int flag, int mode,
> edesc->bEndpointAddress, 0, &sce->pipeh);
> if (err)
> return (EIO);
> + /* Clear HC endpoint toggle. */
> + usbd_clear_endpoint_toggle(sce->pipeh);
> break;
> case UE_ISOCHRONOUS:
> if (dir == OUT)
> @@ -940,6 +950,50 @@ ugen_get_alt_index(struct ugen_softc *sc
> if (err)
> return (-1);
> return (usbd_get_interface_altindex(iface));
> +}
> +
> +int
> +ugen_clear_endpoint_toggle(struct ugen_softc *sc, struct usbd_interface
> *iface)
> +{
> + usb_interface_descriptor_t *id;
> + usb_endpoint_descriptor_t *ed;
> + usbd_status err;
> + int i;
> +
> + /* Only halt interface endpoints when none are in use. */
> + for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
> + if (i == USB_CONTROL_ENDPOINT)
> + continue;
> + if (sc->sc_is_open[i] != 0)
> + return (0);
> + }
> + DPRINTFN(1,("%s: halt interface endpoints\n", __func__));
> +
> + id = usbd_get_interface_descriptor(iface);
> + if (id == NULL)
> + return (-1);
> +
> + for (i = 0; i < id->bNumEndpoints; i++) {
> + ed = usbd_interface2endpoint_descriptor(iface, i);
> + if (ed == NULL)
> + return (-1);
> +
> + switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
> + case UE_BULK:
> + case UE_INTERRUPT:
> + err = usbd_clear_endpoint_feature(sc->sc_udev,
> + ed->bEndpointAddress, UF_ENDPOINT_HALT);
> + if (err) {
> + printf("%s: halt endpoint failed!\n", __func__);
> + return (-1);
> + }
> + break;
> + default:
> + break;
> + }
> + }
> +
> + return (0);
> }
>
> int
> Index: dev/usb/usbdi_util.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/usbdi_util.c,v
> retrieving revision 1.44
> diff -u -p -u -p -r1.44 usbdi_util.c
> --- dev/usb/usbdi_util.c 6 Oct 2019 17:11:51 -0000 1.44
> +++ dev/usb/usbdi_util.c 6 Jan 2021 07:19:32 -0000
> @@ -192,6 +192,19 @@ usbd_clear_port_feature(struct usbd_devi
> }
>
> usbd_status
> +usbd_clear_endpoint_feature(struct usbd_device *dev, int epaddr, int sel)
> +{
> + usb_device_request_t req;
> +
> + req.bmRequestType = UT_WRITE_ENDPOINT;
> + req.bRequest = UR_CLEAR_FEATURE;
> + USETW(req.wValue, sel);
> + USETW(req.wIndex, epaddr);
> + USETW(req.wLength, 0);
> + return (usbd_do_request(dev, &req, 0));
> +}
> +
> +usbd_status
> usbd_set_port_feature(struct usbd_device *dev, int port, int sel)
> {
> usb_device_request_t req;
> Index: dev/usb/usbdi_util.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/usbdi_util.h,v
> retrieving revision 1.29
> diff -u -p -u -p -r1.29 usbdi_util.h
> --- dev/usb/usbdi_util.h 8 Dec 2014 22:00:11 -0000 1.29
> +++ dev/usb/usbdi_util.h 6 Jan 2021 07:19:32 -0000
> @@ -41,6 +41,7 @@ usbd_status usbd_set_hub_feature(struct
> usbd_status usbd_clear_hub_feature(struct usbd_device *, int);
> usbd_status usbd_set_port_feature(struct usbd_device *dev, int, int);
> usbd_status usbd_clear_port_feature(struct usbd_device *, int, int);
> +usbd_status usbd_clear_endpoint_feature(struct usbd_device *, int, int);
> usbd_status usbd_get_device_status(struct usbd_device *, usb_status_t *);
> usbd_status usbd_get_hub_status(struct usbd_device *, usb_hub_status_t *);
> usbd_status usbd_get_hub_descriptor(struct usbd_device *,
--
Regards,
Mikolaj