Fork of official USB device library just changed PID (Product ID) in constructor in USBMSD.h to be different for USBMSD_AT45_HelloWorld program

Dependents:   USBMSD_AT45_HelloWorld

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC17.cpp Source File

USBHAL_LPC17.cpp

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #ifdef TARGET_LPC1768
00020 
00021 #include "USBHAL.h"
00022 
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 // Convert physical endpoint number to register bit
00029 #define EP(endpoint) (1UL<<endpoint)
00030 
00031 // Power Control for Peripherals register
00032 #define PCUSB      (1UL<<31)
00033 
00034 // USB Clock Control register
00035 #define DEV_CLK_EN (1UL<<1)
00036 #define AHB_CLK_EN (1UL<<4)
00037 
00038 // USB Clock Status register
00039 #define DEV_CLK_ON (1UL<<1)
00040 #define AHB_CLK_ON (1UL<<4)
00041 
00042 // USB Device Interupt registers
00043 #define FRAME      (1UL<<0)
00044 #define EP_FAST    (1UL<<1)
00045 #define EP_SLOW    (1UL<<2)
00046 #define DEV_STAT   (1UL<<3)
00047 #define CCEMPTY    (1UL<<4)
00048 #define CDFULL     (1UL<<5)
00049 #define RxENDPKT   (1UL<<6)
00050 #define TxENDPKT   (1UL<<7)
00051 #define EP_RLZED   (1UL<<8)
00052 #define ERR_INT    (1UL<<9)
00053 
00054 // USB Control register
00055 #define RD_EN (1<<0)
00056 #define WR_EN (1<<1)
00057 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
00058 
00059 // USB Receive Packet Length register
00060 #define DV      (1UL<<10)
00061 #define PKT_RDY (1UL<<11)
00062 #define PKT_LNGTH_MASK (0x3ff)
00063 
00064 // Serial Interface Engine (SIE)
00065 #define SIE_WRITE   (0x01)
00066 #define SIE_READ    (0x02)
00067 #define SIE_COMMAND (0x05)
00068 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
00069 
00070 // SIE Command codes
00071 #define SIE_CMD_SET_ADDRESS        (0xD0)
00072 #define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
00073 #define SIE_CMD_SET_MODE           (0xF3)
00074 #define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
00075 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
00076 #define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
00077 #define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
00078 #define SIE_CMD_GET_ERROR_CODE     (0xFF)
00079 #define SIE_CMD_READ_ERROR_STATUS  (0xFB)
00080 
00081 #define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
00082 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
00083 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
00084 
00085 #define SIE_CMD_CLEAR_BUFFER    (0xF2)
00086 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
00087 
00088 // SIE Device Status register
00089 #define SIE_DS_CON    (1<<0)
00090 #define SIE_DS_CON_CH (1<<1)
00091 #define SIE_DS_SUS    (1<<2)
00092 #define SIE_DS_SUS_CH (1<<3)
00093 #define SIE_DS_RST    (1<<4)
00094 
00095 // SIE Device Set Address register
00096 #define SIE_DSA_DEV_EN  (1<<7)
00097 
00098 // SIE Configue Device register
00099 #define SIE_CONF_DEVICE (1<<0)
00100 
00101 // Select Endpoint register
00102 #define SIE_SE_FE       (1<<0)
00103 #define SIE_SE_ST       (1<<1)
00104 #define SIE_SE_STP      (1<<2)
00105 #define SIE_SE_PO       (1<<3)
00106 #define SIE_SE_EPN      (1<<4)
00107 #define SIE_SE_B_1_FULL (1<<5)
00108 #define SIE_SE_B_2_FULL (1<<6)
00109 
00110 // Set Endpoint Status command
00111 #define SIE_SES_ST      (1<<0)
00112 #define SIE_SES_DA      (1<<5)
00113 #define SIE_SES_RF_MO   (1<<6)
00114 #define SIE_SES_CND_ST  (1<<7)
00115 
00116 
00117 USBHAL * USBHAL::instance;
00118 
00119 volatile int epComplete;
00120 uint32_t endpointStallState;
00121 
00122 static void SIECommand(uint32_t command) {
00123     // The command phase of a SIE transaction
00124     LPC_USB->USBDevIntClr = CCEMPTY;
00125     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
00126     while (!(LPC_USB->USBDevIntSt & CCEMPTY));
00127 }
00128 
00129 static void SIEWriteData(uint8_t data) {
00130     // The data write phase of a SIE transaction
00131     LPC_USB->USBDevIntClr = CCEMPTY;
00132     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
00133     while (!(LPC_USB->USBDevIntSt & CCEMPTY));
00134 }
00135 
00136 static uint8_t SIEReadData(uint32_t command) {
00137     // The data read phase of a SIE transaction
00138     LPC_USB->USBDevIntClr = CDFULL;
00139     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
00140     while (!(LPC_USB->USBDevIntSt & CDFULL));
00141     return (uint8_t)LPC_USB->USBCmdData;
00142 }
00143 
00144 static void SIEsetDeviceStatus(uint8_t status) {
00145     // Write SIE device status register
00146     SIECommand(SIE_CMD_SET_DEVICE_STATUS);
00147     SIEWriteData(status);
00148 }
00149 
00150 static uint8_t SIEgetDeviceStatus(void) {
00151     // Read SIE device status register
00152     SIECommand(SIE_CMD_GET_DEVICE_STATUS);
00153     return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
00154 }
00155 
00156 void SIEsetAddress(uint8_t address) {
00157     // Write SIE device address register
00158     SIECommand(SIE_CMD_SET_ADDRESS);
00159     SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
00160 }
00161 
00162 static uint8_t SIEselectEndpoint(uint8_t endpoint) {
00163     // SIE select endpoint command
00164     SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
00165     return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
00166 }
00167 
00168 static uint8_t SIEclearBuffer(void) {
00169     // SIE clear buffer command
00170     SIECommand(SIE_CMD_CLEAR_BUFFER);
00171     return SIEReadData(SIE_CMD_CLEAR_BUFFER);
00172 }
00173 
00174 static void SIEvalidateBuffer(void) {
00175     // SIE validate buffer command
00176     SIECommand(SIE_CMD_VALIDATE_BUFFER);
00177 }
00178 
00179 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
00180     // SIE set endpoint status command
00181     SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
00182     SIEWriteData(status);
00183 }
00184 
00185 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
00186 static uint16_t SIEgetFrameNumber(void) {
00187     // Read current frame number
00188     uint16_t lowByte;
00189     uint16_t highByte;
00190 
00191     SIECommand(SIE_CMD_READ_FRAME_NUMBER);
00192     lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00193     highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00194 
00195     return (highByte << 8) | lowByte;
00196 }
00197 
00198 static void SIEconfigureDevice(void) {
00199     // SIE Configure device command
00200     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00201     SIEWriteData(SIE_CONF_DEVICE);
00202 }
00203 
00204 static void SIEunconfigureDevice(void) {
00205     // SIE Configure device command
00206     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00207     SIEWriteData(0);
00208 }
00209 
00210 static void SIEconnect(void) {
00211     // Connect USB device
00212     uint8_t status;
00213 
00214     status = SIEgetDeviceStatus();
00215     SIEsetDeviceStatus(status | SIE_DS_CON);
00216 }
00217 
00218 
00219 static void SIEdisconnect(void) {
00220     // Disconnect USB device
00221     uint8_t status;
00222 
00223     status = SIEgetDeviceStatus();
00224     SIEsetDeviceStatus(status & ~SIE_DS_CON);
00225 }
00226 
00227 
00228 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
00229     // Implemented using using EP_INT_CLR.
00230     LPC_USB->USBEpIntClr = EP(endpoint);
00231     while (!(LPC_USB->USBDevIntSt & CDFULL));
00232     return (uint8_t)LPC_USB->USBCmdData;
00233 }
00234 
00235 
00236 
00237 
00238 
00239 static void enableEndpointEvent(uint8_t endpoint) {
00240     // Enable an endpoint interrupt
00241     LPC_USB->USBEpIntEn |= EP(endpoint);
00242 }
00243 
00244 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
00245 static void disableEndpointEvent(uint8_t endpoint) {
00246     // Disable an endpoint interrupt
00247     LPC_USB->USBEpIntEn &= ~EP(endpoint);
00248 }
00249 
00250 static volatile uint32_t __attribute__((used)) dummyRead;
00251 
00252 
00253 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
00254     // Read from an OUT endpoint
00255     uint32_t size;
00256     uint32_t i;
00257     uint32_t data = 0;
00258     uint8_t offset;
00259 
00260     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
00261     while (!(LPC_USB->USBRxPLen & PKT_RDY));
00262 
00263     size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
00264 
00265     offset = 0;
00266 
00267     if (size > 0) {
00268         for (i=0; i<size; i++) {
00269             if (offset==0) {
00270                 // Fetch up to four bytes of data as a word
00271                 data = LPC_USB->USBRxData;
00272             }
00273 
00274             // extract a byte
00275             *buffer = (data>>offset) & 0xff;
00276             buffer++;
00277 
00278             // move on to the next byte
00279             offset = (offset + 8) % 32;
00280         }
00281     } else {
00282         dummyRead = LPC_USB->USBRxData;
00283     }
00284 
00285     LPC_USB->USBCtrl = 0;
00286 
00287     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
00288         SIEselectEndpoint(endpoint);
00289         SIEclearBuffer();
00290     }
00291     
00292     return size;
00293 }
00294 
00295 static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
00296     // Write to an IN endpoint
00297     uint32_t temp, data;
00298     uint8_t offset;
00299 
00300     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
00301 
00302     LPC_USB->USBTxPLen = size;
00303     offset = 0;
00304     data = 0;
00305 
00306     if (size>0) {
00307         do {
00308             // Fetch next data byte into a word-sized temporary variable
00309             temp = *buffer++;
00310 
00311             // Add to current data word
00312             temp = temp << offset;
00313             data = data | temp;
00314 
00315             // move on to the next byte
00316             offset = (offset + 8) % 32;
00317             size--;
00318 
00319             if ((offset==0) || (size==0)) {
00320                 // Write the word to the endpoint
00321                 LPC_USB->USBTxData = data;
00322                 data = 0;
00323             }
00324         } while (size>0);
00325     } else {
00326         LPC_USB->USBTxData = 0;
00327     }
00328 
00329     // Clear WR_EN to cover zero length packet case
00330     LPC_USB->USBCtrl=0;
00331 
00332     SIEselectEndpoint(endpoint);
00333     SIEvalidateBuffer();
00334 }
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 USBHAL::USBHAL(void) {
00343     // Disable IRQ
00344     NVIC_DisableIRQ(USB_IRQn);
00345 
00346     // Enable power to USB device controller
00347     LPC_SC->PCONP |= PCUSB;
00348 
00349     // Enable USB clocks
00350     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00351     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00352 
00353     // Configure pins P0.29 and P0.30 to be USB D+ and USB D-
00354     LPC_PINCON->PINSEL1 &= 0xc3ffffff;
00355     LPC_PINCON->PINSEL1 |= 0x14000000;
00356 
00357     // Disconnect USB device
00358     SIEdisconnect();
00359 
00360     // Configure pin P2.9 to be Connect
00361     LPC_PINCON->PINSEL4 &= 0xfffcffff;
00362     LPC_PINCON->PINSEL4 |= 0x00040000;
00363 
00364     // Connect must be low for at least 2.5uS
00365     wait(0.3);
00366 
00367     // Set the maximum packet size for the control endpoints
00368     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
00369     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
00370 
00371     // Attach IRQ
00372     instance = this;
00373     NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
00374 
00375     // Enable interrupts for device events and EP0
00376     LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME;
00377     enableEndpointEvent(EP0IN);
00378     enableEndpointEvent(EP0OUT);
00379 }
00380 
00381 USBHAL::~USBHAL(void) {
00382     // Ensure device disconnected
00383     SIEdisconnect();
00384 
00385     // Disable USB interrupts
00386     NVIC_DisableIRQ(USB_IRQn);
00387 }
00388 
00389 void USBHAL::connect(void) {
00390     NVIC_EnableIRQ(USB_IRQn);
00391     // Connect USB device
00392     SIEconnect();
00393 }
00394 
00395 void USBHAL::disconnect(void) {
00396     NVIC_DisableIRQ(USB_IRQn);
00397     // Disconnect USB device
00398     SIEdisconnect();
00399 }
00400 
00401 void USBHAL::configureDevice(void) {
00402     SIEconfigureDevice();
00403 }
00404 
00405 void USBHAL::unconfigureDevice(void) {
00406     SIEunconfigureDevice();
00407 }
00408 
00409 void USBHAL::setAddress(uint8_t address) {
00410     SIEsetAddress(address);
00411 }
00412 
00413 void USBHAL::EP0setup(uint8_t *buffer) {
00414     endpointReadcore(EP0OUT, buffer);
00415 }
00416 
00417 void USBHAL::EP0read(void) {
00418     // Not required
00419 }
00420 
00421 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00422     return endpointReadcore(EP0OUT, buffer);
00423 }
00424 
00425 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00426     endpointWritecore(EP0IN, buffer, size);
00427 }
00428 
00429 void USBHAL::EP0getWriteResult(void) {
00430     // Not required
00431 }
00432 
00433 void USBHAL::EP0stall(void) {
00434     // This will stall both control endpoints
00435     stallEndpoint(EP0OUT);
00436 }
00437 
00438 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00439     return EP_PENDING;
00440 }
00441 
00442 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
00443 
00444     //for isochronous endpoint, we don't wait an interrupt
00445     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
00446         if (!(epComplete & EP(endpoint)))
00447             return EP_PENDING;
00448     }
00449     
00450     *bytesRead = endpointReadcore(endpoint, buffer);
00451     epComplete &= ~EP(endpoint);
00452     return EP_COMPLETED;
00453 }
00454 
00455 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00456     if (getEndpointStallState(endpoint)) {
00457         return EP_STALLED;
00458     }
00459 
00460     epComplete &= ~EP(endpoint);
00461 
00462     endpointWritecore(endpoint, data, size);
00463     return EP_PENDING;
00464 }
00465 
00466 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00467     if (epComplete & EP(endpoint)) {
00468         epComplete &= ~EP(endpoint);
00469         return EP_COMPLETED;
00470     }
00471 
00472     return EP_PENDING;
00473 }
00474 
00475 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
00476     // Realise an endpoint
00477     LPC_USB->USBDevIntClr = EP_RLZED;
00478     LPC_USB->USBReEp |= EP(endpoint);
00479     LPC_USB->USBEpInd = endpoint;
00480     LPC_USB->USBMaxPSize = maxPacket;
00481 
00482     while (!(LPC_USB->USBDevIntSt & EP_RLZED));
00483     LPC_USB->USBDevIntClr = EP_RLZED;
00484 
00485     // Clear stall state
00486     endpointStallState &= ~EP(endpoint);
00487 
00488     enableEndpointEvent(endpoint);
00489     return true;
00490 }
00491 
00492 void USBHAL::stallEndpoint(uint8_t endpoint) {
00493     // Stall an endpoint
00494     if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
00495         // Conditionally stall both control endpoints
00496         SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
00497     } else {
00498         SIEsetEndpointStatus(endpoint, SIE_SES_ST);
00499 
00500         // Update stall state
00501         endpointStallState |= EP(endpoint);
00502     }
00503 }
00504 
00505 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00506     // Unstall an endpoint. The endpoint will also be reinitialised
00507     SIEsetEndpointStatus(endpoint, 0);
00508 
00509     // Update stall state
00510     endpointStallState &= ~EP(endpoint);
00511 }
00512 
00513 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
00514     // Returns true if endpoint stalled
00515     return endpointStallState & EP(endpoint);
00516 }
00517 
00518 void USBHAL::remoteWakeup(void) {
00519     // Remote wakeup
00520     uint8_t status;
00521 
00522     // Enable USB clocks
00523     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00524     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00525 
00526     status = SIEgetDeviceStatus();
00527     SIEsetDeviceStatus(status & ~SIE_DS_SUS);
00528 }
00529 
00530 
00531 
00532 
00533 
00534 void USBHAL::_usbisr(void) {
00535     instance->usbisr();
00536 }
00537 
00538 
00539 void USBHAL::usbisr(void) {
00540     uint8_t devStat;
00541 
00542     if (LPC_USB->USBDevIntSt & FRAME) {
00543         // Start of frame event
00544         SOF(SIEgetFrameNumber());
00545         // Clear interrupt status flag
00546         LPC_USB->USBDevIntClr = FRAME;
00547     }
00548 
00549     if (LPC_USB->USBDevIntSt & DEV_STAT) {
00550         // Device Status interrupt
00551         // Must clear the interrupt status flag before reading the device status from the SIE
00552         LPC_USB->USBDevIntClr = DEV_STAT;
00553 
00554         // Read device status from SIE
00555         devStat = SIEgetDeviceStatus();
00556         //printf("devStat: %d\r\n", devStat);
00557 
00558         if (devStat & SIE_DS_SUS_CH) {
00559             // Suspend status changed
00560             if((devStat & SIE_DS_SUS) != 0) {
00561                 suspendStateChanged(0);
00562             }
00563         }
00564 
00565         if (devStat & SIE_DS_RST) {
00566             // Bus reset
00567             if((devStat & SIE_DS_SUS) == 0) {
00568                 suspendStateChanged(1);
00569             }
00570             busReset();
00571         }
00572     }
00573 
00574     if (LPC_USB->USBDevIntSt & EP_SLOW) {
00575         // (Slow) Endpoint Interrupt
00576 
00577         // Process each endpoint interrupt
00578         if (LPC_USB->USBEpIntSt & EP(EP0OUT)) {
00579             if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
00580                 // this is a setup packet
00581                 EP0setupCallback();
00582             } else {
00583                 EP0out();
00584             }
00585             LPC_USB->USBDevIntClr = EP_SLOW;
00586         }
00587 
00588         if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
00589             selectEndpointClearInterrupt(EP0IN);
00590             LPC_USB->USBDevIntClr = EP_SLOW;
00591             EP0in();
00592         }
00593 
00594         // TODO: This should cover all endpoints, not just EP1,2,3:
00595         if (LPC_USB->USBEpIntSt & EP(EP1IN)) {
00596             selectEndpointClearInterrupt(EP1IN);
00597             epComplete |= EP(EP1IN);
00598             LPC_USB->USBDevIntClr = EP_SLOW;
00599             if (EP1_IN_callback())
00600                 epComplete &= ~EP(EP1IN);
00601         }
00602 
00603         if (LPC_USB->USBEpIntSt & EP(EP1OUT)) {
00604             selectEndpointClearInterrupt(EP1OUT);
00605             epComplete |= EP(EP1OUT);
00606             LPC_USB->USBDevIntClr = EP_SLOW;
00607             if (EP1_OUT_callback())
00608                 epComplete &= ~EP(EP1OUT);
00609         }
00610 
00611         if (LPC_USB->USBEpIntSt & EP(EP2IN)) {
00612             selectEndpointClearInterrupt(EP2IN);
00613             epComplete |= EP(EP2IN);
00614             LPC_USB->USBDevIntClr = EP_SLOW;
00615             if (EP2_IN_callback())
00616                 epComplete &= ~EP(EP2IN);
00617         }
00618 
00619         if (LPC_USB->USBEpIntSt & EP(EP2OUT)) {
00620             selectEndpointClearInterrupt(EP2OUT);
00621             epComplete |= EP(EP2OUT);
00622             LPC_USB->USBDevIntClr = EP_SLOW;
00623             if (EP2_OUT_callback())
00624                 epComplete &= ~EP(EP2OUT);
00625         }
00626 
00627         if (LPC_USB->USBEpIntSt & EP(EP3IN)) {
00628             selectEndpointClearInterrupt(EP3IN);
00629             epComplete |= EP(EP3IN);
00630             LPC_USB->USBDevIntClr = EP_SLOW;
00631             if (EP3_IN_callback())
00632                 epComplete &= ~EP(EP3IN);
00633         }
00634 
00635         if (LPC_USB->USBEpIntSt & EP(EP3OUT)) {
00636             selectEndpointClearInterrupt(EP3OUT);
00637             epComplete |= EP(EP3OUT);
00638             LPC_USB->USBDevIntClr = EP_SLOW;
00639             if (EP3_OUT_callback())
00640                 epComplete &= ~EP(EP3OUT);
00641         }
00642     }
00643 }
00644 
00645 #endif