summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-03-19 10:29:17 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-03-19 10:29:17 +0000
commit8a2dc096f7398aeaecfb5a2d432e39cac203db40 (patch)
tree94bf69b6659a7907b6e55452a8f763133aecab91 /sys/dev/usb
parentac96b236166f8ac2ecd3cd82b494036fbea13644 (diff)
Use the same workaround as ehci(4) and ohci(4) in setaddr() to deal with
half configured control pipe, from Patrick Wildt.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/dwc2/dwc2.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/sys/dev/usb/dwc2/dwc2.c b/sys/dev/usb/dwc2/dwc2.c
index afa749d80b6..1016bbc288b 100644
--- a/sys/dev/usb/dwc2/dwc2.c
+++ b/sys/dev/usb/dwc2/dwc2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwc2.c,v 1.22 2015/02/14 05:52:19 uebayasi Exp $ */
+/* $OpenBSD: dwc2.c,v 1.23 2015/03/19 10:29:16 mpi Exp $ */
/* $NetBSD: dwc2.c,v 1.32 2014/09/02 23:26:20 macallan Exp $ */
/*-
@@ -91,6 +91,7 @@ int dwc2debug = 0;
#endif
STATIC usbd_status dwc2_open(struct usbd_pipe *);
+STATIC int dwc2_setaddr(struct usbd_device *, int);
STATIC void dwc2_poll(struct usbd_bus *);
STATIC void dwc2_softintr(void *);
STATIC void dwc2_waitintr(struct dwc2_softc *, struct usbd_xfer *);
@@ -172,6 +173,7 @@ dwc2_free_bus_bandwidth(struct dwc2_hsotg *hsotg, u16 bw,
STATIC struct usbd_bus_methods dwc2_bus_methods = {
.open_pipe = dwc2_open,
+ .dev_setaddr = dwc2_setaddr,
.soft_intr = dwc2_softintr,
.do_poll = dwc2_poll,
#if 0
@@ -269,6 +271,29 @@ dwc2_freem(struct usbd_bus *bus, struct usb_dma *dma)
}
#endif
+/*
+ * Work around the half configured control (default) pipe when setting
+ * the address of a device.
+ */
+STATIC int
+dwc2_setaddr(struct usbd_device *dev, int addr)
+{
+ if (usbd_set_address(dev, addr))
+ return (1);
+
+ dev->address = addr;
+
+ /*
+ * Re-establish the default pipe with the new address and the
+ * new max packet size.
+ */
+ dwc2_close_pipe(dev->default_pipe);
+ if (dwc2_open(dev->default_pipe))
+ return (EINVAL);
+
+ return (0);
+}
+
struct usbd_xfer *
dwc2_allocx(struct usbd_bus *bus)
{