キーボードの長押しに対応。

Dependents:   PS4_FF14_Adapter

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC11U.cpp Source File

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