Newer
Older
ubyte *buf;
int nbytes;
int bytesleft;
/* Check the request from the head of the endpoint request queue */
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPINQEMPTY), 0);
uvdbg("len=%d xfrd=%d nullpkt=%d\n",
privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
/* Ignore any attempt to send a zero length packet on anything but EP0IN */
if (privreq->req.len == 0)
{
if (privep->epphy == LPC214X_EP0_IN)
{
lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPINNULLPACKET), 0);
}
/* In any event, the request is complete */
lpc214x_reqcomplete(privep, OK);
return OK;
}
/* Otherwise send the data in the packet (in the DMA on case, we
* may be resuming transfer already in progress.
*/
#warning REVISIT... Unless the EP supports double buffering, only one packet may be sent
/* Get the number of bytes left to be sent in the packet */
bytesleft = privreq->req.len - privreq->req.xfrd;
/* Send the next packet if (1) there are more bytes to be sent, or
* (2) the last packet sent was exactly maxpacketsize (bytesleft == 0)
*/
usbtrace(TRACE_WRITE(privep->epphy), privreq->req.xfrd);
if (bytesleft > 0 || privep->txnullpkt)
{
/* Try to send maxpacketsize -- unless we don't have that many
* bytes to send.
*/
if (bytesleft > privep->ep.maxpacket)
{
nbytes = privep->ep.maxpacket;
privep->txnullpkt = 0;
}
else
privep->txnullpkt = (bytesleft == privep->ep.maxpacket);
}
/* Send the largest number of bytes that we can in this packet */
buf = privreq->req.buf + privreq->req.xfrd;
lpc214x_epwrite(privep->epphy, buf, nbytes);
/* Update for the next time through the loop */
privreq->req.xfrd += nbytes;
}
/* If all of the bytes were sent (including any final null packet)
* then we are finished with the transfer
if (bytesleft <= 0 || !privep->txnullpkt)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
lpc214x_reqcomplete(privep, OK);
return OK;
}
}
return OK; /* Won't get here */
}
/*******************************************************************************
* Name: lpc214x_rdrequest
*
* Description:
* Receive to the next queued read request
*
*******************************************************************************/
static int lpc214x_rdrequest(struct lpc214x_ep_s *privep)
{
struct lpc214x_req_s *privreq;
ubyte *buf;
int nbytesread;
/* Check the request from the head of the endpoint request queue */
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPOUTQEMPTY), 0);
uvdbg("len=%d xfrd=%d nullpkt=%d\n",
privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
/* Ignore any attempt to receive a zero length packet */
if (privreq->req.len == 0)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPOUTNULLPACKET), 0);
lpc214x_reqcomplete(privep, OK);
return OK;
}
#warning REVISIT... Unless the EP supports double buffering, only one packet may be received
usbtrace(TRACE_READ(privep->epphy), privreq->req.xfrd);
for (;;)
{
/* Receive the next packet if (1) there are more bytes to be receive, or
* (2) the last packet was exactly maxpacketsize.
*/
buf = privreq->req.buf + privreq->req.xfrd;
nbytesread = lpc214x_epread(privep->epphy, buf, privep->ep.maxpacket);
if (nbytesread < 0)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPREAD), nbytesread);
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
return ERROR;
}
/* If the receive buffer is full or if the last packet was not full
* then we are finished with the transfer.
*/
privreq->req.xfrd += nbytesread;
if (privreq->req.len < privreq->req.xfrd || nbytesread < privep->ep.maxpacket)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
lpc214x_reqcomplete(privep, OK);
return OK;
}
}
return OK; /* Won't get here */
}
/*******************************************************************************
* Name: lpc214x_cancelrequests
*
* Description:
* Cancel all pending requests for an endpoint
*
*******************************************************************************/
static void lpc214x_cancelrequests(struct lpc214x_ep_s *privep)
{
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
lpc214x_reqcomplete(privep, -ESHUTDOWN);
}
}
/*******************************************************************************
* Name: lpc214x_eprealize
*
* Description:
* Enable or disable an endpoint
*
*******************************************************************************/
static void lpc214x_eprealize(struct lpc214x_ep_s *privep, boolean prio, uint32 packetsize)
{
struct lpc214x_usbdev_s *priv = privep->dev;
uint32 mask;
uint32 reg;
/* Initialize endpoint software priority */
mask = 1 << privep->epphy;
if (prio)
{
priv->softprio = priv->softprio | mask;
}
else
{
priv->softprio = priv->softprio & ~mask;
}
/* Clear realize interrupt bit */
lpc214x_putreg(USBDEV_DEVINT_EPRLZED, LPC214X_USBDEV_DEVINTCLR);
/* Realize the endpoint */
reg = lpc214x_getreg(LPC214X_USBDEV_REEP);
reg |= (1 << privep->epphy);
lpc214x_putreg(reg, LPC214X_USBDEV_REEP);
/* Set endpoint maximum packet size */
lpc214x_putreg(privep->epphy, LPC214X_USBDEV_EPIND);
lpc214x_putreg(packetsize, LPC214X_USBDEV_MAXPSIZE);
/* Wait for Realize complete */
while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_EPRLZED) == 0);
/* Clear realize interrupt bit */
lpc214x_putreg(USBDEV_DEVINT_EPRLZED,LPC214X_USBDEV_DEVINTCLR);
}
/*******************************************************************************
* Name: lpc214x_epclrinterrupt
*
* Description:
* Clear the EP interrupt flag and return the current EP status
*
*******************************************************************************/
static ubyte lpc214x_epclrinterrupt(ubyte epphy)
{
/* Clear the endpoint interrupt */
lpc214x_putreg(1 << epphy, LPC214X_USBDEV_EPINTCLR);
/* Wait for data in the command data register */
while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
/* Return the value of the command data register */
return lpc214x_getreg(LPC214X_USBDEV_CMDDATA);
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
}
/*******************************************************************************
* Name: lpc214x_ep0configure
*
* Description:
* Configure endpoint 0
*
*******************************************************************************/
static inline void lpc214x_ep0configure(struct lpc214x_usbdev_s *priv)
{
uint32 inten;
/* EndPoint 0 initialization */
lpc214x_eprealize(&priv->eplist[LPC214X_CTRLEP_OUT], 0, CONFIG_USBDEV_EP0_MAXSIZE);
lpc214x_eprealize(&priv->eplist[LPC214X_CTRLEP_IN], 1, CONFIG_USBDEV_EP0_MAXSIZE);
/* Enable EP0 interrupts (not DMA) */
inten = lpc214x_getreg(LPC214X_USBDEV_EPINTEN);
inten |= 3; /* EP0 Rx and Tx */
lpc214x_putreg(inten, LPC214X_USBDEV_EPINTEN);
}
/*******************************************************************************
* Name: lpc214x_dmareset
*
* Description: Reset USB DMA
*
*******************************************************************************/
#ifdef CONFIG_LPC214X_USBDEV_DMA
static inline void lpc214x_dmareset(uint32 enable)
{
int i;
/* Disable All DMA interrupts */
lpc214x_putreg(0, LPC214X_USBDEV_DMAINTEN);
lpc214x_putreg(0xffffffff, LPC214X_USBDEV_EPDMADIS);
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
/* DMA Request clear */
putreq32(0xffffffff, LPC214X_USBDEV_DMARCLR);
/* End of Transfer Interrupt Clear */
putreq32(0xffffffff, LPC214X_USBDEV_EOTINTCLR);
/* New DD Request Interrupt Clear */
putreq32(0xffffffff, LPC214X_USBDEV_NDDRINTCLR);
/* System Error Interrupt Clear */
putreq32(0xffffffff, LPC214X_USBDEV_SYSERRINTCLR);
/* Nullify all pointers in the UDCA */
for (i = 0; i < LPC214X_NPHYSENDPOINTS; ++i)
{
USB_UDCA[i] = NULL;
}
/* Set USB UDCA Head register */
lpc214x_putreg((uint32)USB_UDCA, LPC214X_USBDEV_UDCAH);
/* Invalidate all DMA descriptors */
for (i = 0; i < CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS; ++i)
{
memset(&USB_DDESC[i], 0, USB_DDESCSIZE);
}
/* Enable DMA interrupts */
lpc214x_putreg(enable, LPC214X_USBDEV_DMAINTEN);
}
#endif
/*******************************************************************************
* Name: lpc214x_usbreset
*
* Description:
* Reset Usb engine
*
*******************************************************************************/
static void lpc214x_usbreset(struct lpc214x_usbdev_s *priv)
{
/* Disable all endpoint interrupts */
lpc214x_putreg(0, LPC214X_USBDEV_EPINTEN);
/* Frame is Hp interrupt */
lpc214x_putreg(1, LPC214X_USBDEV_DEVINTPRI);
/* Clear all pending interrupts */
lpc214x_putreg(0xffffffff, LPC214X_USBDEV_EPINTCLR);
lpc214x_putreg(0xffffffff, LPC214X_USBDEV_DEVINTCLR);
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
/* Periperhal address is needed */
priv->paddrset = 0;
/* Endpoints not yet configured */
lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
/* EndPoint 0 initialization */
lpc214x_ep0configure(priv);
#ifdef CONFIG_LPC214X_USBDEV_DMA
/* Enable End_of_Transfer_Interrupt and System_Error_Interrupt USB DMA
* interrupts
*/
lpc214x_dmareset(CONFIG_LPC214X_USBDEV_DMAINTMASK);
#endif
/* Enable Device interrupts */
lpc214x_putreg(USB_SLOW_INT|USB_DEVSTATUS_INT|USB_FAST_INT|USB_FRAME_INT|USB_ERROR_INT,
LPC214X_USBDEV_DEVINTEN);
}
/*******************************************************************************
* Name: lpc214x_dispatchrequest
*
* Description:
* Provide unhandled setup actions to the class driver. This is logically part
* of the USB interrupt handler.
*
*******************************************************************************/
static void lpc214x_dispatchrequest(struct lpc214x_usbdev_s *priv,
{
int ret;
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DISPATCH), 0);
if (priv && priv->driver)
{
/* Forward to the control request to the class driver implementation */
ret = CLASS_SETUP(priv->driver, &priv->usbdev, ctrl);
if (ret < 0)
{
/* Stall on failure */
priv->stalled = 1;
}
}
}
/*******************************************************************************
* Name: lpc214x_ep0setup
*
* Description:
* USB Ctrl EP Setup Event. This is logically part of the USB interrupt
* handler. This event occurs when a setup packet is receive on EP0 OUT.
*
*******************************************************************************/
static inline void lpc214x_ep0setup(struct lpc214x_usbdev_s *priv)
{
struct lpc214x_ep_s *ep0 = &priv->eplist[LPC214X_EP0_OUT];
struct lpc214x_req_s *privreq = lpc214x_rqpeek(ep0);
ubyte epphy;
ubyte response[2];
int ret;
/* Starting a control request? */
if (priv->usbdev.speed == USB_SPEED_UNKNOWN)
{
priv->usbdev.speed = USB_SPEED_FULL;
lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 1);
}
/* Terminate any pending requests */
{
sint16 result = OK;
if (privreq->req.xfrd != privreq->req.len)
{
result = -EPROTO;
}
usbtrace(TRACE_COMPLETE(ep0->epphy), privreq->req.xfrd);
lpc214x_reqcomplete(ep0, result);
}
/* Assume NOT stalled */
ep0->stalled = 0;
priv->stalled = 0;
/* Read EP0 data */
ret = lpc214x_epread(LPC214X_EP0_OUT, (ubyte*)&ctrl, USB_SIZEOF_CTRLREQ);
if (ret <= 0)
{
return;
}
/* And extract the little-endian 16-bit values to host order */
value = GETUINT16(ctrl.value);
index = GETUINT16(ctrl.index);
len = GETUINT16(ctrl.len);
uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
/* Dispatch any non-standard requests */
if ((ctrl.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD)
return;
}
/* Handle standard request. Pick off the things of interest to the
* USB device controller driver; pass what is left to the class driver
*/
{
case USB_REQ_GETSTATUS:
{
/* type: device-to-host; recipient = device, interface, endpoint
* value: 0
* index: zero interface endpoint
* len: 2; data = status
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSTATUS), 0);
if (!priv->paddrset || len != 2 ||
(ctrl.type & USB_REQ_DIR_IN) == 0 || value != 0)
{
priv->stalled = 1;
}
else
{
{
case USB_REQ_RECIPIENT_ENDPOINT:
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPGETSTATUS), 0);
if (epphy < LPC214X_NPHYSENDPOINTS)
{
if ((lpc214x_usbcmd(CMD_USB_EP_SELECT|epphy, 0) & CMD_USB_EPSELECT_ST) != 0)
{
response[0] = 1; /* Stalled */
}
else
{
response[0] = 0; /* Not stalled */
}
response[1] = 0;
lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
priv->ep0state = LPC214X_EP0SHORTWRITE;
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADEPGETSTATUS), 0);
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
priv->stalled = 1;
}
}
break;
case USB_REQ_RECIPIENT_DEVICE:
{
if (index == 0)
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DEVGETSTATUS), 0);
/* Features: Remote Wakeup=YES; selfpowered=? */
response[0] = (priv->selfpowered << USB_FEATURE_SELFPOWERED) |
(1 << USB_FEATURE_REMOTEWAKEUP);
response[1] = 0;
lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
priv->ep0state = LPC214X_EP0SHORTWRITE;
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADDEVGETSTATUS), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_RECIPIENT_INTERFACE:
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_IFGETSTATUS), 0);
response[0] = 0;
response[1] = 0;
lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
priv->ep0state = LPC214X_EP0SHORTWRITE;
}
break;
default:
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETSTATUS), 0);
priv->stalled = 1;
}
break;
}
}
}
break;
case USB_REQ_CLEARFEATURE:
{
/* type: host-to-device; recipient = device, interface or endpoint
* value: feature selector
* index: zero interface endpoint;
* len: zero, data = none
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_CLEARFEATURE), 0);
if ((ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
else if (priv->paddrset != 0 && value == USB_FEATURE_ENDPOINTHALT &&
index < LPC214X_NLOGENDPOINTS && len == 0)
priv->eplist[epphys].halted = 0;
lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
priv->ep0state = LPC214X_EP0STATUSIN;
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADCLEARFEATURE), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_SETFEATURE:
{
/* type: host-to-device; recipient = device, interface, endpoint
* value: feature selector
* index: zero interface endpoint;
* len: 0; data = none
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SETFEATURE), 0);
if (((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) &&
else if ((ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
else if (priv->paddrset != 0 && value == USB_FEATURE_ENDPOINTHALT &&
index < LPC214X_NLOGENDPOINTS && len == 0)
priv->eplist[epphys].halted = 1;
lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
priv->ep0state = LPC214X_EP0STATUSIN;
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETFEATURE), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_SETADDRESS:
{
/* type: host-to-device; recipient = device
* value: device address
* index: 0
* len: 0; data = none
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0SETUPSETADDRESS), value);
if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
/* Save the address. We cannot actually change to the next address until
* the completion of the status phase.
*/
priv->paddr = ctrl.value[0];
/* Note that if we send the SETADDRESS command twice, that will force the
* address change. Otherwise, the hardware will automatically set the
* address at the end of the status phase.
*/
lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN | priv->paddr);
/* Send a NULL packet. The status phase completes when the null packet has
* been sent successfully.
*/
lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
priv->ep0state = LPC214X_EP0SETADDRESS;
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETADDRESS), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_GETDESCRIPTOR:
/* type: device-to-host; recipient = device
* value: descriptor type and index
* index: 0 or language ID;
* len: descriptor len; data = descriptor
*/
/* type: host-to-device; recipient = device
* value: descriptor type and index
* index: 0 or language ID;
* len: descriptor len; data = descriptor
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSETDESC), 0);
if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE)
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETSETDESC), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_GETCONFIGURATION:
/* type: device-to-host; recipient = device
* value: 0;
* index: 0;
* len: 1; data = configuration value
*/
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETCONFIG), 0);
if (priv->paddrset && (ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
{
lpc214x_dispatchrequest(priv, &ctrl);
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETCONFIG), 0);
priv->stalled = 1;
}
}
break;
case USB_REQ_SETCONFIGURATION:
/* type: host-to-device; recipient = device
* value: configuration value
* index: 0;
* len: 0; data = none
*/
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SETCONFIG), 0);
if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
{
lpc214x_dispatchrequest(priv, &ctrl);
}
else
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETCONFIG), 0);
priv->stalled = 1;
}
}
break;
/* type: device-to-host; recipient = interface
* value: 0
* index: interface;
* len: 1; data = alt interface
*/
/* type: host-to-device; recipient = interface
* value: alternate setting
* index: interface;
* len: 0; data = none
*/
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSETIF), 0);
lpc214x_dispatchrequest(priv, &ctrl);
}
break;
case USB_REQ_SYNCHFRAME:
/* type: device-to-host; recipient = endpoint
* value: 0
* index: endpoint;
* len: 2; data = frame number
*/
{
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SYNCHFRAME), 0);
}
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDCTRLREQ), 0);
priv->stalled = 1;
}
break;
}
if (priv->stalled)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
lpc214x_epstall(&ep0->ep, FALSE);
lpc214x_epstall(&ep0->ep, FALSE);
}
}
/*******************************************************************************
* Name: lpc214x_ep0dataoutinterrupt
*
* Description:
* USB Ctrl EP Data OUT Event. This is logically part of the USB interrupt
* handler. Each non-isochronous OUT endpoint gives an interrupt when they
* receive a packet without error.
*
*******************************************************************************/
static inline void lpc214x_ep0dataoutinterrupt(struct lpc214x_usbdev_s *priv)
{
struct lpc214x_ep_s *ep0;
uint32 pktlen;
/* Copy new setup packet into setup buffer */
switch (priv->ep0state)
{
case LPC214X_EP0SHORTWRITE:
{
priv->ep0state = LPC214X_EP0STATUSOUT;
pktlen = lpc214x_epread(LPC214X_EP0_OUT, NULL, CONFIG_USBDEV_EP0_MAXSIZE);
if (LPC214X_READOVERRUN(pktlen))
{
lpc214x_ep0setup(priv);
}
}
break;
case LPC214X_EP0SHORTWRSENT:
{
priv->ep0state = LPC214X_EP0REQUEST;
pktlen = lpc214x_epread(LPC214X_EP0_OUT, NULL, CONFIG_USBDEV_EP0_MAXSIZE);
if (LPC214X_READOVERRUN(pktlen))
{
lpc214x_ep0setup(priv);
}
}
break;
/* Process the next request action (if any) */
lpc214x_rdrequest(&priv->eplist[LPC214X_EP0_OUT]);
}
break;
default:
priv->stalled = 1;
break;
}
if (priv->stalled)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0OUTSTALLED), priv->ep0state);
ep0 = &priv->eplist[LPC214X_EP0_OUT];
lpc214x_epstall(&ep0->ep, FALSE);
lpc214x_epstall(&ep0->ep, FALSE);
}
return;
}
/*******************************************************************************
* Name: lpc214x_ep0dataininterrupt
*
* Description:
* USB Ctrl EP Data IN Event. This is logically part of the USB interrupt
* handler. All non-isochronous IN endpoints give this interrupt when a
* packet is successfully transmitted (OR a NAK handshake is sent on the bus
* provided that the interrupt on NAK feature is enabled).
*
*******************************************************************************/
static inline void lpc214x_ep0dataininterrupt(struct lpc214x_usbdev_s *priv)
{
struct lpc214x_ep_s *ep0;
switch (priv->ep0state)
{
case LPC214X_EP0STATUSOUT:
case LPC214X_EP0STATUSIN:
priv->ep0state = LPC214X_EP0REQUEST;
break;
case LPC214X_EP0SHORTWRITE:
priv->ep0state = LPC214X_EP0SHORTWRSENT;
break;
case LPC214X_EP0SETADDRESS:
{
/* If the address was set to a non-zero value, then thiscompletes the
* default phase, and begins the address phase (still not fully configured)
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0INSETADDRESS), (uint16)priv->paddr);
lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
priv->ep0state = LPC214X_EP0REQUEST;
case LPC214X_EP0REQUEST:
{
/* Process the next request action (if any) */
lpc214x_wrrequest(&priv->eplist[LPC214X_EP0_IN]);
}
break;
default:
priv->stalled = 1;
break;
}
if (priv->stalled)
{
usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0INSTALLED), priv->ep0state);
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
ep0 = &priv->eplist[LPC214X_EP0_IN];
lpc214x_epstall(&ep0->ep, FALSE);
lpc214x_epstall(&ep0->ep, FALSE);
}
}
/*******************************************************************************
* Name: lpc214x_usbinterrupt
*
* Description:
* USB interrupt handler
*
*******************************************************************************/
static int lpc214x_usbinterrupt(int irq, FAR void *context)
{
struct lpc214x_usbdev_s *priv = &g_usbdev;
struct lpc214x_ep_s *privep ;
uint32 devintstatus; /* Sampled state of the device interrupt status register */
uint32 epintstatus; /* Sampled state of the endpoint interrupt status register */
#ifdef CONFIG_LPC214X_USBDEV_DMA
uint32 dmaintstatus; /* Sampled state of dma interrupt status register */
#endif
uint32 softprio; /* Current priority interrupt bitset */
uint32 pending; /* Pending subset of priority interrupt bitset */
ubyte epphy; /* Physical endpoint number being processed */
int i;
usbtrace(TRACE_INTENTRY(LPC214X_TRACEINTID_USB), 0);
/* Read the device interrupt status register */
devintstatus = lpc214x_getreg(LPC214X_USBDEV_DEVINTST);
#ifdef CONFIG_LPC214X_USBDEV_DMA
/* Check for low priority and high priority (non-DMA) interrupts */
if ((lpc214x_getreg(LPC214X_USBDEV_INTST) & (USBDEV_INTST_REQLP|USBDEV_INTST_REQHP)) != 0)
{
#endif
#ifdef CONFIG_LPC214X_USBDEV_EPFAST_INTERRUPT
/* Fast EP interrupt */
if ((devintstatus & USBDEV_DEVINT_EPFAST) != 0)
{
/* Clear Fast EP interrupt */
lpc214x_putreg(USBDEV_DEVINT_EPFAST, LPC214X_USBDEV_DEVINTCLR);
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPFAST), 0);
/* Do what? */
}
#endif
#if CONFIG_DEBUG
/* USB engine error interrupt */
if ((devintstatus & USBDEV_DEVINT_EPRINT))
{
ubyte errcode;
/* Clear the error interrupt */
lpc214x_putreg(USBDEV_DEVINT_EPRINT, LPC214X_USBDEV_DEVINTCLR);
/* And show what error occurred */
errcode = (ubyte)lpc214x_usbcmd(CMD_USB_DEV_READERRORSTATUS, 0) & 0x0f;
usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPRINT), (uint16)errcode);
}
#endif
#ifdef CONFIG_LPC214X_USBDEV_FRAME_INTERRUPT
/* Frame interrupt */
if ((devintstatus & USBDEV_DEVINT_FRAME) != 0)
{
/* Clear the frame interrupt */
lpc214x_putreg(USBDEV_DEVINT_FRAME, LPC214X_USBDEV_DEVINTCLR);