Suga koubou / Mbed 2 deprecated USB_CDC_MSD_Hello

Dependencies:   ChaNFSSD mbed ChaNFS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBBusInterface_LPC11U.cpp Source File

USBBusInterface_LPC11U.cpp

00001 // USBBusInterface_LPC11U.c
00002 // USB Bus Interface for NXP LPC11Uxx
00003 // Copyright (c) 2011 ARM Limited. All rights reserved.
00004 
00005 // Reference:
00006 // NXP UM10462 LPC11U1x User manual Rev. 1 � 14 April 2011
00007 
00008 #ifdef TARGET_LPC11U24
00009 
00010 #include "USBBusInterface.h"
00011 
00012 USBHAL * USBHAL::instance;
00013 
00014 
00015 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
00016 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
00017 
00018 // Convert physical endpoint number to register bit
00019 #define EP(endpoint) (1UL<<endpoint)
00020 
00021 // Convert physical to logical
00022 #define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
00023 
00024 // Get endpoint direction
00025 #define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
00026 #define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
00027 
00028 // USB RAM
00029 #define USB_RAM_START (0x20004000)
00030 #define USB_RAM_SIZE  (0x00000800)
00031 
00032 // SYSAHBCLKCTRL
00033 #define CLK_USB     (1UL<<14)
00034 #define CLK_USBRAM  (1UL<<27)
00035 
00036 // USB Information register
00037 #define FRAME_NR(a)     ((a) & 0x7ff)   // Frame number
00038 
00039 // USB Device Command/Status register
00040 #define DEV_ADDR_MASK   (0x7f)          // Device address
00041 #define DEV_ADDR(a)     ((a) & DEV_ADDR_MASK)
00042 #define DEV_EN          (1UL<<7)        // Device enable
00043 #define SETUP           (1UL<<8)        // SETUP token received
00044 #define PLL_ON          (1UL<<9)        // PLL enabled in suspend
00045 #define DCON            (1UL<<16)       // Device status - connect
00046 #define DSUS            (1UL<<17)       // Device status - suspend
00047 #define DCON_C          (1UL<<24)       // Connect change
00048 #define DSUS_C          (1UL<<25)       // Suspend change
00049 #define DRES_C          (1UL<<26)       // Reset change
00050 #define VBUSDEBOUNCED   (1UL<<28)       // Vbus detected
00051 
00052 // Endpoint Command/Status list
00053 #define CMDSTS_A                 (1UL<<31)          // Active
00054 #define CMDSTS_D                 (1UL<<30)          // Disable
00055 #define CMDSTS_S                 (1UL<<29)          // Stall
00056 #define CMDSTS_TR                (1UL<<28)          // Toggle Reset
00057 #define CMDSTS_RF                (1UL<<27)          // Rate Feedback mode
00058 #define CMDSTS_TV                (1UL<<27)          // Toggle Value
00059 #define CMDSTS_T                 (1UL<<26)          // Endpoint Type
00060 #define CMDSTS_NBYTES(n)         (((n)&0x3ff)<<16)  // Number of bytes
00061 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff)  // Buffer start address
00062 
00063 #define BYTES_REMAINING(s)       (((s)>>16)&0x3ff)  // Bytes remaining after transfer
00064 
00065 // USB Non-endpoint interrupt sources
00066 #define FRAME_INT   (1UL<<30)
00067 #define DEV_INT     (1UL<<31)
00068 
00069 static volatile int epComplete = 0;
00070 
00071 // One entry for a double-buffered logical endpoint in the endpoint
00072 // command/status list. Endpoint 0 is single buffered, out[1] is used
00073 // for the SETUP packet and in[1] is not used
00074 typedef __packed struct {
00075     uint32_t out[2];
00076     uint32_t in[2];
00077 } EP_COMMAND_STATUS;
00078 
00079 typedef __packed struct {
00080     uint8_t out[MAX_PACKET_SIZE_EP0];
00081     uint8_t in[MAX_PACKET_SIZE_EP0];
00082     uint8_t setup[SETUP_PACKET_SIZE];
00083 } CONTROL_TRANSFER;
00084 
00085 typedef __packed struct {
00086     uint32_t    maxPacket;
00087     uint32_t    buffer[2];
00088     uint32_t    options;
00089 } EP_STATE;
00090 
00091 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
00092 
00093 // Pointer to the endpoint command/status list
00094 static EP_COMMAND_STATUS *ep = NULL;
00095 
00096 // Pointer to endpoint 0 data (IN/OUT and SETUP)
00097 static CONTROL_TRANSFER *ct = NULL;
00098 
00099 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
00100 // initiating a remote wakeup event.
00101 static volatile uint32_t devCmdStat;
00102 
00103 // Pointers used to allocate USB RAM
00104 static uint32_t usbRamPtr = USB_RAM_START;
00105 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
00106 
00107 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
00108 
00109 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
00110 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
00111     if (size > 0) {
00112         do {
00113             *dst++ = *src++;
00114         } while (--size > 0);
00115     }
00116 }
00117 
00118 
00119 USBHAL::USBHAL(void) {
00120     NVIC_DisableIRQ(USB_IRQn);
00121 
00122     // nUSB_CONNECT output
00123     LPC_IOCON->PIO0_6 = 0x00000001;
00124 
00125     // Enable clocks (USB registers, USB RAM)
00126     LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
00127 
00128     // Ensure device disconnected (DCON not set)
00129     LPC_USB->DEVCMDSTAT = 0;
00130 
00131     // to ensure that the USB host sees the device as
00132     // disconnected if the target CPU is reset.
00133     wait(0.3);
00134 
00135     // Reserve space in USB RAM for endpoint command/status list
00136     // Must be 256 byte aligned
00137     usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
00138     ep = (EP_COMMAND_STATUS *)usbRamPtr;
00139     usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
00140     LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
00141 
00142     // Reserve space in USB RAM for Endpoint 0
00143     // Must be 64 byte aligned
00144     usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
00145     ct = (CONTROL_TRANSFER *)usbRamPtr;
00146     usbRamPtr += sizeof(CONTROL_TRANSFER);
00147     LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
00148 
00149     // Setup command/status list for EP0
00150     ep[0].out[0] = 0;
00151     ep[0].in[0] =  0;
00152     ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
00153 
00154     // Route all interrupts to IRQ, some can be routed to
00155     // USB_FIQ if you wish.
00156     LPC_USB->INTROUTING = 0;
00157 
00158     // Set device address 0, enable USB device, no remote wakeup
00159     devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
00160     LPC_USB->DEVCMDSTAT = devCmdStat;
00161 
00162     // Enable interrupts for device events and EP0
00163     LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT;
00164     instance = this;
00165 
00166     //attach IRQ handler and enable interrupts
00167     NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
00168     NVIC_EnableIRQ(USB_IRQn);
00169 }
00170 
00171 USBHAL::~USBHAL(void) {
00172     // Ensure device disconnected (DCON not set)
00173     LPC_USB->DEVCMDSTAT = 0;
00174 
00175     // Disable USB interrupts
00176     NVIC_DisableIRQ(USB_IRQn);
00177 }
00178 
00179 void USBHAL::connect(void) {
00180     devCmdStat |= DCON;
00181     LPC_USB->DEVCMDSTAT = devCmdStat;
00182 }
00183 
00184 void USBHAL::disconnect(void) {
00185     devCmdStat &= ~DCON;
00186     LPC_USB->DEVCMDSTAT = devCmdStat;
00187 }
00188 
00189 void USBHAL::configureDevice(void) {
00190 }
00191 
00192 void USBHAL::unconfigureDevice(void) {
00193 }
00194 
00195 void USBHAL::EP0setup(uint8_t *buffer) {
00196     // Copy setup packet data
00197     USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
00198 }
00199 
00200 void USBHAL::EP0read(void) {
00201     // Start an endpoint 0 read
00202 
00203     // The USB ISR will call USBDevice_EP0out() when a packet has been read,
00204     // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
00205     // read the data.
00206 
00207     ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
00208                    | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
00209 }
00210 
00211 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00212     // Complete an endpoint 0 read
00213     uint32_t bytesRead;
00214 
00215     // Find how many bytes were read
00216     bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
00217 
00218     // Copy data
00219     USBMemCopy(buffer, ct->out, bytesRead);
00220     return bytesRead;
00221 }
00222 
00223 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00224     // Start and endpoint 0 write
00225 
00226     // The USB ISR will call USBDevice_EP0in() when the data has
00227     // been written, the USBDevice layer then calls
00228     // USBBusInterface_EP0getWriteResult() to complete the transaction.
00229 
00230     // Copy data
00231     USBMemCopy(ct->in, buffer, size);
00232 
00233     // Start transfer
00234     ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
00235                   | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
00236 }
00237 
00238 
00239 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00240     uint8_t bf = 0;
00241     uint32_t flags = 0;
00242 
00243     //check which buffer must be filled
00244     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00245         // Double buffered
00246         if (LPC_USB->EPINUSE & EP(endpoint)) {
00247             bf = 1;
00248         } else {
00249             bf = 0;
00250         }
00251     }
00252     
00253     // if isochronous endpoint, T = 1
00254     if(endpointState[endpoint].options & ISOCHRONOUS)
00255     {
00256         flags |= CMDSTS_T;
00257     }
00258         
00259     //Active the endpoint for reading
00260     ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
00261                                        | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
00262     return EP_PENDING;
00263 }
00264 
00265 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
00266 
00267     uint8_t bf = 0;
00268 
00269     if (!(epComplete & EP(endpoint)))
00270         return EP_PENDING;
00271     else {
00272         epComplete &= ~EP(endpoint);
00273 
00274         //check which buffer has been filled
00275         if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00276             // Double buffered (here we read the previous buffer which was used)
00277             if (LPC_USB->EPINUSE & EP(endpoint)) {
00278                 bf = 0;
00279             } else {
00280                 bf = 1;
00281             }
00282         }
00283 
00284         // Find how many bytes were read
00285         *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
00286 
00287         // Copy data
00288         USBMemCopy(data, ct->out, *bytesRead);
00289         return EP_COMPLETED;
00290     }
00291 }
00292 
00293 void USBHAL::EP0getWriteResult(void) {
00294     // Complete an endpoint 0 write
00295 
00296     // Nothing required for this target
00297     return;
00298 }
00299 
00300 void USBHAL::EP0stall(void) {
00301     ep[0].in[0] = CMDSTS_S;
00302     ep[0].out[0] = CMDSTS_S;
00303 }
00304 
00305 void USBHAL::setAddress(uint8_t address) {
00306     devCmdStat &= ~DEV_ADDR_MASK;
00307     devCmdStat |= DEV_ADDR(address);
00308     LPC_USB->DEVCMDSTAT = devCmdStat;
00309 }
00310 
00311 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00312     uint32_t flags = 0;
00313     uint32_t bf;
00314 
00315     // Validate parameters
00316     if (data == NULL) {
00317         return EP_INVALID;
00318     }
00319 
00320     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00321         return EP_INVALID;
00322     }
00323 
00324     if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
00325         return EP_INVALID;
00326     }
00327 
00328     if (size > endpointState[endpoint].maxPacket) {
00329         return EP_INVALID;
00330     }
00331 
00332     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00333         // Double buffered
00334         if (LPC_USB->EPINUSE & EP(endpoint)) {
00335             bf = 1;
00336         } else {
00337             bf = 0;
00338         }
00339     } else {
00340         // Single buffered
00341         bf = 0;
00342     }
00343 
00344     // Check if already active
00345     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
00346         return EP_INVALID;
00347     }
00348 
00349     // Check if stalled
00350     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
00351         return EP_STALLED;
00352     }
00353 
00354     // Copy data to USB RAM
00355     USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
00356 
00357     // Add options
00358     if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
00359         flags |= CMDSTS_RF;
00360     }
00361 
00362     if (endpointState[endpoint].options & ISOCHRONOUS) {
00363         flags |= CMDSTS_T;
00364     }
00365 
00366     // Add transfer
00367     ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
00368                                       endpointState[endpoint].buffer[bf]) \
00369                                       | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
00370 
00371     return EP_PENDING;
00372 }
00373 
00374 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00375     uint32_t bf;
00376     // Validate parameters
00377 
00378     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00379         return EP_INVALID;
00380     }
00381 
00382     if (OUT_EP(endpoint)) {
00383         return EP_INVALID;
00384     }
00385 
00386     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00387         // Double buffered     // TODO: FIX THIS
00388         if (LPC_USB->EPINUSE & EP(endpoint)) {
00389             bf = 1;
00390         } else {
00391             bf = 0;
00392         }
00393     } else {
00394         // Single buffered
00395         bf = 0;
00396     }
00397 
00398     // Check if endpoint still active
00399     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
00400         return EP_PENDING;
00401     }
00402 
00403     // Check if stalled
00404     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
00405         return EP_STALLED;
00406     }
00407 
00408     return EP_COMPLETED;
00409 }
00410 
00411 void USBHAL::stallEndpoint(uint8_t endpoint) {
00412 
00413     // TODO: should this clear active bit?
00414 
00415     if (IN_EP(endpoint)) {
00416         ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
00417         ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
00418     } else {
00419         ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
00420         ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
00421     }
00422 }
00423 
00424 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00425     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00426         // Double buffered
00427         if (IN_EP(endpoint)) {
00428             ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
00429             ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
00430 
00431             if (LPC_USB->EPINUSE & EP(endpoint)) {
00432                 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
00433             } else {
00434                 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
00435             }
00436         } else {
00437             ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
00438             ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
00439 
00440             if (LPC_USB->EPINUSE & EP(endpoint)) {
00441                 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
00442             } else {
00443                 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
00444             }
00445         }
00446     } else {
00447         // Single buffered
00448         if (IN_EP(endpoint)) {
00449             ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
00450         } else {
00451             ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
00452         }
00453     }
00454 }
00455 
00456 bool USBHAL::getEndpointStallState(unsigned char endpoint) {
00457     if (IN_EP(endpoint)) {
00458         if (LPC_USB->EPINUSE & EP(endpoint)) {
00459             if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
00460                 return true;
00461             }
00462         } else {
00463             if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
00464                 return true;
00465             }
00466         }
00467     } else {
00468         if (LPC_USB->EPINUSE & EP(endpoint)) {
00469             if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
00470                 return true;
00471             }
00472         } else {
00473             if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
00474                 return true;
00475             }
00476         }
00477     }
00478 
00479     return false;
00480 }
00481 
00482 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
00483     uint32_t tmpEpRamPtr;
00484 
00485     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00486         return false;
00487     }
00488 
00489     // Not applicable to the control endpoints
00490     if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
00491         return false;
00492     }
00493 
00494     // Allocate buffers in USB RAM
00495     tmpEpRamPtr = epRamPtr;
00496 
00497     // Must be 64 byte aligned
00498     tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00499 
00500     if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
00501         // Out of memory
00502         return false;
00503     }
00504 
00505     // Allocate first buffer
00506     endpointState[endpoint].buffer[0] = tmpEpRamPtr;
00507     tmpEpRamPtr += maxPacket;
00508 
00509     if (!(options & SINGLE_BUFFERED)) {
00510         // Must be 64 byte aligned
00511         tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00512 
00513         if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
00514             // Out of memory
00515             return false;
00516         }
00517 
00518         // Allocate second buffer
00519         endpointState[endpoint].buffer[1] = tmpEpRamPtr;
00520         tmpEpRamPtr += maxPacket;
00521     }
00522 
00523     // Commit to this USB RAM allocation
00524     epRamPtr = tmpEpRamPtr;
00525 
00526     // Remaining endpoint state values
00527     endpointState[endpoint].maxPacket = maxPacket;
00528     endpointState[endpoint].options = options;
00529 
00530     // Enable double buffering if required
00531     if (options & SINGLE_BUFFERED) {
00532         LPC_USB->EPBUFCFG &= ~EP(endpoint);
00533     } else {
00534         // Double buffered
00535         LPC_USB->EPBUFCFG |= EP(endpoint);
00536     }
00537 
00538     // Enable interrupt
00539     LPC_USB->INTEN |= EP(endpoint);
00540 
00541     // Enable endpoint
00542     unstallEndpoint(endpoint);
00543     return true;
00544 }
00545 
00546 void USBHAL::remoteWakeup(void) {
00547     // Clearing DSUS bit initiates a remote wakeup if the
00548     // device is currently enabled and suspended - otherwise
00549     // it has no effect.
00550     LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
00551 }
00552 
00553 
00554 static void disableEndpoints(void) {
00555     uint32_t logEp;
00556 
00557     // Ref. Table 158 "When a bus reset is received, software
00558     // must set the disable bit of all endpoints to 1".
00559 
00560     for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
00561         ep[logEp].out[0] = CMDSTS_D;
00562         ep[logEp].out[1] = CMDSTS_D;
00563         ep[logEp].in[0] =  CMDSTS_D;
00564         ep[logEp].in[1] =  CMDSTS_D;
00565     }
00566 
00567     // Start of USB RAM for endpoints > 0
00568     epRamPtr = usbRamPtr;
00569 }
00570 
00571 
00572 
00573 void USBHAL::_usbisr(void) {
00574     instance->usbisr();
00575 }
00576 
00577 
00578 void USBHAL::usbisr(void) {
00579     // Start of frame
00580     if (LPC_USB->INTSTAT & FRAME_INT) {
00581         // Clear SOF interrupt
00582         LPC_USB->INTSTAT = FRAME_INT;
00583 
00584         // SOF event, read frame number
00585         SOF(FRAME_NR(LPC_USB->INFO));
00586     }
00587 
00588     // Device state
00589     if (LPC_USB->INTSTAT & DEV_INT) {
00590         LPC_USB->INTSTAT = DEV_INT;
00591 
00592         if (LPC_USB->DEVCMDSTAT & DCON_C) {
00593             // Connect status changed
00594             LPC_USB->DEVCMDSTAT = devCmdStat | DCON_C;
00595 
00596             connectStateChanged((LPC_USB->DEVCMDSTAT & DCON) != 0);
00597         }
00598 
00599         if (LPC_USB->DEVCMDSTAT & DSUS_C) {
00600             // Suspend status changed
00601             LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
00602 
00603             suspendStateChanged((LPC_USB->DEVCMDSTAT & DSUS) != 0);
00604         }
00605 
00606         if (LPC_USB->DEVCMDSTAT & DRES_C) {
00607             // Bus reset
00608             LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
00609 
00610             // Disable endpoints > 0
00611             disableEndpoints();
00612 
00613             // Bus reset event
00614             busReset();
00615         }
00616     }
00617 
00618     // Endpoint 0
00619     if (LPC_USB->INTSTAT & EP(EP0OUT)) {
00620         // Clear EP0OUT/SETUP interrupt
00621         LPC_USB->INTSTAT = EP(EP0OUT);
00622 
00623         // Check if SETUP
00624         if (LPC_USB->DEVCMDSTAT & SETUP) {
00625             // Clear Active and Stall bits for EP0
00626             // Documentation does not make it clear if we must use the
00627             // EPSKIP register to achieve this, Fig. 16 and NXP reference
00628             // code suggests we can just clear the Active bits - check with
00629             // NXP to be sure.
00630             ep[0].in[0] = 0;
00631             ep[0].out[0] = 0;
00632 
00633             // Clear EP0IN interrupt
00634             LPC_USB->INTSTAT = EP(EP0IN);
00635 
00636             // Clear SETUP (and INTONNAK_CI/O) in device status register
00637             LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
00638 
00639             // EP0 SETUP event (SETUP data received)
00640             EP0setupCallback();
00641         } else {
00642             // EP0OUT ACK event (OUT data received)
00643             EP0out();
00644         }
00645     }
00646 
00647     if (LPC_USB->INTSTAT & EP(EP0IN)) {
00648         // Clear EP0IN interrupt
00649         LPC_USB->INTSTAT = EP(EP0IN);
00650 
00651         // EP0IN ACK event (IN data sent)
00652         EP0in();
00653     }
00654 
00655     if (LPC_USB->INTSTAT & EP(EP1IN)) {
00656         // Clear EP1IN interrupt
00657         LPC_USB->INTSTAT = EP(EP1IN);
00658         epComplete |= EP(EP1IN);
00659         if (EP1_IN_callback())
00660             epComplete &= ~EP(EP1IN);
00661     }
00662 
00663     if (LPC_USB->INTSTAT & EP(EP1OUT)) {
00664         // Clear EP1OUT interrupt
00665         LPC_USB->INTSTAT = EP(EP1OUT);
00666         epComplete |= EP(EP1OUT);
00667         if (EP1_OUT_callback())
00668             epComplete &= ~EP(EP1OUT);
00669     }
00670 
00671     if (LPC_USB->INTSTAT & EP(EP2IN)) {
00672         // Clear EPBULK_IN interrupt
00673         LPC_USB->INTSTAT = EP(EP2IN);
00674         epComplete |= EP(EP2IN);
00675         if (EP2_IN_callback())
00676             epComplete &= ~EP(EP2IN);
00677     }
00678 
00679     if (LPC_USB->INTSTAT & EP(EP2OUT)) {
00680         // Clear EPBULK_OUT interrupt
00681         LPC_USB->INTSTAT = EP(EP2OUT);
00682         epComplete |= EP(EP2OUT);
00683         //Call callback function. If true, clear epComplete
00684         if (EP2_OUT_callback())
00685             epComplete &= ~EP(EP2OUT);
00686     }
00687 
00688     if (LPC_USB->INTSTAT & EP(EP3IN)) {
00689         // Clear EP3_IN interrupt
00690         LPC_USB->INTSTAT = EP(EP3IN);
00691         epComplete |= EP(EP3IN);
00692         if (EP3_IN_callback())
00693             epComplete &= ~EP(EP3IN);
00694     }
00695 
00696     if (LPC_USB->INTSTAT & EP(EP3OUT)) {
00697         // Clear EP3_OUT interrupt
00698         LPC_USB->INTSTAT = EP(EP3OUT);
00699         epComplete |= EP(EP3OUT);
00700         //Call callback function. If true, clear epComplete
00701         if (EP3_OUT_callback())
00702             epComplete &= ~EP(EP3OUT);
00703     }
00704 }
00705 
00706 #endif