static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { FAR struct usbmsc_dev_s *priv; FAR struct usbmsc_req_s *reqcontainer; irqstate_t flags; int i; usbtrace(TRACE_CLASSUNBIND, 0); #ifdef CONFIG_DEBUG if (!driver || !dev || !dev->ep0) { usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0); return; } #endif /* Extract reference to private data */ priv = ((FAR struct usbmsc_driver_s *)driver)->dev; #ifdef CONFIG_DEBUG if (!priv) { usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND1), 0); return; } #endif /* The worker thread should have already been stopped by the * driver un-initialize logic. */ DEBUGASSERT(priv->thstate == USBMSC_STATE_TERMINATED || priv->thstate == USBMSC_STATE_NOTSTARTED); /* Make sure that we are not already unbound */ if (priv != NULL) { /* Make sure that the endpoints have been unconfigured. If * we were terminated gracefully, then the configuration should * already have been reset. If not, then calling usbmsc_resetconfig * should cause the endpoints to immediately terminate all * transfers and return the requests to us (with result == -ESHUTDOWN) */ usbmsc_resetconfig(priv); up_mdelay(50); /* Free the pre-allocated control request */ if (priv->ctrlreq != NULL) { usbmsc_freereq(dev->ep0, priv->ctrlreq); priv->ctrlreq = NULL; } /* Free pre-allocated read requests (which should all have * been returned to the free list at this time -- we don't check) */ for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++) { reqcontainer = &priv->rdreqs[i]; if (reqcontainer->req) { usbmsc_freereq(priv->epbulkout, reqcontainer->req); reqcontainer->req = NULL; } } /* Free the bulk OUT endpoint */ if (priv->epbulkout) { DEV_FREEEP(dev, priv->epbulkout); priv->epbulkout = NULL; } /* Free write requests that are not in use (which should be all * of them */ flags = irqsave(); while (!sq_empty(&priv->wrreqlist)) { reqcontainer = (struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist); if (reqcontainer->req != NULL) { usbmsc_freereq(priv->epbulkin, reqcontainer->req); } } /* Free the bulk IN endpoint */ if (priv->epbulkin) { DEV_FREEEP(dev, priv->epbulkin); priv->epbulkin = NULL; } irqrestore(flags); } }
static void usbclass_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) { struct apbridge_dev_s *priv; usbtrace(TRACE_CLASSUNBIND, 0); #ifdef CONFIG_DEBUG if (!driver || !dev || !dev->ep0) { usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0); return; } #endif /* Extract reference to private data */ priv = ((struct apbridge_driver_s *)driver)->dev; #ifdef CONFIG_DEBUG if (!priv) { usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EP0NOTBOUND), 0); return; } #endif /* Make sure that we are not already unbound */ if (priv != NULL) { /* Make sure that the endpoints have been unconfigured. If * we were terminated gracefully, then the configuration should * already have been reset. If not, then calling usbclass_resetconfig * should cause the endpoints to immediately terminate all * transfers and return the requests to us (with result == -ESHUTDOWN) */ usbclass_resetconfig(priv); up_mdelay(50); /* Free the interrupt IN endpoint */ if (priv->epintin) { DEV_FREEEP(dev, priv->epintin); priv->epintin = NULL; } /* Free the bulk IN endpoint */ if (priv->epbulkin) { DEV_FREEEP(dev, priv->epbulkin); priv->epbulkin = NULL; } /* Free the pre-allocated control request */ if (priv->ctrlreq != NULL) { usbclass_freereq(dev->ep0, priv->ctrlreq); priv->ctrlreq = NULL; } /* Free the bulk OUT endpoint */ if (priv->epbulkout) { DEV_FREEEP(dev, priv->epbulkout); priv->epbulkout = NULL; } } }