From e7792435c70e6611944a146c394f50d7f3194c8d Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 25 Apr 2015 11:17:37 -0600 Subject: [PATCH] Add missing logic to destroy a class when the device is no longer connected to the hub port --- arch/arm/src/lpc17xx/lpc17_usbhost.c | 6 +++++ drivers/usbhost/usbhost_hub.c | 33 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index 4f082f313a..11543bb92e 100644 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -931,6 +931,12 @@ static inline int lpc17_remctrled(struct lpc17_usbhost_s *priv, prev->hw.nexted = ed->hw.nexted; } + + /* Just in case the hardware happens to be processing this ed now... + * it should go back to the control list head. + */ + + ed->hw.nexted = 0; } return OK; diff --git a/drivers/usbhost/usbhost_hub.c b/drivers/usbhost/usbhost_hub.c index fd4cdcffc0..123da2e404 100644 --- a/drivers/usbhost/usbhost_hub.c +++ b/drivers/usbhost/usbhost_hub.c @@ -662,6 +662,7 @@ static void usbhost_hub_event(FAR void *arg) { FAR struct usbhost_class_s *hubclass; FAR struct usbhost_hubport_s *hport; + FAR struct usbhost_hubport_s *connport; FAR struct usbhost_hubpriv_s *priv; FAR struct usb_ctrlreq_s *ctrlreq; struct usb_portstatus_s portstatus; @@ -739,7 +740,7 @@ static void usbhost_hub_event(FAR void *arg) ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, NULL); if (ret < 0) { - udbg("ERROR: Failed to clear port %d change mask %x: %d\n", + udbg("ERROR: Failed to clear port %d change mask %04x: %d\n", port, mask, ret); } @@ -760,7 +761,7 @@ static void usbhost_hub_event(FAR void *arg) uint16_t debouncestable = 0; uint16_t connection = 0xffff; - uvdbg("Port %d status %x change %x\n", port, status, change); + uvdbg("Port %d status %04x change %04x\n", port, status, change); /* Debounce */ @@ -822,7 +823,9 @@ static void usbhost_hub_event(FAR void *arg) if ((status & USBHUB_PORT_STAT_CONNECTION) != 0) { - /* Connect */ + /* Device connected to a port on the hub */ + + uvdbg("Connection on port %d\n", port); ctrlreq->type = USBHUB_REQ_TYPE_PORT; ctrlreq->req = USBHUB_REQ_SETFEATURE; @@ -862,8 +865,6 @@ static void usbhost_hub_event(FAR void *arg) if ((status & USBHUB_PORT_STAT_RESET) == 0 && (status & USBHUB_PORT_STAT_ENABLE) != 0) { - FAR struct usbhost_hubport_s *connport; - if ((change & USBHUB_PORT_STAT_CRESET) != 0) { ctrlreq->type = USBHUB_REQ_TYPE_PORT; @@ -916,12 +917,29 @@ static void usbhost_hub_event(FAR void *arg) } else { - /* Disconnect */ + /* Device disconnected from a port on the hub. Release port + * resources. + */ + + uvdbg("Disconnection on port %d\n", port); + + /* Free any devices classes connect on this hub port */ + + connport = &priv->hport[port]; + if (connport->devclass != NULL) + { + CLASS_DISCONNECTED(connport->devclass); + connport->devclass = NULL; + } + + /* Free any resources used by the hub port */ + + usbhost_hport_deactivate(connport); } } else if (change) { - udbg("WARNING: status %x change %x not handled\n", status, change); + udbg("WARNING: status %04x change %04x not handled\n", status, change); } } @@ -1024,6 +1042,7 @@ static void usbhost_disconnect_event(FAR void *arg) if (child->devclass != NULL) { CLASS_DISCONNECTED(child->devclass); + child->devclass = NULL; } /* Free any resources used by the hub port */