After a reset, need to re-connected to the bus

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4449 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-03-03 18:59:32 +00:00
parent dabec8c010
commit 73af31f231
1 changed files with 70 additions and 46 deletions

View File

@ -327,7 +327,8 @@ enum pic32mx_ctrlstate_e
CTRLSTATE_WAITSETUP = 0, /* No request in progress, waiting for setup */ CTRLSTATE_WAITSETUP = 0, /* No request in progress, waiting for setup */
CTRLSTATE_RDREQUEST, /* Read request (OUT) in progress */ CTRLSTATE_RDREQUEST, /* Read request (OUT) in progress */
CTRLSTATE_WRREQUEST, /* Write request (IN) in progress */ CTRLSTATE_WRREQUEST, /* Write request (IN) in progress */
CTRLSTATE_STALLED /* We are stalled */ CTRLSTATE_STALL, /* EP0 stall requested */
CTRLSTATE_STALLED /* EP0 is stalled */
}; };
union wb_u union wb_u
@ -1220,7 +1221,7 @@ static void pic32mx_dispatchrequest(struct pic32mx_usbdev_s *priv)
/* Stall on failure */ /* Stall on failure */
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_DISPATCHSTALL), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_DISPATCHSTALL), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
} }
@ -1499,7 +1500,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
index.b[MSB] != 0 || value.w != 0) index.b[MSB] != 0 || value.w != 0)
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADEPGETSTATUS), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADEPGETSTATUS), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
else else
{ {
@ -1512,7 +1513,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
if (epno >= PIC32MX_NENDPOINTS) if (epno >= PIC32MX_NENDPOINTS)
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADEPGETSTATUS), epno); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADEPGETSTATUS), epno);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
else else
{ {
@ -1559,7 +1560,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADDEVGETSTATUS), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADDEVGETSTATUS), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
break; break;
@ -1575,7 +1576,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
default: default:
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETSTATUS), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETSTATUS), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
break; break;
} }
@ -1647,7 +1648,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADCLEARFEATURE), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADCLEARFEATURE), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
else else
@ -1734,7 +1735,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETFEATURE), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETFEATURE), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
else else
@ -1760,7 +1761,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
index.w != 0 || len.w != 0 || value.w > 127) index.w != 0 || len.w != 0 || value.w > 127)
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETADDRESS), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETADDRESS), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
else else
{ {
@ -1799,7 +1800,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETSETDESC), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETSETDESC), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
break; break;
@ -1824,7 +1825,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETCONFIG), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADGETCONFIG), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
break; break;
@ -1849,7 +1850,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETCONFIG), 0); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BADSETCONFIG), 0);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
break; break;
@ -1891,7 +1892,7 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
default: default:
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDCTRLREQ), priv->ctrl.req); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDCTRLREQ), priv->ctrl.req);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
break; break;
} }
@ -1912,9 +1913,9 @@ resume_packet_processing:
* must be sent (may be a zero length packet). * must be sent (may be a zero length packet).
* 2. The request was successfully handled by the class implementation. In * 2. The request was successfully handled by the class implementation. In
* case, the EP0 IN response has already been queued and the local variable * case, the EP0 IN response has already been queued and the local variable
* 'dispatched' will be set to true and ctrlstate != CTRLSTATE_STALLED; * 'dispatched' will be set to true and ctrlstate != CTRLSTATE_STALL;
* 3. An error was detected in either the above logic or by the class implementation * 3. An error was detected in either the above logic or by the class implementation
* logic. In either case, priv->state will be set CTRLSTATE_STALLED * logic. In either case, priv->state will be set CTRLSTATE_STALL
* to indicate this case. * to indicate this case.
* *
* NOTE: Non-standard requests are a special case. They are handled by the * NOTE: Non-standard requests are a special case. They are handled by the
@ -1922,7 +1923,7 @@ resume_packet_processing:
* logic altogether. * logic altogether.
*/ */
if (!dispatched && (priv->ctrlstate != CTRLSTATE_STALLED)) if (!dispatched && (priv->ctrlstate != CTRLSTATE_STALL))
{ {
/* The SETUP command was not dispatched to the class driver and the SETUP /* The SETUP command was not dispatched to the class driver and the SETUP
* command did not cause a stall. We will respond. First, restrict the * command did not cause a stall. We will respond. First, restrict the
@ -2077,7 +2078,7 @@ static void pic32mx_ep0incomplete(struct pic32mx_usbdev_s *priv)
else else
{ {
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDSTATE), priv->ctrlstate); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDSTATE), priv->ctrlstate);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
} }
@ -2091,7 +2092,9 @@ static void pic32mx_ep0outcomplete(struct pic32mx_usbdev_s *priv)
switch (priv->ctrlstate) switch (priv->ctrlstate)
{ {
case CTRLSTATE_RDREQUEST: /* Read request in progress */ /* Read request in progress */
case CTRLSTATE_RDREQUEST:
/* Process the next read request for EP0 */ /* Process the next read request for EP0 */
@ -2107,7 +2110,9 @@ static void pic32mx_ep0outcomplete(struct pic32mx_usbdev_s *priv)
} }
break; break;
case CTRLSTATE_WAITSETUP: /* No transfer in progress, waiting for SETUP */ /* No transfer in progress, waiting for SETUP */
case CTRLSTATE_WAITSETUP:
{ {
/* In this case the last OUT transaction must have been a status /* In this case the last OUT transaction must have been a status
* stage of a CTRLSTATE_WRREQUEST: Prepare EP0 OUT for the next SETUP * stage of a CTRLSTATE_WRREQUEST: Prepare EP0 OUT for the next SETUP
@ -2118,14 +2123,14 @@ static void pic32mx_ep0outcomplete(struct pic32mx_usbdev_s *priv)
} }
break; break;
default: /* Unexpected state OR host aborted the OUT transfer before it completed,
{ * STALL the endpoint in either case
/* Unexpected state OR host aborted the OUT transfer before it
* completed, STALL the endpoint in either case
*/ */
default:
{
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDSTATE), priv->ctrlstate); usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_INVALIDSTATE), priv->ctrlstate);
priv->ctrlstate = CTRLSTATE_STALLED; priv->ctrlstate = CTRLSTATE_STALL;
} }
break; break;
} }
@ -2204,9 +2209,9 @@ static void pic32mx_ep0transfer(struct pic32mx_usbdev_s *priv, uint16_t status)
pic32mx_ep0incomplete(priv); pic32mx_ep0incomplete(priv);
} }
/* Check for a stall */ /* Check for a request to stall EP0 */
if (priv->ctrlstate == CTRLSTATE_STALLED) if (priv->ctrlstate == CTRLSTATE_STALL)
{ {
/* Stall EP0 */ /* Stall EP0 */
@ -3181,6 +3186,10 @@ static int pic32mx_epstall(struct usbdev_ep_s *ep, bool resume)
{ {
ret = pic32mx_epbdtstall(ep, privep->bdtout, resume, false); ret = pic32mx_epbdtstall(ep, privep->bdtout, resume, false);
} }
/* Set the EP0 control state appropriately */
privep->dev->ctrlstate = resume ? CTRLSTATE_WAITSETUP : CTRLSTATE_STALLED;
} }
/* Otherwise, select the BDT for the endpoint direction */ /* Otherwise, select the BDT for the endpoint direction */
@ -3389,6 +3398,12 @@ static int pic32mx_selfpowered(struct usbdev_s *dev, bool selfpowered)
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: pic32mx_reset * Name: pic32mx_reset
*
* Description:
* Reset the software and hardware states. If the USB controller has been
* attached to a host, then connect to the bus as well. At the end of
* this reset, the hardware should be in the full up, ready-to-run state.
*
****************************************************************************/ ****************************************************************************/
static void pic32mx_reset(struct pic32mx_usbdev_s *priv) static void pic32mx_reset(struct pic32mx_usbdev_s *priv)
@ -3400,6 +3415,19 @@ static void pic32mx_reset(struct pic32mx_usbdev_s *priv)
/* Re-configure the USB controller in its initial, unconnected state */ /* Re-configure the USB controller in its initial, unconnected state */
pic32mx_hwreset(priv); pic32mx_hwreset(priv);
/* pic32mx_attach() was called, then the attach flag will be set and we
* should also attach to the USB bus.
*/
if (priv->attached)
{
/* usbdev_attach() has already been called.. attach to the bus
* now
*/
pic32mx_attach(priv);
}
} }
/**************************************************************************** /****************************************************************************
@ -3602,6 +3630,10 @@ static void pic32mx_swreset(struct pic32mx_usbdev_s *priv)
/**************************************************************************** /****************************************************************************
* Name: pic32mx_hwreset * Name: pic32mx_hwreset
*
* Description:
* Reset the hardware and leave it in a known, unready state.
*
****************************************************************************/ ****************************************************************************/
static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv) static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
@ -3717,9 +3749,10 @@ static void pic32mx_hwshutdown(struct pic32mx_usbdev_s *priv)
{ {
uint16_t regval; uint16_t regval;
/* Put the hardware in its normal, unconnected state */ /* Put the hardware and driver in its initial, unconnected state */
pic32mx_reset(priv); pic32mx_swreset(priv);
pic32mx_hwreset(priv);
priv->usbdev.speed = USB_SPEED_UNKNOWN; priv->usbdev.speed = USB_SPEED_UNKNOWN;
/* Disable all interrupts and force the USB controller into reset */ /* Disable all interrupts and force the USB controller into reset */
@ -3884,24 +3917,13 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
else else
{ {
/* Setup the USB controller in it initial unconnected state */ /* Setup the USB controller in it initial ready-to-run state (might
* be connected or unconnected, depending on usbdev_attach() has
* been called).
*/
DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED); DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED);
pic32mx_reset(priv); pic32mx_reset(priv);
/* We do not know the order in which the user will call APIs. If
* pic32mx_attach() were called before we got here, the the attach
* flag will be set and we should also attach to the USB bus.
*/
if (priv->attached)
{
/* usbdev_attach() has already been called.. attach to the bus
* now
*/
pic32mx_attach(priv);
}
} }
return ret; return ret;
} }
@ -3938,11 +3960,13 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
#endif #endif
/* Reset the hardware and cancel all requests. All requests must be /* Reset the hardware and cancel all requests. All requests must be
* canceled while the class driver is still bound. * canceled while the class driver is still bound. This will put
* the hardware back into its initial, unconnected state.
*/ */
flags = irqsave(); flags = irqsave();
pic32mx_reset(priv); pic32mx_swreset(priv);
pic32mx_hwreset(priv);
/* Unbind the class driver */ /* Unbind the class driver */
@ -3953,7 +3977,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
up_disable_irq(PIC32MX_IRQSRC_USB); up_disable_irq(PIC32MX_IRQSRC_USB);
/* Put the hardware in an inactive state. Then bring the hardware back up /* Put the hardware in an inactive state. Then bring the hardware back up
* in the reset state (this is probably not necessary, the pic32mx_reset() * in the reset state (this is probably not necessary, the pic32mx_hwreset()
* call above was probably sufficient). * call above was probably sufficient).
*/ */