diff options
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_usbdev.c | 112 |
1 files changed, 59 insertions, 53 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.c b/nuttx/arch/arm/src/stm32/stm32_usbdev.c index 2dc8c1edf..6036eb3d5 100644 --- a/nuttx/arch/arm/src/stm32/stm32_usbdev.c +++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.c @@ -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; |