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

Reply via email to