USB host: Need to include the port structure when disconnecting, otherwise may destroy a root hub port
This commit is contained in:
parent
973f572829
commit
c2a3f936aa
@ -467,7 +467,8 @@ static int efm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport,
|
||||
bool connected);
|
||||
#endif
|
||||
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr);
|
||||
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -4761,12 +4762,13 @@ static int efm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
static void efm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct efm32_usbhost_s *priv = (FAR struct efm32_usbhost_s *)drvr;
|
||||
DEBUGASSERT(priv);
|
||||
DEBUGASSERT(priv != NULL && hport != NULL);
|
||||
|
||||
priv->rhport.hport.devclass = NULL;
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -390,7 +390,8 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport,
|
||||
bool connected);
|
||||
#endif
|
||||
static void lpc17_disconnect(struct usbhost_driver_s *drvr);
|
||||
static void lpc17_disconnect(struct usbhost_driver_s *drvr,
|
||||
struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -3213,6 +3214,8 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -3223,12 +3226,13 @@ static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void lpc17_disconnect(struct usbhost_driver_s *drvr)
|
||||
static void lpc17_disconnect(struct usbhost_driver_s *drvr,
|
||||
struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
|
||||
DEBUGASSERT(priv);
|
||||
DEBUGASSERT(priv != NULL && hport != NULL);
|
||||
|
||||
priv->rhport.hport.devclass = NULL;
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -549,7 +549,8 @@ static int lpc31_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
|
||||
static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport, bool connected);
|
||||
#endif
|
||||
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr);
|
||||
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -4638,6 +4639,8 @@ static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -4648,15 +4651,16 @@ static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr;
|
||||
DEBUGASSERT(rhport);
|
||||
DEBUGASSERT(rhport != NULL && hport != NULL);
|
||||
|
||||
/* Unbind the class */
|
||||
/* REVISIT: Is there more that needs to be done? */
|
||||
|
||||
rhport->hport.hport.devclass = NULL;
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -425,7 +425,8 @@ static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
|
||||
static int sam_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport, bool connected);
|
||||
#endif
|
||||
static void sam_disconnect(FAR struct usbhost_driver_s *drvr);
|
||||
static void sam_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -4464,6 +4465,8 @@ static int sam_connect(FAR struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -4474,10 +4477,11 @@ static int sam_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void sam_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
static void sam_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
DEBUGASSERT(rhport);
|
||||
DEBUGASSERT(rhport != NULL && hport != NULL);
|
||||
|
||||
/* Unbind the class */
|
||||
/* REVISIT: Is there more that needs to be done? */
|
||||
|
@ -388,7 +388,7 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplis
|
||||
struct sam_ed_s *ed, uint32_t dirpid, uint32_t toggle,
|
||||
volatile uint8_t *buffer, size_t buflen);
|
||||
static int sam_ep0enqueue(struct sam_rhport_s *rhport);
|
||||
static void sam_ep0dequeue(struct sam_rhport_s *rhport);
|
||||
static void sam_ep0dequeue(struct sam_eplist_s *ep0);
|
||||
static int sam_wdhwait(struct sam_rhport_s *rhport, struct sam_ed_s *ed);
|
||||
#ifdef CONFIG_USBHOST_ASYNCH
|
||||
static int sam_wdhasynch(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
|
||||
@ -448,7 +448,8 @@ static int sam_connect(struct usbhost_driver_s *drvr,
|
||||
struct usbhost_hubport_s *hport,
|
||||
bool connected);
|
||||
#endif
|
||||
static void sam_disconnect(struct usbhost_driver_s *drvr);
|
||||
static void sam_disconnect(struct usbhost_driver_s *drvr,
|
||||
struct usbhost_hubport_s *hport);
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Data
|
||||
@ -1520,8 +1521,8 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_eplist_s *eplis
|
||||
* Name: sam_ep0enqueue
|
||||
*
|
||||
* Description:
|
||||
* Initialize ED for EP0, add it to the control ED list, and enable control
|
||||
* transfers.
|
||||
* Initialize ED for a root hub EP0, add it to the control ED list, and
|
||||
* enable control transfers.
|
||||
*
|
||||
* Input Parameters:
|
||||
* rhpndx - Root hub port index.
|
||||
@ -1609,14 +1610,15 @@ static int sam_ep0enqueue(struct sam_rhport_s *rhport)
|
||||
* list processing.
|
||||
*
|
||||
* Input Parameters:
|
||||
* rhpndx - Root hub port index.
|
||||
* ep0 - The control endpoint to be released. May be the control endpoint for
|
||||
* an attached hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void sam_ep0dequeue(struct sam_rhport_s *rhport)
|
||||
static void sam_ep0dequeue(struct sam_eplist_s *ep0)
|
||||
{
|
||||
struct sam_ed_s *edctrl;
|
||||
struct sam_ed_s *curred;
|
||||
@ -1627,8 +1629,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
|
||||
uintptr_t physcurr;
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(rhport && rhport->ep0init && rhport->ep0.ed != NULL &&
|
||||
rhport->ep0.tail != NULL);
|
||||
DEBUGASSERT(ep0->ed != NULL && ep0->tail != NULL);
|
||||
|
||||
/* ControlListEnable. This bit is cleared to disable the processing of the
|
||||
* Control list. We should never modify the control list while CLE is set.
|
||||
@ -1643,7 +1644,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
|
||||
* precedessor).
|
||||
*/
|
||||
|
||||
edctrl = rhport->ep0.ed;
|
||||
edctrl = ep0->ed;
|
||||
physcurr = sam_getreg(SAM_USBHOST_CTRLHEADED);
|
||||
|
||||
for (curred = (struct sam_ed_s *)sam_virtramaddr(physcurr),
|
||||
@ -1692,7 +1693,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
|
||||
|
||||
/* Release any TDs that may still be attached to the ED. */
|
||||
|
||||
tdtail = rhport->ep0.tail;
|
||||
tdtail = ep0->tail;
|
||||
physcurr = edctrl->hw.headp;
|
||||
|
||||
for (currtd = (struct sam_gtd_s *)sam_virtramaddr(physcurr);
|
||||
@ -1708,8 +1709,8 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
|
||||
sam_tdfree(tdtail);
|
||||
sam_edfree(edctrl);
|
||||
|
||||
rhport->ep0.ed = NULL;
|
||||
rhport->ep0.tail = NULL;
|
||||
ep0->ed = NULL;
|
||||
ep0->tail = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -2408,7 +2409,7 @@ static int sam_rh_enumerate(struct usbhost_connection_s *conn,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Add EP0 to the control list */
|
||||
/* Add root hub EP0 to the control list */
|
||||
|
||||
if (!rhport->ep0init)
|
||||
{
|
||||
@ -3659,6 +3660,8 @@ static int sam_connect(struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -3669,19 +3672,29 @@ static int sam_connect(struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void sam_disconnect(struct usbhost_driver_s *drvr)
|
||||
static void sam_disconnect(struct usbhost_driver_s *drvr,
|
||||
struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
DEBUGASSERT(rhport);
|
||||
struct sam_eplist_s *ep0;
|
||||
|
||||
DEBUGASSERT(rhport != NULL && hport != NULL && hport->ep0);
|
||||
ep0 = (struct sam_eplist_s *)hport->ep0;
|
||||
|
||||
/* Remove the disconnected port from the control list */
|
||||
|
||||
sam_ep0dequeue(rhport);
|
||||
rhport->ep0init = false;
|
||||
sam_ep0dequeue(ep0);
|
||||
|
||||
/* Unbind the class */
|
||||
/* Did we just dequeue EP0 from a hoot hub port? */
|
||||
|
||||
rhport->hport.hport.devclass = NULL;
|
||||
if (ROOTHUB(hport))
|
||||
{
|
||||
rhport->ep0init = false;
|
||||
}
|
||||
|
||||
/* Unbind the class from the port */
|
||||
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -454,7 +454,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport,
|
||||
bool connected);
|
||||
#endif
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -4684,6 +4685,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -4694,12 +4697,13 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
|
||||
DEBUGASSERT(priv);
|
||||
DEBUGASSERT(priv != NULL && hport != NULL);
|
||||
|
||||
priv->rhport.hport.devclass = NULL;
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -454,7 +454,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport,
|
||||
bool connected);
|
||||
#endif
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr);
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
|
||||
/* Initialization **************************************************************/
|
||||
|
||||
@ -4684,6 +4685,8 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -4694,12 +4697,13 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr)
|
||||
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
|
||||
DEBUGASSERT(priv);
|
||||
DEBUGASSERT(priv != NULL && hport != NULL);
|
||||
|
||||
priv->rhport.hport.devclass = NULL;
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -184,7 +184,7 @@ static int ehci_waiter(int argc, char *argv[])
|
||||
* Name: sam_usbinitialize
|
||||
*
|
||||
* Description:
|
||||
* Called from sam_usbinitialize very early in inialization to setup USB-related
|
||||
* Called from sam_usbinitialize very early in initialization to setup USB-related
|
||||
* GPIO pins for the SAMA5D4-EK board.
|
||||
*
|
||||
* USB Ports
|
||||
|
@ -798,7 +798,7 @@ static void usbhost_destroy(FAR void *arg)
|
||||
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
DRVR_DISCONNECT(hport->drvr);
|
||||
DRVR_DISCONNECT(hport->drvr, hport);
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
|
@ -654,7 +654,7 @@ static void usbhost_destroy(FAR void *arg)
|
||||
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
DRVR_DISCONNECT(hport->drvr);
|
||||
DRVR_DISCONNECT(hport->drvr, hport);
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
|
@ -1074,13 +1074,17 @@ static void usbhost_disconnect_event(FAR void *arg)
|
||||
usbhost_hport_deactivate(child);
|
||||
}
|
||||
|
||||
/* Deactivate the parent hub port (unless it is the root hub port) */
|
||||
|
||||
usbhost_hport_deactivate(hport);
|
||||
|
||||
/* Destroy the semaphores */
|
||||
|
||||
sem_destroy(&priv->exclsem);
|
||||
|
||||
/* Deactivate the parent hub port (unless it is the root hub port) */
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
usbhost_hport_deactivate(hport);
|
||||
DRVR_DISCONNECT(hport->drvr, hport);
|
||||
|
||||
/* Free the class instance */
|
||||
|
||||
|
@ -377,7 +377,7 @@ static void usbhost_destroy(FAR void *arg)
|
||||
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
DRVR_DISCONNECT(drvr);
|
||||
DRVR_DISCONNECT(drvr, hport);
|
||||
|
||||
/* And free the class instance. Hmmm.. this may execute on the worker
|
||||
* thread and the work structure is part of what is getting freed. That
|
||||
|
@ -952,7 +952,7 @@ static void usbhost_destroy(FAR void *arg)
|
||||
|
||||
/* Disconnect the USB host device */
|
||||
|
||||
DRVR_DISCONNECT(hport->drvr);
|
||||
DRVR_DISCONNECT(hport->drvr, hport);
|
||||
|
||||
/* Free the function address assigned to this device */
|
||||
|
||||
|
@ -579,6 +579,8 @@
|
||||
* Input Parameters:
|
||||
* drvr - The USB host driver instance obtained as a parameter from the call to
|
||||
* the class create() method.
|
||||
* hport - The port from which the device is being disconnected. Might be a port
|
||||
* on a hub.
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
@ -588,7 +590,7 @@
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#define DRVR_DISCONNECT(drvr) ((drvr)->disconnect(drvr))
|
||||
#define DRVR_DISCONNECT(drvr, hport) ((drvr)->disconnect(drvr, hport))
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
@ -873,7 +875,8 @@ struct usbhost_driver_s
|
||||
* (until a new instance is received from the create() method).
|
||||
*/
|
||||
|
||||
void (*disconnect)(FAR struct usbhost_driver_s *drvr);
|
||||
void (*disconnect)(FAR struct usbhost_driver_s *drvr,
|
||||
FAR struct usbhost_hubport_s *hport);
|
||||
};
|
||||
|
||||
/************************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user