diff options
Diffstat (limited to 'sys/dev/usb/ohci.c')
-rw-r--r-- | sys/dev/usb/ohci.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 76c7aebd60c..789aa62a83c 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ohci.c,v 1.139 2014/08/10 11:18:57 mpi Exp $ */ +/* $OpenBSD: ohci.c,v 1.140 2014/10/05 08:40:29 mpi Exp $ */ /* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ @@ -88,6 +88,7 @@ usbd_status ohci_alloc_std_chain(struct ohci_softc *, u_int, struct ohci_soft_td **); usbd_status ohci_open(struct usbd_pipe *); +int ohci_setaddr(struct usbd_device *, int); void ohci_poll(struct usbd_bus *); void ohci_softintr(void *); void ohci_waitintr(struct ohci_softc *, struct usbd_xfer *); @@ -232,7 +233,7 @@ struct ohci_pipe { struct usbd_bus_methods ohci_bus_methods = { .open_pipe = ohci_open, - .dev_setaddr = usbd_set_address, + .dev_setaddr = ohci_setaddr, .soft_intr = ohci_softintr, .do_poll = ohci_poll, .allocx = ohci_allocx, @@ -2006,6 +2007,40 @@ ohci_open(struct usbd_pipe *pipe) } /* + * Work around the half configured control (default) pipe when setting + * the address of a device. + * + * Because a single ED is setup per endpoint in ohci_open(), and the + * control pipe is configured before we could have set the address + * of the device or read the wMaxPacketSize of the endpoint, we have + * to re-open the pipe twice here. + */ +int +ohci_setaddr(struct usbd_device *dev, int addr) +{ + /* Root Hub */ + if (dev->depth == 0) + return (0); + + /* Re-establish the default pipe with the new max packet size. */ + ohci_device_ctrl_close(dev->default_pipe); + if (ohci_open(dev->default_pipe)) + return (EINVAL); + + if (usbd_set_address(dev, addr)) + return (1); + + dev->address = addr; + + /* Re-establish the default pipe with the new address. */ + ohci_device_ctrl_close(dev->default_pipe); + if (ohci_open(dev->default_pipe)) + return (EINVAL); + + return (0); +} + +/* * Close a reqular pipe. * Assumes that there are no pending transactions. */ |