Fix some errors in how STM32 USB F3 state was being handled. Fix is correct, but does not change behavior
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5639 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
4f1f8f6b43
commit
e9d4532625
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32/stm32_usbdev.c
|
||||
*
|
||||
* Copyright (C) 2009-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2009-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.orgr>
|
||||
*
|
||||
* References:
|
||||
@ -266,12 +266,12 @@
|
||||
|
||||
/* The various states of a control pipe */
|
||||
|
||||
enum stm32_devstate_e
|
||||
enum stm32_ep0state_e
|
||||
{
|
||||
DEVSTATE_IDLE = 0, /* No request in progress */
|
||||
DEVSTATE_RDREQUEST, /* Read request in progress */
|
||||
DEVSTATE_WRREQUEST, /* Write request in progress */
|
||||
DEVSTATE_STALLED /* We are stalled */
|
||||
EP0STATE_IDLE = 0, /* No request in progress */
|
||||
EP0STATE_RDREQUEST, /* Read request in progress */
|
||||
EP0STATE_WRREQUEST, /* Write request in progress */
|
||||
EP0STATE_STALLED /* We are stalled */
|
||||
};
|
||||
|
||||
/* Resume states */
|
||||
@ -336,7 +336,7 @@ struct stm32_usbdev_s
|
||||
/* STM32-specific fields */
|
||||
|
||||
struct usb_ctrlreq_s ctrl; /* Last EP0 request */
|
||||
uint8_t devstate; /* Driver state (see enum stm32_devstate_e) */
|
||||
uint8_t ep0state; /* State of EP0 (see enum stm32_ep0state_e) */
|
||||
uint8_t rsmstate; /* Resume state (see enum stm32_rsmstate_e) */
|
||||
uint8_t nesofs; /* ESOF counter (for resume support) */
|
||||
uint8_t rxpending:1; /* 1: OUT data in PMA, but no read requests */
|
||||
@ -1158,7 +1158,7 @@ static void stm32_reqcomplete(struct stm32_ep_s *privep, int16_t result)
|
||||
bool stalled = privep->stalled;
|
||||
if (USB_EPNO(privep->ep.eplog) == EP0)
|
||||
{
|
||||
privep->stalled = (privep->dev->devstate == DEVSTATE_STALLED);
|
||||
privep->stalled = (privep->dev->ep0state == EP0STATE_STALLED);
|
||||
}
|
||||
|
||||
/* Save the result in the request structure */
|
||||
@ -1238,8 +1238,7 @@ static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
*/
|
||||
|
||||
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPINQEMPTY), 0);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
return OK;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
epno = USB_EPNO(privep->ep.eplog);
|
||||
@ -1283,7 +1282,6 @@ static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
|
||||
buf = privreq->req.buf + privreq->req.xfrd;
|
||||
stm32_epwrite(priv, privep, buf, nbytes);
|
||||
priv->devstate = DEVSTATE_WRREQUEST;
|
||||
|
||||
/* Update for the next data IN interrupt */
|
||||
|
||||
@ -1291,15 +1289,16 @@ static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
bytesleft = privreq->req.len - privreq->req.xfrd;
|
||||
|
||||
/* If all of the bytes were sent (including any final null packet)
|
||||
* then we are finished with the transfer
|
||||
* then we are finished with the request buffer).
|
||||
*/
|
||||
|
||||
if (bytesleft == 0 && !privep->txnullpkt)
|
||||
{
|
||||
/* Return the write request to the class driver */
|
||||
|
||||
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
|
||||
privep->txnullpkt = 0;
|
||||
stm32_reqcomplete(privep, OK);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1330,7 +1329,7 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
*/
|
||||
|
||||
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPOUTQEMPTY), epno);
|
||||
return OK;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ullvdbg("EP%d: len=%d xfrd=%d\n", epno, privreq->req.len, privreq->req.xfrd);
|
||||
@ -1359,22 +1358,18 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
/* Receive the next packet */
|
||||
|
||||
stm32_copyfrompma(dest, src, readlen);
|
||||
priv->devstate = DEVSTATE_RDREQUEST;
|
||||
|
||||
/* If the receive buffer is full or this is a partial packet,
|
||||
* then we are finished with the transfer
|
||||
* then we are finished with the request buffer).
|
||||
*/
|
||||
|
||||
privreq->req.xfrd += readlen;
|
||||
if (pmalen < privep->ep.maxpacket || privreq->req.xfrd >= privreq->req.len)
|
||||
{
|
||||
/* Complete the transfer and mark the state IDLE. The endpoint
|
||||
* RX will be marked valid when the data phase completes.
|
||||
*/
|
||||
/* Return the read request to the class driver. */
|
||||
|
||||
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
||||
stm32_reqcomplete(privep, OK);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1416,7 +1411,7 @@ static void stm32_dispatchrequest(struct stm32_usbdev_s *priv)
|
||||
/* Stall on failure */
|
||||
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_DISPATCHSTALL), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1452,7 +1447,7 @@ static void stm32_epdone(struct stm32_usbdev_s *priv, uint8_t epno)
|
||||
{
|
||||
/* Read host data into the current read request */
|
||||
|
||||
stm32_rdrequest(priv, privep);
|
||||
(void)stm32_rdrequest(priv, privep);
|
||||
|
||||
/* "After the received data is processed, the application software
|
||||
* should set the STAT_RX bits to '11' (Valid) in the USB_EPnR,
|
||||
@ -1583,7 +1578,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
ullvdbg("SETUP: type=%02x req=%02x value=%04x index=%04x len=%04x\n",
|
||||
priv->ctrl.type, priv->ctrl.req, value.w, index.w, len.w);
|
||||
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
priv->ep0state = EP0STATE_IDLE;
|
||||
|
||||
/* Dispatch any non-standard requests */
|
||||
|
||||
@ -1616,7 +1611,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
index.b[MSB] != 0 || value.w != 0)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1629,7 +1624,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
if (epno >= STM32_NENDPOINTS)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADEPGETSTATUS), epno);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1679,7 +1674,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADDEVGETSTATUS), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1695,7 +1690,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
default:
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSTATUS), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1736,7 +1731,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADCLEARFEATURE), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1780,7 +1775,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETFEATURE), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1799,7 +1794,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
index.w != 0 || len.w != 0 || value.w > 127)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETADDRESS), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
|
||||
/* Note that setting of the device address will be deferred. A zero-length
|
||||
@ -1834,7 +1829,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETSETDESC), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1859,7 +1854,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADGETCONFIG), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1884,7 +1879,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_BADSETCONFIG), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1926,7 +1921,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
default:
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_INVALIDCTRLREQ), priv->ctrl.req);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1938,9 +1933,9 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
* must be sent (may be a zero length packet).
|
||||
* 2. The request was successfully handled by the class implementation. In
|
||||
* case, the EP0 IN response has already been queued and the local variable
|
||||
* 'handled' will be set to true and devstate != DEVSTATE_STALLED;
|
||||
* 'handled' will be set to true and ep0state != EP0STATE_STALLED;
|
||||
* 3. An error was detected in either the above logic or by the class implementation
|
||||
* logic. In either case, priv->state will be set DEVSTATE_STALLED
|
||||
* logic. In either case, priv->state will be set EP0STATE_STALLED
|
||||
* to indicate this case.
|
||||
*
|
||||
* NOTE: Non-standard requests are a special case. They are handled by the
|
||||
@ -1948,7 +1943,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
* logic altogether.
|
||||
*/
|
||||
|
||||
if (priv->devstate != DEVSTATE_STALLED && !handled)
|
||||
if (priv->ep0state != EP0STATE_STALLED && !handled)
|
||||
{
|
||||
/* We will response. First, restrict the data length to the length
|
||||
* requested in the setup packet
|
||||
@ -1962,7 +1957,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
/* Send the response (might be a zero-length packet) */
|
||||
|
||||
stm32_epwrite(priv, ep0, response.b, nbytes);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
priv->ep0state = EP0STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1972,6 +1967,8 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
|
||||
static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* There is no longer anything in the EP0 TX packet memory */
|
||||
|
||||
priv->eplist[EP0].txbusy = false;
|
||||
@ -1980,14 +1977,15 @@ static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
* from the class driver?
|
||||
*/
|
||||
|
||||
if (priv->devstate == DEVSTATE_WRREQUEST)
|
||||
if (priv->ep0state == EP0STATE_WRREQUEST)
|
||||
{
|
||||
stm32_wrrequest(priv, &priv->eplist[EP0]);
|
||||
ret = stm32_wrrequest(priv, &priv->eplist[EP0]);
|
||||
priv->ep0state = ((ret == OK) ? EP0STATE_WRREQUEST : EP0STATE_IDLE);
|
||||
}
|
||||
|
||||
/* No.. Are we processing the completion of a status response? */
|
||||
|
||||
else if (priv->devstate == DEVSTATE_IDLE)
|
||||
else if (priv->ep0state == EP0STATE_IDLE)
|
||||
{
|
||||
/* Look at the saved SETUP command. Was it a SET ADDRESS request?
|
||||
* If so, then now is the time to set the address.
|
||||
@ -2003,7 +2001,7 @@ static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2013,12 +2011,15 @@ static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
|
||||
static void stm32_ep0out(struct stm32_usbdev_s *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct stm32_ep_s *privep = &priv->eplist[EP0];
|
||||
switch (priv->devstate)
|
||||
switch (priv->ep0state)
|
||||
{
|
||||
case DEVSTATE_RDREQUEST: /* Write request in progress */
|
||||
case DEVSTATE_IDLE: /* No transfer in progress */
|
||||
stm32_rdrequest(priv, privep);
|
||||
case EP0STATE_RDREQUEST: /* Write request in progress */
|
||||
case EP0STATE_IDLE: /* No transfer in progress */
|
||||
ret = stm32_rdrequest(priv, privep);
|
||||
priv->ep0state = ((ret == OK) ? EP0STATE_RDREQUEST : EP0STATE_IDLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2026,7 +2027,7 @@ static void stm32_ep0out(struct stm32_usbdev_s *priv)
|
||||
* completed, STALL the endpoint in either case
|
||||
*/
|
||||
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2119,7 +2120,7 @@ static inline void stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr)
|
||||
/* Now figure out the new RX/TX status. Here are all possible
|
||||
* consequences of the above EP0 operations:
|
||||
*
|
||||
* rxstatus txstatus devstate MEANING
|
||||
* rxstatus txstatus ep0state MEANING
|
||||
* -------- -------- --------- ---------------------------------
|
||||
* NAK NAK IDLE Nothing happened
|
||||
* NAK VALID IDLE EP0 response sent from USBDEV driver
|
||||
@ -2129,9 +2130,9 @@ static inline void stm32_ep0done(struct stm32_usbdev_s *priv, uint16_t istr)
|
||||
* First handle the STALL condition:
|
||||
*/
|
||||
|
||||
if (priv->devstate == DEVSTATE_STALLED)
|
||||
if (priv->ep0state == EP0STATE_STALLED)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->devstate);
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
|
||||
priv->rxstatus = USB_EPR_STATRX_STALL;
|
||||
priv->txstatus = USB_EPR_STATTX_STALL;
|
||||
}
|
||||
@ -2859,7 +2860,7 @@ static int stm32_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
||||
if (!privep->txbusy)
|
||||
{
|
||||
priv->txstatus = USB_EPR_STATTX_NAK;
|
||||
ret = stm32_wrrequest(priv, privep);
|
||||
ret = stm32_wrrequest(priv, privep);
|
||||
|
||||
/* Set the new TX status */
|
||||
|
||||
@ -2971,7 +2972,12 @@ static int stm32_epstall(struct usbdev_ep_s *ep, bool resume)
|
||||
if (status == 0)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPDISABLED), 0);
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
|
||||
if (epno == 0)
|
||||
{
|
||||
priv->ep0state = EP0STATE_STALLED;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -3272,7 +3278,7 @@ static void stm32_reset(struct stm32_usbdev_s *priv)
|
||||
|
||||
/* Reset the device state structure */
|
||||
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
priv->ep0state = EP0STATE_IDLE;
|
||||
priv->rsmstate = RSMSTATE_IDLE;
|
||||
priv->rxpending = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user