USB device stack

Dependents:   blinky_max32630fthr FTHR_USB_serial FTHR_OLED HSP_RPC_GUI_3_0_1 ... more

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC40.cpp Source File

USBHAL_LPC40.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 #if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
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 PORT_CLK_EN (1UL<<3)
00037 #define AHB_CLK_EN  (1UL<<4)
00038 
00039 // USB Clock Status register
00040 #define DEV_CLK_ON (1UL<<1)
00041 #define AHB_CLK_ON (1UL<<4)
00042 
00043 // USB Device Interupt registers
00044 #define FRAME      (1UL<<0)
00045 #define EP_FAST    (1UL<<1)
00046 #define EP_SLOW    (1UL<<2)
00047 #define DEV_STAT   (1UL<<3)
00048 #define CCEMPTY    (1UL<<4)
00049 #define CDFULL     (1UL<<5)
00050 #define RxENDPKT   (1UL<<6)
00051 #define TxENDPKT   (1UL<<7)
00052 #define EP_RLZED   (1UL<<8)
00053 #define ERR_INT    (1UL<<9)
00054 
00055 // USB Control register
00056 #define RD_EN (1<<0)
00057 #define WR_EN (1<<1)
00058 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
00059 
00060 // USB Receive Packet Length register
00061 #define DV      (1UL<<10)
00062 #define PKT_RDY (1UL<<11)
00063 #define PKT_LNGTH_MASK (0x3ff)
00064 
00065 // Serial Interface Engine (SIE)
00066 #define SIE_WRITE   (0x01)
00067 #define SIE_READ    (0x02)
00068 #define SIE_COMMAND (0x05)
00069 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
00070 
00071 // SIE Command codes
00072 #define SIE_CMD_SET_ADDRESS        (0xD0)
00073 #define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
00074 #define SIE_CMD_SET_MODE           (0xF3)
00075 #define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
00076 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
00077 #define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
00078 #define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
00079 #define SIE_CMD_GET_ERROR_CODE     (0xFF)
00080 #define SIE_CMD_READ_ERROR_STATUS  (0xFB)
00081 
00082 #define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
00083 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
00084 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
00085 
00086 #define SIE_CMD_CLEAR_BUFFER    (0xF2)
00087 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
00088 
00089 // SIE Device Status register
00090 #define SIE_DS_CON    (1<<0)
00091 #define SIE_DS_CON_CH (1<<1)
00092 #define SIE_DS_SUS    (1<<2)
00093 #define SIE_DS_SUS_CH (1<<3)
00094 #define SIE_DS_RST    (1<<4)
00095 
00096 // SIE Device Set Address register
00097 #define SIE_DSA_DEV_EN  (1<<7)
00098 
00099 // SIE Configue Device register
00100 #define SIE_CONF_DEVICE (1<<0)
00101 
00102 // Select Endpoint register
00103 #define SIE_SE_FE       (1<<0)
00104 #define SIE_SE_ST       (1<<1)
00105 #define SIE_SE_STP      (1<<2)
00106 #define SIE_SE_PO       (1<<3)
00107 #define SIE_SE_EPN      (1<<4)
00108 #define SIE_SE_B_1_FULL (1<<5)
00109 #define SIE_SE_B_2_FULL (1<<6)
00110 
00111 // Set Endpoint Status command
00112 #define SIE_SES_ST      (1<<0)
00113 #define SIE_SES_DA      (1<<5)
00114 #define SIE_SES_RF_MO   (1<<6)
00115 #define SIE_SES_CND_ST  (1<<7)
00116 
00117 
00118 USBHAL * USBHAL::instance;
00119 
00120 static volatile int epComplete;
00121 static uint32_t endpointStallState;
00122 
00123 static void SIECommand(uint32_t command) {
00124     // The command phase of a SIE transaction
00125     LPC_USB->DevIntClr = CCEMPTY;
00126     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
00127     while (!(LPC_USB->DevIntSt & CCEMPTY));
00128 }
00129 
00130 static void SIEWriteData(uint8_t data) {
00131     // The data write phase of a SIE transaction
00132     LPC_USB->DevIntClr = CCEMPTY;
00133     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_WRITE, data);
00134     while (!(LPC_USB->DevIntSt & CCEMPTY));
00135 }
00136 
00137 static uint8_t SIEReadData(uint32_t command) {
00138     // The data read phase of a SIE transaction
00139     LPC_USB->DevIntClr = CDFULL;
00140     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_READ, command);
00141     while (!(LPC_USB->DevIntSt & CDFULL));
00142     return (uint8_t)LPC_USB->CmdData;
00143 }
00144 
00145 static void SIEsetDeviceStatus(uint8_t status) {
00146     // Write SIE device status register
00147     SIECommand(SIE_CMD_SET_DEVICE_STATUS);
00148     SIEWriteData(status);
00149 }
00150 
00151 static uint8_t SIEgetDeviceStatus(void) {
00152     // Read SIE device status register
00153     SIECommand(SIE_CMD_GET_DEVICE_STATUS);
00154     return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
00155 }
00156 
00157 void SIEsetAddress(uint8_t address) {
00158     // Write SIE device address register
00159     SIECommand(SIE_CMD_SET_ADDRESS);
00160     SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
00161 }
00162 
00163 static uint8_t SIEselectEndpoint(uint8_t endpoint) {
00164     // SIE select endpoint command
00165     SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
00166     return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
00167 }
00168 
00169 static uint8_t SIEclearBuffer(void) {
00170     // SIE clear buffer command
00171     SIECommand(SIE_CMD_CLEAR_BUFFER);
00172     return SIEReadData(SIE_CMD_CLEAR_BUFFER);
00173 }
00174 
00175 static void SIEvalidateBuffer(void) {
00176     // SIE validate buffer command
00177     SIECommand(SIE_CMD_VALIDATE_BUFFER);
00178 }
00179 
00180 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
00181     // SIE set endpoint status command
00182     SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
00183     SIEWriteData(status);
00184 }
00185 
00186 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
00187 static uint16_t SIEgetFrameNumber(void) {
00188     // Read current frame number
00189     uint16_t lowByte;
00190     uint16_t highByte;
00191 
00192     SIECommand(SIE_CMD_READ_FRAME_NUMBER);
00193     lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00194     highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00195 
00196     return (highByte << 8) | lowByte;
00197 }
00198 
00199 static void SIEconfigureDevice(void) {
00200     // SIE Configure device command
00201     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00202     SIEWriteData(SIE_CONF_DEVICE);
00203 }
00204 
00205 static void SIEunconfigureDevice(void) {
00206     // SIE Configure device command
00207     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00208     SIEWriteData(0);
00209 }
00210 
00211 static void SIEconnect(void) {
00212     // Connect USB device
00213     uint8_t status = SIEgetDeviceStatus();
00214     SIEsetDeviceStatus(status | SIE_DS_CON);
00215 }
00216 
00217 
00218 static void SIEdisconnect(void) {
00219     // Disconnect USB device
00220     uint8_t status = SIEgetDeviceStatus();
00221     SIEsetDeviceStatus(status & ~SIE_DS_CON);
00222 }
00223 
00224 
00225 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
00226     // Implemented using using EP_INT_CLR.
00227     LPC_USB->EpIntClr = EP(endpoint);
00228     while (!(LPC_USB->DevIntSt & CDFULL));
00229     return (uint8_t)LPC_USB->CmdData;
00230 }
00231 
00232 
00233 static void enableEndpointEvent(uint8_t endpoint) {
00234     // Enable an endpoint interrupt
00235     LPC_USB->EpIntEn |= EP(endpoint);
00236 }
00237 
00238 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
00239 static void disableEndpointEvent(uint8_t endpoint) {
00240     // Disable an endpoint interrupt
00241     LPC_USB->EpIntEn &= ~EP(endpoint);
00242 }
00243 
00244 static volatile uint32_t __attribute__((used)) dummyRead;
00245 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
00246     // Read from an OUT endpoint
00247     uint32_t size;
00248     uint32_t i;
00249     uint32_t data = 0;
00250     uint8_t offset;
00251 
00252     LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | RD_EN;
00253     while (!(LPC_USB->RxPLen & PKT_RDY));
00254 
00255     size = LPC_USB->RxPLen & PKT_LNGTH_MASK;
00256 
00257     offset = 0;
00258 
00259     if (size > 0) {
00260         for (i=0; i<size; i++) {
00261             if (offset==0) {
00262                 // Fetch up to four bytes of data as a word
00263                 data = LPC_USB->RxData;
00264             }
00265 
00266             // extract a byte
00267             *buffer = (data>>offset) & 0xff;
00268             buffer++;
00269 
00270             // move on to the next byte
00271             offset = (offset + 8) % 32;
00272         }
00273     } else {
00274         dummyRead = LPC_USB->RxData;
00275     }
00276 
00277     LPC_USB->Ctrl = 0;
00278 
00279     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
00280         SIEselectEndpoint(endpoint);
00281         SIEclearBuffer();
00282     }
00283 
00284     return size;
00285 }
00286 
00287 static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
00288     // Write to an IN endpoint
00289     uint32_t temp, data;
00290     uint8_t offset;
00291 
00292     LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | WR_EN;
00293 
00294     LPC_USB->TxPLen = size;
00295     offset = 0;
00296     data = 0;
00297 
00298     if (size>0) {
00299         do {
00300             // Fetch next data byte into a word-sized temporary variable
00301             temp = *buffer++;
00302 
00303             // Add to current data word
00304             temp = temp << offset;
00305             data = data | temp;
00306 
00307             // move on to the next byte
00308             offset = (offset + 8) % 32;
00309             size--;
00310 
00311             if ((offset==0) || (size==0)) {
00312                 // Write the word to the endpoint
00313                 LPC_USB->TxData = data;
00314                 data = 0;
00315             }
00316         } while (size>0);
00317     } else {
00318         LPC_USB->TxData = 0;
00319     }
00320 
00321     // Clear WR_EN to cover zero length packet case
00322     LPC_USB->Ctrl=0;
00323 
00324     SIEselectEndpoint(endpoint);
00325     SIEvalidateBuffer();
00326 }
00327 
00328 USBHAL::USBHAL(void) {
00329     // Disable IRQ
00330     NVIC_DisableIRQ(USB_IRQn);
00331 
00332     // fill in callback array
00333     epCallback[0] = &USBHAL::EP1_OUT_callback;
00334     epCallback[1] = &USBHAL::EP1_IN_callback;
00335     epCallback[2] = &USBHAL::EP2_OUT_callback;
00336     epCallback[3] = &USBHAL::EP2_IN_callback;
00337     epCallback[4] = &USBHAL::EP3_OUT_callback;
00338     epCallback[5] = &USBHAL::EP3_IN_callback;
00339     epCallback[6] = &USBHAL::EP4_OUT_callback;
00340     epCallback[7] = &USBHAL::EP4_IN_callback;
00341     epCallback[8] = &USBHAL::EP5_OUT_callback;
00342     epCallback[9] = &USBHAL::EP5_IN_callback;
00343     epCallback[10] = &USBHAL::EP6_OUT_callback;
00344     epCallback[11] = &USBHAL::EP6_IN_callback;
00345     epCallback[12] = &USBHAL::EP7_OUT_callback;
00346     epCallback[13] = &USBHAL::EP7_IN_callback;
00347     epCallback[14] = &USBHAL::EP8_OUT_callback;
00348     epCallback[15] = &USBHAL::EP8_IN_callback;
00349     epCallback[16] = &USBHAL::EP9_OUT_callback;
00350     epCallback[17] = &USBHAL::EP9_IN_callback;
00351     epCallback[18] = &USBHAL::EP10_OUT_callback;
00352     epCallback[19] = &USBHAL::EP10_IN_callback;
00353     epCallback[20] = &USBHAL::EP11_OUT_callback;
00354     epCallback[21] = &USBHAL::EP11_IN_callback;
00355     epCallback[22] = &USBHAL::EP12_OUT_callback;
00356     epCallback[23] = &USBHAL::EP12_IN_callback;
00357     epCallback[24] = &USBHAL::EP13_OUT_callback;
00358     epCallback[25] = &USBHAL::EP13_IN_callback;
00359     epCallback[26] = &USBHAL::EP14_OUT_callback;
00360     epCallback[27] = &USBHAL::EP14_IN_callback;
00361     epCallback[28] = &USBHAL::EP15_OUT_callback;
00362     epCallback[29] = &USBHAL::EP15_IN_callback;
00363 
00364     // Enable power to USB device controller
00365     LPC_SC->PCONP |= PCUSB;
00366 
00367     // Enable USB clocks
00368     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
00369     while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
00370 
00371     // Select port USB2
00372     LPC_USB->StCtrl |= 3;
00373 
00374 
00375     // Configure pin P0.31 to be USB2
00376     LPC_IOCON->P0_31 &= ~0x07;
00377     LPC_IOCON->P0_31 |= 0x01;
00378 
00379     // Disconnect USB device
00380     SIEdisconnect();
00381 
00382     // Configure pin P0.14 to be Connect
00383     LPC_IOCON->P0_14 &= ~0x07;
00384     LPC_IOCON->P0_14 |= 0x03;
00385 
00386     // Connect must be low for at least 2.5uS
00387     wait(0.3);
00388 
00389     // Set the maximum packet size for the control endpoints
00390     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
00391     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
00392 
00393     // Attach IRQ
00394     instance = this;
00395     NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
00396 
00397     // Enable interrupts for device events and EP0
00398     LPC_USB->DevIntEn = EP_SLOW | DEV_STAT | FRAME;
00399     enableEndpointEvent(EP0IN);
00400     enableEndpointEvent(EP0OUT);
00401 }
00402 
00403 USBHAL::~USBHAL(void) {
00404     // Ensure device disconnected
00405     SIEdisconnect();
00406     // Disable USB interrupts
00407     NVIC_DisableIRQ(USB_IRQn);
00408 }
00409 
00410 void USBHAL::connect(void) {
00411     NVIC_EnableIRQ(USB_IRQn);
00412     // Connect USB device
00413     SIEconnect();
00414 }
00415 
00416 void USBHAL::disconnect(void) {
00417     NVIC_DisableIRQ(USB_IRQn);
00418     // Disconnect USB device
00419     SIEdisconnect();
00420 }
00421 
00422 void USBHAL::configureDevice(void) {
00423     SIEconfigureDevice();
00424 }
00425 
00426 void USBHAL::unconfigureDevice(void) {
00427     SIEunconfigureDevice();
00428 }
00429 
00430 void USBHAL::setAddress(uint8_t address) {
00431     SIEsetAddress(address);
00432 }
00433 
00434 void USBHAL::EP0setup(uint8_t *buffer) {
00435     endpointReadcore(EP0OUT, buffer);
00436 }
00437 
00438 void USBHAL::EP0read(void) {
00439     // Not required
00440 }
00441 
00442 void USBHAL::EP0readStage(void) {
00443     // Not required
00444 }
00445 
00446 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00447     return endpointReadcore(EP0OUT, buffer);
00448 }
00449 
00450 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00451     endpointWritecore(EP0IN, buffer, size);
00452 }
00453 
00454 void USBHAL::EP0getWriteResult(void) {
00455     // Not required
00456 }
00457 
00458 void USBHAL::EP0stall(void) {
00459     // This will stall both control endpoints
00460     stallEndpoint(EP0OUT);
00461 }
00462 
00463 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00464     return EP_PENDING;
00465 }
00466 
00467 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
00468 
00469     //for isochronous endpoint, we don't wait an interrupt
00470     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
00471         if (!(epComplete & EP(endpoint)))
00472             return EP_PENDING;
00473     }
00474 
00475     *bytesRead = endpointReadcore(endpoint, buffer);
00476     epComplete &= ~EP(endpoint);
00477     return EP_COMPLETED;
00478 }
00479 
00480 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00481     if (getEndpointStallState(endpoint)) {
00482         return EP_STALLED;
00483     }
00484 
00485     epComplete &= ~EP(endpoint);
00486 
00487     endpointWritecore(endpoint, data, size);
00488     return EP_PENDING;
00489 }
00490 
00491 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00492     if (epComplete & EP(endpoint)) {
00493         epComplete &= ~EP(endpoint);
00494         return EP_COMPLETED;
00495     }
00496 
00497     return EP_PENDING;
00498 }
00499 
00500 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
00501     // Realise an endpoint
00502     LPC_USB->DevIntClr = EP_RLZED;
00503     LPC_USB->ReEp |= EP(endpoint);
00504     LPC_USB->EpInd = endpoint;
00505     LPC_USB->MaxPSize = maxPacket;
00506 
00507     while (!(LPC_USB->DevIntSt & EP_RLZED));
00508     LPC_USB->DevIntClr = EP_RLZED;
00509 
00510     // Clear stall state
00511     endpointStallState &= ~EP(endpoint);
00512 
00513     enableEndpointEvent(endpoint);
00514     return true;
00515 }
00516 
00517 void USBHAL::stallEndpoint(uint8_t endpoint) {
00518     // Stall an endpoint
00519     if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
00520         // Conditionally stall both control endpoints
00521         SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
00522     } else {
00523         SIEsetEndpointStatus(endpoint, SIE_SES_ST);
00524 
00525         // Update stall state
00526         endpointStallState |= EP(endpoint);
00527     }
00528 }
00529 
00530 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00531     // Unstall an endpoint. The endpoint will also be reinitialised
00532     SIEsetEndpointStatus(endpoint, 0);
00533 
00534     // Update stall state
00535     endpointStallState &= ~EP(endpoint);
00536 }
00537 
00538 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
00539     // Returns true if endpoint stalled
00540     return endpointStallState & EP(endpoint);
00541 }
00542 
00543 void USBHAL::remoteWakeup(void) {
00544     // Remote wakeup
00545     uint8_t status;
00546 
00547     // Enable USB clocks
00548     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00549     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00550 
00551     status = SIEgetDeviceStatus();
00552     SIEsetDeviceStatus(status & ~SIE_DS_SUS);
00553 }
00554 
00555 void USBHAL::_usbisr(void) {
00556     instance->usbisr();
00557 }
00558 
00559 
00560 void USBHAL::usbisr(void) {
00561     uint8_t devStat;
00562 
00563     if (LPC_USB->DevIntSt & FRAME) {
00564         // Start of frame event
00565         SOF(SIEgetFrameNumber());
00566         // Clear interrupt status flag
00567         LPC_USB->DevIntClr = FRAME;
00568     }
00569 
00570     if (LPC_USB->DevIntSt & DEV_STAT) {
00571         // Device Status interrupt
00572         // Must clear the interrupt status flag before reading the device status from the SIE
00573         LPC_USB->DevIntClr = DEV_STAT;
00574 
00575         // Read device status from SIE
00576         devStat = SIEgetDeviceStatus();
00577         //printf("devStat: %d\r\n", devStat);
00578 
00579         if (devStat & SIE_DS_SUS_CH) {
00580             // Suspend status changed
00581             if((devStat & SIE_DS_SUS) != 0) {
00582                 suspendStateChanged(0);
00583             }
00584         }
00585 
00586         if (devStat & SIE_DS_RST) {
00587             // Bus reset
00588             if((devStat & SIE_DS_SUS) == 0) {
00589                 suspendStateChanged(1);
00590             }
00591             busReset();
00592         }
00593     }
00594 
00595     if (LPC_USB->DevIntSt & EP_SLOW) {
00596         // (Slow) Endpoint Interrupt
00597 
00598         // Process each endpoint interrupt
00599         if (LPC_USB->EpIntSt & EP(EP0OUT)) {
00600             if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
00601                 // this is a setup packet
00602                 EP0setupCallback();
00603             } else {
00604                 EP0out();
00605             }
00606             LPC_USB->DevIntClr = EP_SLOW;
00607         }
00608 
00609         if (LPC_USB->EpIntSt & EP(EP0IN)) {
00610             selectEndpointClearInterrupt(EP0IN);
00611             LPC_USB->DevIntClr = EP_SLOW;
00612             EP0in();
00613         }
00614 
00615         for (uint8_t num = 2; num < 16*2; num++) {
00616             if (LPC_USB->EpIntSt & EP(num)) {
00617                 selectEndpointClearInterrupt(num);
00618                 epComplete |= EP(num);
00619                 LPC_USB->DevIntClr = EP_SLOW;
00620                 if ((instance->*(epCallback[num - 2]))()) {
00621                     epComplete &= ~EP(num);
00622                 }
00623             }
00624         }
00625     }
00626 }
00627 
00628 #endif