Need to send ZLP at end of no-data setup
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2206 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
026fdc7e41
commit
ff92a5567e
@ -269,7 +269,7 @@ enum stm32_devstate_e
|
||||
DEVSTATE_INIT,
|
||||
DEVSTATE_RDREQUEST, /* Read request in progress */
|
||||
DEVSTATE_WRREQUEST, /* Write request in progress */
|
||||
DEVSTATE_IDLE, /* No transfer in progress */
|
||||
DEVSTATE_IDLE, /* No request in progress */
|
||||
DEVSTATE_STALLED /* We are stalled */
|
||||
};
|
||||
|
||||
@ -417,7 +417,8 @@ static void stm32_esofpoll(struct stm32_usbdev_s *priv) ;
|
||||
|
||||
/* Request Helpers **********************************************************/
|
||||
|
||||
static void stm32_copytopma(const ubyte *buffer, uint16 pma, uint16 nbytes);
|
||||
static void stm32_copytopma(const ubyte *buffer, uint16 pma,
|
||||
uint16 nbytes);
|
||||
static inline void
|
||||
stm32_copyfrompma(ubyte *buffer, uint16 pma, uint16 nbytes);
|
||||
static struct stm32_req_s *
|
||||
@ -428,17 +429,20 @@ static inline void
|
||||
stm32_abortrequest(struct stm32_ep_s *privep,
|
||||
struct stm32_req_s *privreq, sint16 result);
|
||||
static void stm32_reqcomplete(struct stm32_ep_s *privep, sint16 result);
|
||||
static void stm32_epwrite(struct stm32_usbdev_s *buf, struct stm32_ep_s *privep,
|
||||
const ubyte *data, uint32 nbytes);
|
||||
static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep);
|
||||
static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep);
|
||||
static void stm32_epwrite(struct stm32_usbdev_s *buf,
|
||||
struct stm32_ep_s *privep, const ubyte *data, uint32 nbytes);
|
||||
static int stm32_wrrequest(struct stm32_usbdev_s *priv,
|
||||
struct stm32_ep_s *privep);
|
||||
static int stm32_rdrequest(struct stm32_usbdev_s *priv,
|
||||
struct stm32_ep_s *privep);
|
||||
|
||||
/* Interrupt level processing ***********************************************/
|
||||
|
||||
static int stm32_dispatchrequest(struct stm32_usbdev_s *priv);
|
||||
static void stm32_ep0post(struct stm32_usbdev_s *priv);
|
||||
static void stm32_ep0setup(struct stm32_usbdev_s *priv);
|
||||
static void stm32_ep0out(struct stm32_usbdev_s *priv, struct stm32_ep_s *privep);
|
||||
static void stm32_ep0out(struct stm32_usbdev_s *priv,
|
||||
struct stm32_ep_s *privep);
|
||||
static void stm32_ep0in(struct stm32_usbdev_s *priv);
|
||||
static void stm32_setdevaddr(struct stm32_usbdev_s *priv, ubyte value);
|
||||
static void stm32_lptransfer(struct stm32_usbdev_s *priv);
|
||||
@ -1185,7 +1189,7 @@ static void stm32_epwrite(struct stm32_usbdev_s *priv,
|
||||
ubyte epno = USB_EPNO(privep->ep.eplog);
|
||||
usbtrace(TRACE_WRITE(epno), nbytes);
|
||||
|
||||
/* Check for NULL packet */
|
||||
/* Check for a zero-length packet */
|
||||
|
||||
if (nbytes > 0)
|
||||
{
|
||||
@ -1206,7 +1210,6 @@ static void stm32_epwrite(struct stm32_usbdev_s *priv,
|
||||
*/
|
||||
|
||||
privep->txbusy = 1;
|
||||
priv->devstate = DEVSTATE_WRREQUEST;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1267,8 +1270,8 @@ static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
nbytes = privep->ep.maxpacket;
|
||||
|
||||
/* Handle the case where this packet is exactly the
|
||||
* maxpacketsize. Do we need to send a NULL packet
|
||||
* in this case?
|
||||
* maxpacketsize. Do we need to send a zero-length packet
|
||||
* in this case?
|
||||
*/
|
||||
|
||||
if (bytesleft == privep->ep.maxpacket &&
|
||||
@ -1283,6 +1286,7 @@ 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 */
|
||||
|
||||
@ -1298,6 +1302,7 @@ static int stm32_wrrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
|
||||
privep->txnullpkt = 0;
|
||||
stm32_reqcomplete(privep, OK);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1359,6 +1364,7 @@ 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 then we are finished with the transfer */
|
||||
|
||||
@ -1366,9 +1372,9 @@ static int stm32_rdrequest(struct stm32_usbdev_s *priv, struct stm32_ep_s *prive
|
||||
if (privreq->req.xfrd >= privreq->req.len)
|
||||
{
|
||||
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
priv->rxstatus = USB_EPR_STATRX_VALID; /* Re-enable for next data reception */
|
||||
stm32_reqcomplete(privep, OK);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1425,6 +1431,7 @@ static void stm32_ep0post(struct stm32_usbdev_s *priv)
|
||||
stm32_seteprxcount(EP0, STM32_EP0MAXPACKET);
|
||||
if (priv->devstate == DEVSTATE_STALLED)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->devstate);
|
||||
priv->rxstatus = USB_EPR_STATRX_STALL;
|
||||
priv->txstatus = USB_EPR_STATTX_STALL;
|
||||
}
|
||||
@ -1445,7 +1452,7 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
union wb_u response;
|
||||
boolean handled = FALSE;
|
||||
ubyte epno;
|
||||
int nbytes = 0;
|
||||
int nbytes = 0; /* Assume zero-length packet */
|
||||
int ret;
|
||||
|
||||
/* Terminate any pending requests */
|
||||
@ -1719,8 +1726,9 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
}
|
||||
|
||||
/* Note that setting of the device address will be deferred until the
|
||||
* EP0IN complete interrupt
|
||||
/* Note that setting of the device address will be deferred. A zero-length
|
||||
* packet will be sent and the device address will be set when the zero-
|
||||
* length packet transfer completes.
|
||||
*/
|
||||
}
|
||||
break;
|
||||
@ -1888,38 +1896,21 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
* to indicate this case.
|
||||
*/
|
||||
|
||||
if (priv->devstate == DEVSTATE_STALLED)
|
||||
if (priv->devstate != DEVSTATE_STALLED && !handled)
|
||||
{
|
||||
usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EP0SETUPSTALLED), priv->devstate);
|
||||
stm32_epstall(priv->usbdev.ep0, FALSE);
|
||||
stm32_epstall(priv->usbdev.ep0, FALSE);
|
||||
}
|
||||
else if ((priv->ctrl.type & USB_REQ_DIR_IN) != 0)
|
||||
{
|
||||
/* Check if the class driver already handled the IN response */
|
||||
/* We will response. First, restrict the data length to the length
|
||||
* requested in the setup packet
|
||||
*/
|
||||
|
||||
if (!handled)
|
||||
if (nbytes > len.w)
|
||||
{
|
||||
/* NO.. Then we will respond. First, restrict the data length to
|
||||
* the length requested in the setup packet
|
||||
*/
|
||||
|
||||
if (nbytes > len.w)
|
||||
{
|
||||
nbytes = len.w;
|
||||
}
|
||||
|
||||
/* Send the response (might be a zero-length packet) */
|
||||
|
||||
stm32_epwrite(priv, ep0, response.b, nbytes);
|
||||
nbytes = len.w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setup for next data reception */
|
||||
|
||||
/* Send the response (might be a zero-length packet) */
|
||||
|
||||
stm32_epwrite(priv, ep0, response.b, nbytes);
|
||||
priv->devstate = DEVSTATE_IDLE;
|
||||
priv->rxstatus = USB_EPR_STATRX_VALID;
|
||||
}
|
||||
|
||||
stm32_ep0post(priv);
|
||||
@ -1931,14 +1922,23 @@ static void stm32_ep0setup(struct stm32_usbdev_s *priv)
|
||||
|
||||
static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
{
|
||||
uint32 devstate = priv->devstate;
|
||||
/* Are we processing the completion of one packet of an outgoing request
|
||||
* from the class driver?
|
||||
*/
|
||||
|
||||
if (priv->devstate == DEVSTATE_WRREQUEST)
|
||||
{
|
||||
stm32_wrrequest(priv, &priv->eplist[EP0]);
|
||||
devstate = priv->devstate;
|
||||
}
|
||||
else if (devstate == DEVSTATE_IDLE)
|
||||
|
||||
/* No.. Are we processing the completion of a status response? */
|
||||
|
||||
else if (priv->devstate == DEVSTATE_IDLE)
|
||||
{
|
||||
/* Look at the saved SETUP command. Was it a SET ADDRESS request?
|
||||
* If so, then now is the time to set the address.
|
||||
*/
|
||||
|
||||
if (priv->ctrl.req == USB_REQ_SETADDRESS &&
|
||||
(priv->ctrl.type & REQRECIPIENT_MASK) == (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_DEVICE))
|
||||
{
|
||||
@ -1946,15 +1946,12 @@ static void stm32_ep0in(struct stm32_usbdev_s *priv)
|
||||
value.w = GETUINT16(priv->ctrl.value);
|
||||
stm32_setdevaddr(priv, value.b[LSB]);
|
||||
}
|
||||
|
||||
devstate = DEVSTATE_STALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
devstate = DEVSTATE_STALLED;
|
||||
priv->devstate = DEVSTATE_STALLED;
|
||||
}
|
||||
|
||||
priv->devstate = devstate;
|
||||
stm32_ep0post(priv);
|
||||
}
|
||||
|
||||
@ -2972,7 +2969,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, boolean resume)
|
||||
/* Resuming a stalled endpoint */
|
||||
|
||||
usbtrace(TRACE_EPRESUME, epno);
|
||||
privep->stalled = 0;
|
||||
privep->stalled = FALSE;
|
||||
|
||||
if (USB_ISEPIN(ep->eplog))
|
||||
{
|
||||
@ -3011,7 +3008,7 @@ static int stm32_epstall(struct usbdev_ep_s *ep, boolean resume)
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_EPSTALL, epno);
|
||||
privep->stalled = 1;
|
||||
privep->stalled = TRUE;
|
||||
|
||||
if (USB_ISEPIN(ep->eplog))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user