Setcom Corporation / USBDevice

Dependents:   shaun_larada

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 {
00124     // The command phase of a SIE transaction
00125     LPC_USB->USBDevIntClr = CCEMPTY;
00126     LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_COMMAND, command );
00127 
00128     while ( !( LPC_USB->USBDevIntSt & CCEMPTY ) );
00129 }
00130 
00131 static void SIEWriteData( uint8_t data )
00132 {
00133     // The data write phase of a SIE transaction
00134     LPC_USB->USBDevIntClr = CCEMPTY;
00135     LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_WRITE, data );
00136 
00137     while ( !( LPC_USB->USBDevIntSt & CCEMPTY ) );
00138 }
00139 
00140 static uint8_t SIEReadData( uint32_t command )
00141 {
00142     // The data read phase of a SIE transaction
00143     LPC_USB->USBDevIntClr = CDFULL;
00144     LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_READ, command );
00145 
00146     while ( !( LPC_USB->USBDevIntSt & CDFULL ) );
00147 
00148     return ( uint8_t )LPC_USB->USBCmdData;
00149 }
00150 
00151 static void SIEsetDeviceStatus( uint8_t status )
00152 {
00153     // Write SIE device status register
00154     SIECommand( SIE_CMD_SET_DEVICE_STATUS );
00155     SIEWriteData( status );
00156 }
00157 
00158 static uint8_t SIEgetDeviceStatus( void )
00159 {
00160     // Read SIE device status register
00161     SIECommand( SIE_CMD_GET_DEVICE_STATUS );
00162     return SIEReadData( SIE_CMD_GET_DEVICE_STATUS );
00163 }
00164 
00165 void SIEsetAddress( uint8_t address )
00166 {
00167     // Write SIE device address register
00168     SIECommand( SIE_CMD_SET_ADDRESS );
00169     SIEWriteData( ( address & 0x7f ) | SIE_DSA_DEV_EN );
00170 }
00171 
00172 static uint8_t SIEselectEndpoint( uint8_t endpoint )
00173 {
00174     // SIE select endpoint command
00175     SIECommand( SIE_CMD_SELECT_ENDPOINT( endpoint ) );
00176     return SIEReadData( SIE_CMD_SELECT_ENDPOINT( endpoint ) );
00177 }
00178 
00179 static uint8_t SIEclearBuffer( void )
00180 {
00181     // SIE clear buffer command
00182     SIECommand( SIE_CMD_CLEAR_BUFFER );
00183     return SIEReadData( SIE_CMD_CLEAR_BUFFER );
00184 }
00185 
00186 static void SIEvalidateBuffer( void )
00187 {
00188     // SIE validate buffer command
00189     SIECommand( SIE_CMD_VALIDATE_BUFFER );
00190 }
00191 
00192 static void SIEsetEndpointStatus( uint8_t endpoint, uint8_t status )
00193 {
00194     // SIE set endpoint status command
00195     SIECommand( SIE_CMD_SET_ENDPOINT_STATUS( endpoint ) );
00196     SIEWriteData( status );
00197 }
00198 
00199 static uint16_t SIEgetFrameNumber( void ) __attribute__ ( ( unused ) );
00200 static uint16_t SIEgetFrameNumber( void )
00201 {
00202     // Read current frame number
00203     uint16_t lowByte;
00204     uint16_t highByte;
00205     SIECommand( SIE_CMD_READ_FRAME_NUMBER );
00206     lowByte = SIEReadData( SIE_CMD_READ_FRAME_NUMBER );
00207     highByte = SIEReadData( SIE_CMD_READ_FRAME_NUMBER );
00208     return ( highByte << 8 ) | lowByte;
00209 }
00210 
00211 static void SIEconfigureDevice( void )
00212 {
00213     // SIE Configure device command
00214     SIECommand( SIE_CMD_CONFIGURE_DEVICE );
00215     SIEWriteData( SIE_CONF_DEVICE );
00216 }
00217 
00218 static void SIEunconfigureDevice( void )
00219 {
00220     // SIE Configure device command
00221     SIECommand( SIE_CMD_CONFIGURE_DEVICE );
00222     SIEWriteData( 0 );
00223 }
00224 
00225 static void SIEconnect( void )
00226 {
00227     // Connect USB device
00228     uint8_t status;
00229     status = SIEgetDeviceStatus();
00230     SIEsetDeviceStatus( status | SIE_DS_CON );
00231 }
00232 
00233 
00234 static void SIEdisconnect( void )
00235 {
00236     // Disconnect USB device
00237     uint8_t status;
00238     status = SIEgetDeviceStatus();
00239     SIEsetDeviceStatus( status & ~SIE_DS_CON );
00240 }
00241 
00242 
00243 static uint8_t selectEndpointClearInterrupt( uint8_t endpoint )
00244 {
00245     // Implemented using using EP_INT_CLR.
00246     LPC_USB->USBEpIntClr = EP( endpoint );
00247 
00248     while ( !( LPC_USB->USBDevIntSt & CDFULL ) );
00249 
00250     return ( uint8_t )LPC_USB->USBCmdData;
00251 }
00252 
00253 
00254 
00255 
00256 
00257 static void enableEndpointEvent( uint8_t endpoint )
00258 {
00259     // Enable an endpoint interrupt
00260     LPC_USB->USBEpIntEn |= EP( endpoint );
00261 }
00262 
00263 static void disableEndpointEvent( uint8_t endpoint ) __attribute__ ( ( unused ) );
00264 static void disableEndpointEvent( uint8_t endpoint )
00265 {
00266     // Disable an endpoint interrupt
00267     LPC_USB->USBEpIntEn &= ~EP( endpoint );
00268 }
00269 
00270 static volatile uint32_t __attribute__( ( used ) ) dummyRead;
00271 
00272 
00273 uint32_t USBHAL::endpointReadcore( uint8_t endpoint, uint8_t *buffer )
00274 {
00275     // Read from an OUT endpoint
00276     uint32_t size;
00277     uint32_t i;
00278     uint32_t data = 0;
00279     uint8_t offset;
00280     LPC_USB->USBCtrl = LOG_ENDPOINT( endpoint ) | RD_EN;
00281 
00282     while ( !( LPC_USB->USBRxPLen & PKT_RDY ) );
00283 
00284     size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
00285     offset = 0;
00286 
00287     if ( size > 0 )
00288     {
00289         for ( i = 0; i < size; i++ )
00290         {
00291             if ( offset == 0 )
00292             {
00293                 // Fetch up to four bytes of data as a word
00294                 data = LPC_USB->USBRxData;
00295             }
00296 
00297             // extract a byte
00298             *buffer = ( data >> offset ) & 0xff;
00299             buffer++;
00300             // move on to the next byte
00301             offset = ( offset + 8 ) % 32;
00302         }
00303     }
00304     else
00305     {
00306         dummyRead = LPC_USB->USBRxData;
00307     }
00308 
00309     LPC_USB->USBCtrl = 0;
00310 
00311     if ( ( endpoint >> 1 ) % 3 || ( endpoint >> 1 ) == 0 )
00312     {
00313         SIEselectEndpoint( endpoint );
00314         SIEclearBuffer();
00315     }
00316 
00317     return size;
00318 }
00319 
00320 static void endpointWritecore( uint8_t endpoint, uint8_t *buffer, uint32_t size )
00321 {
00322     // Write to an IN endpoint
00323     uint32_t temp, data;
00324     uint8_t offset;
00325     LPC_USB->USBCtrl = LOG_ENDPOINT( endpoint ) | WR_EN;
00326     LPC_USB->USBTxPLen = size;
00327     offset = 0;
00328     data = 0;
00329 
00330     if ( size > 0 )
00331     {
00332         do
00333         {
00334             // Fetch next data byte into a word-sized temporary variable
00335             temp = *buffer++;
00336             // Add to current data word
00337             temp = temp << offset;
00338             data = data | temp;
00339             // move on to the next byte
00340             offset = ( offset + 8 ) % 32;
00341             size--;
00342 
00343             if ( ( offset == 0 ) || ( size == 0 ) )
00344             {
00345                 // Write the word to the endpoint
00346                 LPC_USB->USBTxData = data;
00347                 data = 0;
00348             }
00349         }
00350         while ( size > 0 );
00351     }
00352     else
00353     {
00354         LPC_USB->USBTxData = 0;
00355     }
00356 
00357     // Clear WR_EN to cover zero length packet case
00358     LPC_USB->USBCtrl = 0;
00359     SIEselectEndpoint( endpoint );
00360     SIEvalidateBuffer();
00361 }
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 USBHAL::USBHAL( void )
00370 {
00371     // Disable IRQ
00372     NVIC_DisableIRQ( USB_IRQn );
00373     // Enable power to USB device controller
00374     LPC_SC->PCONP |= PCUSB;
00375     // Enable USB clocks
00376     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00377 
00378     while ( LPC_USB->USBClkSt != ( DEV_CLK_ON | AHB_CLK_ON ) );
00379 
00380     // Configure pins P0.29 and P0.30 to be USB D+ and USB D-
00381     LPC_PINCON->PINSEL1 &= 0xc3ffffff;
00382     LPC_PINCON->PINSEL1 |= 0x14000000;
00383     // Disconnect USB device
00384     SIEdisconnect();
00385     // Configure pin P2.9 to be Connect
00386     LPC_PINCON->PINSEL4 &= 0xfffcffff;
00387     LPC_PINCON->PINSEL4 |= 0x00040000;
00388     // Connect must be low for at least 2.5uS
00389     wait( 0.3 );
00390     // Set the maximum packet size for the control endpoints
00391     realiseEndpoint( EP0IN, MAX_PACKET_SIZE_EP0, 0 );
00392     realiseEndpoint( EP0OUT, MAX_PACKET_SIZE_EP0, 0 );
00393     // Attach IRQ
00394     instance = this;
00395     NVIC_SetVector( USB_IRQn, ( uint32_t )&_usbisr );
00396     NVIC_EnableIRQ( USB_IRQn );
00397     // Enable interrupts for device events and EP0
00398     LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME;
00399     enableEndpointEvent( EP0IN );
00400     enableEndpointEvent( EP0OUT );
00401 }
00402 
00403 USBHAL::~USBHAL( void )
00404 {
00405     // Ensure device disconnected
00406     SIEdisconnect();
00407     // Disable USB interrupts
00408     NVIC_DisableIRQ( USB_IRQn );
00409 }
00410 
00411 void USBHAL::connect( void )
00412 {
00413     // Connect USB device
00414     SIEconnect();
00415 }
00416 
00417 void USBHAL::disconnect( void )
00418 {
00419     // Disconnect USB device
00420     SIEdisconnect();
00421 }
00422 
00423 void USBHAL::configureDevice( void )
00424 {
00425     SIEconfigureDevice();
00426 }
00427 
00428 void USBHAL::unconfigureDevice( void )
00429 {
00430     SIEunconfigureDevice();
00431 }
00432 
00433 void USBHAL::setAddress( uint8_t address )
00434 {
00435     SIEsetAddress( address );
00436 }
00437 
00438 void USBHAL::EP0setup( uint8_t *buffer )
00439 {
00440     endpointReadcore( EP0OUT, buffer );
00441 }
00442 
00443 void USBHAL::EP0read( void )
00444 {
00445     // Not required
00446 }
00447 
00448 uint32_t USBHAL::EP0getReadResult( uint8_t *buffer )
00449 {
00450     return endpointReadcore( EP0OUT, buffer );
00451 }
00452 
00453 void USBHAL::EP0write( uint8_t *buffer, uint32_t size )
00454 {
00455     endpointWritecore( EP0IN, buffer, size );
00456 }
00457 
00458 void USBHAL::EP0getWriteResult( void )
00459 {
00460     // Not required
00461 }
00462 
00463 void USBHAL::EP0stall( void )
00464 {
00465     // This will stall both control endpoints
00466     stallEndpoint( EP0OUT );
00467 }
00468 
00469 EP_STATUS USBHAL::endpointRead( uint8_t endpoint, uint32_t maximumSize )
00470 {
00471     return EP_PENDING;
00472 }
00473 
00474 EP_STATUS USBHAL::endpointReadResult( uint8_t endpoint, uint8_t *buffer, uint32_t *bytesRead )
00475 {
00476     //for isochronous endpoint, we don't wait an interrupt
00477     if ( ( endpoint >> 1 ) % 3 || ( endpoint >> 1 ) == 0 )
00478     {
00479         if ( !( epComplete & EP( endpoint ) ) )
00480         {
00481             return EP_PENDING;
00482         }
00483     }
00484 
00485     *bytesRead = endpointReadcore( endpoint, buffer );
00486     epComplete &= ~EP( endpoint );
00487     return EP_COMPLETED;
00488 }
00489 
00490 EP_STATUS USBHAL::endpointWrite( uint8_t endpoint, uint8_t *data, uint32_t size )
00491 {
00492     if ( getEndpointStallState( endpoint ) )
00493     {
00494         return EP_STALLED;
00495     }
00496 
00497     epComplete &= ~EP( endpoint );
00498     endpointWritecore( endpoint, data, size );
00499     return EP_PENDING;
00500 }
00501 
00502 EP_STATUS USBHAL::endpointWriteResult( uint8_t endpoint )
00503 {
00504     if ( epComplete & EP( endpoint ) )
00505     {
00506         epComplete &= ~EP( endpoint );
00507         return EP_COMPLETED;
00508     }
00509 
00510     return EP_PENDING;
00511 }
00512 
00513 bool USBHAL::realiseEndpoint( uint8_t endpoint, uint32_t maxPacket, uint32_t flags )
00514 {
00515     // Realise an endpoint
00516     LPC_USB->USBDevIntClr = EP_RLZED;
00517     LPC_USB->USBReEp |= EP( endpoint );
00518     LPC_USB->USBEpInd = endpoint;
00519     LPC_USB->USBMaxPSize = maxPacket;
00520 
00521     while ( !( LPC_USB->USBDevIntSt & EP_RLZED ) );
00522 
00523     LPC_USB->USBDevIntClr = EP_RLZED;
00524     // Clear stall state
00525     endpointStallState &= ~EP( endpoint );
00526     enableEndpointEvent( endpoint );
00527     return true;
00528 }
00529 
00530 void USBHAL::stallEndpoint( uint8_t endpoint )
00531 {
00532     // Stall an endpoint
00533     if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) )
00534     {
00535         // Conditionally stall both control endpoints
00536         SIEsetEndpointStatus( EP0OUT, SIE_SES_CND_ST );
00537     }
00538     else
00539     {
00540         SIEsetEndpointStatus( endpoint, SIE_SES_ST );
00541         // Update stall state
00542         endpointStallState |= EP( endpoint );
00543     }
00544 }
00545 
00546 void USBHAL::unstallEndpoint( uint8_t endpoint )
00547 {
00548     // Unstall an endpoint. The endpoint will also be reinitialised
00549     SIEsetEndpointStatus( endpoint, 0 );
00550     // Update stall state
00551     endpointStallState &= ~EP( endpoint );
00552 }
00553 
00554 bool USBHAL::getEndpointStallState( uint8_t endpoint )
00555 {
00556     // Returns true if endpoint stalled
00557     return endpointStallState & EP( endpoint );
00558 }
00559 
00560 void USBHAL::remoteWakeup( void )
00561 {
00562     // Remote wakeup
00563     uint8_t status;
00564     // Enable USB clocks
00565     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00566 
00567     while ( LPC_USB->USBClkSt != ( DEV_CLK_ON | AHB_CLK_ON ) );
00568 
00569     status = SIEgetDeviceStatus();
00570     SIEsetDeviceStatus( status & ~SIE_DS_SUS );
00571 }
00572 
00573 
00574 
00575 
00576 
00577 void USBHAL::_usbisr( void )
00578 {
00579     instance->usbisr();
00580 }
00581 
00582 
00583 void USBHAL::usbisr( void )
00584 {
00585     uint8_t devStat;
00586 
00587     if ( LPC_USB->USBDevIntSt & FRAME )
00588     {
00589         // Start of frame event
00590         SOF( SIEgetFrameNumber() );
00591         // Clear interrupt status flag
00592         LPC_USB->USBDevIntClr = FRAME;
00593     }
00594 
00595     if ( LPC_USB->USBDevIntSt & DEV_STAT )
00596     {
00597         // Device Status interrupt
00598         // Must clear the interrupt status flag before reading the device status from the SIE
00599         LPC_USB->USBDevIntClr = DEV_STAT;
00600         // Read device status from SIE
00601         devStat = SIEgetDeviceStatus();
00602         //printf("devStat: %d\r\n", devStat);
00603 
00604         if ( devStat & SIE_DS_SUS_CH )
00605         {
00606             // Suspend status changed
00607             if( ( devStat & SIE_DS_SUS ) != 0 )
00608             {
00609                 suspendStateChanged( 0 );
00610             }
00611         }
00612 
00613         if ( devStat & SIE_DS_RST )
00614         {
00615             // Bus reset
00616             if( ( devStat & SIE_DS_SUS ) == 0 )
00617             {
00618                 suspendStateChanged( 1 );
00619             }
00620 
00621             busReset();
00622         }
00623     }
00624 
00625     if ( LPC_USB->USBDevIntSt & EP_SLOW )
00626     {
00627         // (Slow) Endpoint Interrupt
00628 
00629         // Process each endpoint interrupt
00630         if ( LPC_USB->USBEpIntSt & EP( EP0OUT ) )
00631         {
00632             if ( selectEndpointClearInterrupt( EP0OUT ) & SIE_SE_STP )
00633             {
00634                 // this is a setup packet
00635                 EP0setupCallback();
00636             }
00637             else
00638             {
00639                 EP0out();
00640             }
00641 
00642             LPC_USB->USBDevIntClr = EP_SLOW;
00643         }
00644 
00645         if ( LPC_USB->USBEpIntSt & EP( EP0IN ) )
00646         {
00647             selectEndpointClearInterrupt( EP0IN );
00648             LPC_USB->USBDevIntClr = EP_SLOW;
00649             EP0in();
00650         }
00651 
00652         // TODO: This should cover all endpoints, not just EP1,2,3:
00653         if ( LPC_USB->USBEpIntSt & EP( EP1IN ) )
00654         {
00655             selectEndpointClearInterrupt( EP1IN );
00656             epComplete |= EP( EP1IN );
00657             LPC_USB->USBDevIntClr = EP_SLOW;
00658 
00659             if ( EP1_IN_callback() )
00660             {
00661                 epComplete &= ~EP( EP1IN );
00662             }
00663         }
00664 
00665         if ( LPC_USB->USBEpIntSt & EP( EP1OUT ) )
00666         {
00667             selectEndpointClearInterrupt( EP1OUT );
00668             epComplete |= EP( EP1OUT );
00669             LPC_USB->USBDevIntClr = EP_SLOW;
00670 
00671             if ( EP1_OUT_callback() )
00672             {
00673                 epComplete &= ~EP( EP1OUT );
00674             }
00675         }
00676 
00677         if ( LPC_USB->USBEpIntSt & EP( EP2IN ) )
00678         {
00679             selectEndpointClearInterrupt( EP2IN );
00680             epComplete |= EP( EP2IN );
00681             LPC_USB->USBDevIntClr = EP_SLOW;
00682 
00683             if ( EP2_IN_callback() )
00684             {
00685                 epComplete &= ~EP( EP2IN );
00686             }
00687         }
00688 
00689         if ( LPC_USB->USBEpIntSt & EP( EP2OUT ) )
00690         {
00691             selectEndpointClearInterrupt( EP2OUT );
00692             epComplete |= EP( EP2OUT );
00693             LPC_USB->USBDevIntClr = EP_SLOW;
00694 
00695             if ( EP2_OUT_callback() )
00696             {
00697                 epComplete &= ~EP( EP2OUT );
00698             }
00699         }
00700 
00701         if ( LPC_USB->USBEpIntSt & EP( EP3IN ) )
00702         {
00703             selectEndpointClearInterrupt( EP3IN );
00704             epComplete |= EP( EP3IN );
00705             LPC_USB->USBDevIntClr = EP_SLOW;
00706 
00707             if ( EP3_IN_callback() )
00708             {
00709                 epComplete &= ~EP( EP3IN );
00710             }
00711         }
00712 
00713         if ( LPC_USB->USBEpIntSt & EP( EP3OUT ) )
00714         {
00715             selectEndpointClearInterrupt( EP3OUT );
00716             epComplete |= EP( EP3OUT );
00717             LPC_USB->USBDevIntClr = EP_SLOW;
00718 
00719             if ( EP3_OUT_callback() )
00720             {
00721                 epComplete &= ~EP( EP3OUT );
00722             }
00723         }
00724     }
00725 }
00726 
00727 #endif
00728