-/* $OpenBSD: uhub.c,v 1.67 2014/05/28 11:20:55 mpi Exp $ */
+/* $OpenBSD: uhub.c,v 1.68 2014/07/09 18:15:04 mpi Exp $ */
/* $NetBSD: uhub.c,v 1.64 2003/02/08 03:32:51 ichiro Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */
int uhub_match(struct device *, void *, void *);
void uhub_attach(struct device *, struct device *, void *);
int uhub_detach(struct device *, int);
-int uhub_activate(struct device *, int);
struct cfdriver uhub_cd = {
NULL, "uhub", DV_DULL
};
-const struct cfattach uhub_ca = {
- sizeof(struct uhub_softc),
- uhub_match,
- uhub_attach,
- uhub_detach,
- uhub_activate,
+const struct cfattach uhub_ca = {
+ sizeof(struct uhub_softc), uhub_match, uhub_attach, uhub_detach
};
-struct cfattach uhub_uhub_ca = {
- sizeof(struct uhub_softc), uhub_match, uhub_attach,
- uhub_detach, uhub_activate
+const struct cfattach uhub_uhub_ca = {
+ sizeof(struct uhub_softc), uhub_match, uhub_attach, uhub_detach
};
int
disco:
if (up->device != NULL) {
/* Disconnected */
- usb_disconnect_port(up, &sc->sc_dev);
+ usbd_detach(up->device, &sc->sc_dev);
+ up->device = NULL;
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
return (0);
}
-int
-uhub_activate(struct device *self, int act)
-{
- struct uhub_softc *sc = (struct uhub_softc *)self;
- struct usbd_hub *hub = sc->sc_hub->hub;
- struct usbd_device *dev;
- int nports, port, i;
-
- switch (act) {
- case DVACT_DEACTIVATE:
- if (hub == NULL) /* malfunctioning hub */
- break;
- nports = hub->hubdesc.bNbrPorts;
- for(port = 0; port < nports; port++) {
- dev = hub->ports[port].device;
- if (dev != NULL && dev->subdevs != NULL) {
- for (i = 0; dev->subdevs[i] != NULL; i++)
- config_deactivate(dev->subdevs[i]);
- }
- }
- break;
- }
- return (0);
-}
-
/*
* Called from process context when the hub is gone.
* Detach all devices on active ports.
nports = hub->hubdesc.bNbrPorts;
for(port = 0; port < nports; port++) {
rup = &hub->ports[port];
- if (rup->device)
- usb_disconnect_port(rup, self);
+ if (rup->device != NULL) {
+ usbd_detach(rup->device, self);
+ rup->device = NULL;
+ }
}
if (hub->ports[0].tt)
-/* $OpenBSD: usb_subr.c,v 1.101 2014/07/09 15:47:54 mpi Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.102 2014/07/09 18:15:04 mpi Exp $ */
/* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
struct usbd_device *, int, int);
int usbd_printBCD(char *cp, size_t len, int bcd);
-void usb_free_device(struct usbd_device *, struct usbd_port *);
+void usb_free_device(struct usbd_device *);
#ifdef USBVERBOSE
#include <dev/usb/usbdevs_data.h>
err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
&dev->default_pipe);
if (err) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
USB_MAX_IPACKET, dd);
}
- /* fail to get device descriptor, give up */
if (err) {
- DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
- "failed\n", addr));
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
dev->speed));
if (dd->bDescriptorType != UDESC_DEVICE) {
- /* Illegal device descriptor */
- DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
- dd->bDescriptorType));
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (USBD_INVAL);
}
if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
- DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (USBD_INVAL);
}
err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
&dev->default_pipe);
if (err) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
err = usbd_reload_device_desc(dev);
if (err) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
/* Set the address if the HC didn't do it already. */
if (bus->methods->dev_setaddr != NULL &&
bus->methods->dev_setaddr(dev, addr)) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (USBD_SET_ADDR_FAILED);
}
err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
&dev->default_pipe);
if (err) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
err = usbd_probe_and_attach(parent, dev, port, addr);
if (err) {
- usb_free_device(dev, up);
+ usb_free_device(dev);
+ up->device = NULL;
return (err);
}
}
void
-usb_free_device(struct usbd_device *dev, struct usbd_port *up)
+usb_free_device(struct usbd_device *dev)
{
int ifcidx, nifc;
free(dev->cdesc, M_USB);
if (dev->subdevs != NULL)
free(dev->subdevs, M_USB);
- up->device = NULL;
dev->bus->devices[dev->address] = NULL;
free(dev, M_USB);
* Called from process context when we discover that a port has
* been disconnected.
*/
-void
-usb_disconnect_port(struct usbd_port *up, struct device *parent)
+int
+usbd_detach(struct usbd_device *dev, struct device *parent)
{
- struct usbd_device *dev = up->device;
- int i;
-
- DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
- up, dev, up->portno));
-
-#ifdef DIAGNOSTIC
- if (dev == NULL) {
- printf("usb_disconnect_port: no device\n");
- return;
- }
-#endif
+ int rv;
- if (dev->subdevs != NULL) {
- DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
- for (i = 0; dev->subdevs[i]; i++) {
- DPRINTF(("%s: at %s", dev->subdevs[i]->dv_xname,
- parent->dv_xname));
- if (up->portno != 0)
- DPRINTF((" port %d", up->portno));
- DPRINTF((" (addr %d) deactivated\n", dev->address));
- config_deactivate(dev->subdevs[i]);
- }
- for (i = 0; dev->subdevs[i]; i++) {
- DPRINTF((" (addr %d) disconnected\n", dev->address));
- config_detach(dev->subdevs[i], DETACH_FORCE);
- dev->subdevs[i] = 0;
- }
- }
+ rv = config_detach_children(parent, DETACH_FORCE);
+ if (rv == 0)
+ usb_free_device(dev);
- usb_free_device(dev, up);
+ return (rv);
}