Hi,

similar to ehci/ohci, the default pipe has to be re-established after
setting the new MaxPacketSize and address.  Also, the following diff
makes dwc2 actually set the address by setting a setaddr() function
in the bus method struct.

This makes the raspberry Pi 2's USB properly enumerate all devices.

With help and input from mpi@.

Best regards,
Patrick

diff --git a/sys/dev/usb/dwc2/dwc2.c b/sys/dev/usb/dwc2/dwc2.c
index 2838819..30fc164 100644
--- sys/dev/usb/dwc2/dwc2.c
+++ sys/dev/usb/dwc2/dwc2.c
@@ -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,26 @@ 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. Re-establish the default pipe with the new
+ * address and the new max packet size.
+ */
+STATIC int
+dwc2_setaddr(struct usbd_device *dev, int addr)
+{
+       if (usbd_set_address(dev, addr))
+               return (1);
+
+       dev->address = addr;
+
+       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)
 {

Reply via email to