-/* $OpenBSD: ugen.c,v 1.109 2020/12/25 12:59:52 visa Exp $ */
+/* $OpenBSD: ugen.c,v 1.110 2021/01/25 14:14:42 mglocker Exp $ */
/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
#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)
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);
+void ugen_clear_iface_eps(struct ugen_softc *, struct usbd_interface *);
#define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
#define UGENENDPOINT(n) (minor(n) & 0xf)
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_iface_eps(sc, sce->iface);
switch (UE_GET_XFERTYPE(edesc->bmAttributes)) {
case UE_INTERRUPT:
if (dir == OUT) {
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:
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)
return (0);
}
+
+void
+ugen_clear_iface_eps(struct ugen_softc *sc, struct usbd_interface *iface)
+{
+ usb_interface_descriptor_t *id;
+ usb_endpoint_descriptor_t *ed;
+ uint8_t xfertype;
+ int i;
+
+ /* Only clear 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;
+ }
+ DPRINTFN(1,("%s: clear interface eps\n", __func__));
+
+ id = usbd_get_interface_descriptor(iface);
+ if (id == NULL)
+ goto bad;
+
+ for (i = 0; i < id->bNumEndpoints; i++) {
+ ed = usbd_interface2endpoint_descriptor(iface, i);
+ if (ed == NULL)
+ goto bad;
+
+ xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
+ if (xfertype == UE_BULK || xfertype == UE_INTERRUPT) {
+ if (usbd_clear_endpoint_feature(sc->sc_udev,
+ ed->bEndpointAddress, UF_ENDPOINT_HALT))
+ goto bad;
+ }
+ }
+ return;
+bad:
+ printf("%s: clear endpoints failed!\n", __func__);
+}
-/* $OpenBSD: uhidev.c,v 1.83 2020/08/31 12:26:49 patrick Exp $ */
+/* $OpenBSD: uhidev.c,v 1.84 2021/01/25 14:14:42 mglocker Exp $ */
/* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */
/*
void uhidev_get_report_async_cb(struct usbd_xfer *, void *, usbd_status);
void uhidev_set_report_async_cb(struct usbd_xfer *, void *, usbd_status);
+void uhidev_clear_iface_eps(struct uhidev_softc *, struct usbd_interface *);
struct cfdriver uhidev_cd = {
NULL, "uhidev", DV_DULL
DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize,
sc->sc_iep_addr));
+ /* Clear device endpoint toggle. */
+ uhidev_clear_iface_eps(sc, sc->sc_iface);
+
err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr,
USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf,
sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL);
error = EIO;
goto out1;
}
+ /* Clear HC endpoint toggle. */
+ usbd_clear_endpoint_toggle(sc->sc_ipipe);
DPRINTF(("uhidev_open: sc->sc_ipipe=%p\n", sc->sc_ipipe));
error = EIO;
goto out2;
}
+ /* Clear HC endpoint toggle. */
+ usbd_clear_endpoint_toggle(sc->sc_opipe);
DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe));
}
return 0;
}
+
+void
+uhidev_clear_iface_eps(struct uhidev_softc *sc, struct usbd_interface *iface)
+{
+ usb_interface_descriptor_t *id;
+ usb_endpoint_descriptor_t *ed;
+ uint8_t xfertype;
+ int i;
+
+ /* Only clear interface endpoints when none are in use. */
+ if (sc->sc_ipipe || sc->sc_opipe)
+ return;
+ DPRINTFN(1,("%s: clear interface eps\n", __func__));
+
+ id = usbd_get_interface_descriptor(iface);
+ if (id == NULL)
+ goto bad;
+
+ for (i = 0; i < id->bNumEndpoints; i++) {
+ ed = usbd_interface2endpoint_descriptor(iface, i);
+ if (ed == NULL)
+ goto bad;
+
+ xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
+ if (xfertype == UE_BULK || xfertype == UE_INTERRUPT) {
+ if (usbd_clear_endpoint_feature(sc->sc_udev,
+ ed->bEndpointAddress, UF_ENDPOINT_HALT))
+ goto bad;
+ }
+ }
+ return;
+bad:
+ printf("%s: clear endpoints failed!\n", __func__);
+}