Fork of the official USBDevice library

Fork of USBDevice by mbed official

Committer:
screamer
Date:
Fri Apr 28 17:01:10 2017 +0000
Branch:
device-files
Revision:
76:f0fd8d911b24
Parent:
USBDevice/USBHAL_LPC40.cpp@73:8d28a0cb7b43
Changed the layout of USBDevice implementation for various targets to match mbed-os/targets. This also reduces the amount of files being compiled as USBDevice code for other targets is not compiled.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 73:8d28a0cb7b43 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
screamer 73:8d28a0cb7b43 2 *
screamer 73:8d28a0cb7b43 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
screamer 73:8d28a0cb7b43 4 * and associated documentation files (the "Software"), to deal in the Software without
screamer 73:8d28a0cb7b43 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
screamer 73:8d28a0cb7b43 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
screamer 73:8d28a0cb7b43 7 * Software is furnished to do so, subject to the following conditions:
screamer 73:8d28a0cb7b43 8 *
screamer 73:8d28a0cb7b43 9 * The above copyright notice and this permission notice shall be included in all copies or
screamer 73:8d28a0cb7b43 10 * substantial portions of the Software.
screamer 73:8d28a0cb7b43 11 *
screamer 73:8d28a0cb7b43 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
screamer 73:8d28a0cb7b43 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
screamer 73:8d28a0cb7b43 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
screamer 73:8d28a0cb7b43 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
screamer 73:8d28a0cb7b43 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
screamer 73:8d28a0cb7b43 17 */
screamer 73:8d28a0cb7b43 18
screamer 73:8d28a0cb7b43 19 #if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
screamer 73:8d28a0cb7b43 20
screamer 73:8d28a0cb7b43 21 #include "USBHAL.h"
screamer 73:8d28a0cb7b43 22
screamer 73:8d28a0cb7b43 23
screamer 73:8d28a0cb7b43 24 // Get endpoint direction
screamer 73:8d28a0cb7b43 25 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
screamer 73:8d28a0cb7b43 26 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
screamer 73:8d28a0cb7b43 27
screamer 73:8d28a0cb7b43 28 // Convert physical endpoint number to register bit
screamer 73:8d28a0cb7b43 29 #define EP(endpoint) (1UL<<endpoint)
screamer 73:8d28a0cb7b43 30
screamer 73:8d28a0cb7b43 31 // Power Control for Peripherals register
screamer 73:8d28a0cb7b43 32 #define PCUSB (1UL<<31)
screamer 73:8d28a0cb7b43 33
screamer 73:8d28a0cb7b43 34 // USB Clock Control register
screamer 73:8d28a0cb7b43 35 #define DEV_CLK_EN (1UL<<1)
screamer 73:8d28a0cb7b43 36 #define PORT_CLK_EN (1UL<<3)
screamer 73:8d28a0cb7b43 37 #define AHB_CLK_EN (1UL<<4)
screamer 73:8d28a0cb7b43 38
screamer 73:8d28a0cb7b43 39 // USB Clock Status register
screamer 73:8d28a0cb7b43 40 #define DEV_CLK_ON (1UL<<1)
screamer 73:8d28a0cb7b43 41 #define AHB_CLK_ON (1UL<<4)
screamer 73:8d28a0cb7b43 42
screamer 73:8d28a0cb7b43 43 // USB Device Interupt registers
screamer 73:8d28a0cb7b43 44 #define FRAME (1UL<<0)
screamer 73:8d28a0cb7b43 45 #define EP_FAST (1UL<<1)
screamer 73:8d28a0cb7b43 46 #define EP_SLOW (1UL<<2)
screamer 73:8d28a0cb7b43 47 #define DEV_STAT (1UL<<3)
screamer 73:8d28a0cb7b43 48 #define CCEMPTY (1UL<<4)
screamer 73:8d28a0cb7b43 49 #define CDFULL (1UL<<5)
screamer 73:8d28a0cb7b43 50 #define RxENDPKT (1UL<<6)
screamer 73:8d28a0cb7b43 51 #define TxENDPKT (1UL<<7)
screamer 73:8d28a0cb7b43 52 #define EP_RLZED (1UL<<8)
screamer 73:8d28a0cb7b43 53 #define ERR_INT (1UL<<9)
screamer 73:8d28a0cb7b43 54
screamer 73:8d28a0cb7b43 55 // USB Control register
screamer 73:8d28a0cb7b43 56 #define RD_EN (1<<0)
screamer 73:8d28a0cb7b43 57 #define WR_EN (1<<1)
screamer 73:8d28a0cb7b43 58 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
screamer 73:8d28a0cb7b43 59
screamer 73:8d28a0cb7b43 60 // USB Receive Packet Length register
screamer 73:8d28a0cb7b43 61 #define DV (1UL<<10)
screamer 73:8d28a0cb7b43 62 #define PKT_RDY (1UL<<11)
screamer 73:8d28a0cb7b43 63 #define PKT_LNGTH_MASK (0x3ff)
screamer 73:8d28a0cb7b43 64
screamer 73:8d28a0cb7b43 65 // Serial Interface Engine (SIE)
screamer 73:8d28a0cb7b43 66 #define SIE_WRITE (0x01)
screamer 73:8d28a0cb7b43 67 #define SIE_READ (0x02)
screamer 73:8d28a0cb7b43 68 #define SIE_COMMAND (0x05)
screamer 73:8d28a0cb7b43 69 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
screamer 73:8d28a0cb7b43 70
screamer 73:8d28a0cb7b43 71 // SIE Command codes
screamer 73:8d28a0cb7b43 72 #define SIE_CMD_SET_ADDRESS (0xD0)
screamer 73:8d28a0cb7b43 73 #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
screamer 73:8d28a0cb7b43 74 #define SIE_CMD_SET_MODE (0xF3)
screamer 73:8d28a0cb7b43 75 #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
screamer 73:8d28a0cb7b43 76 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
screamer 73:8d28a0cb7b43 77 #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
screamer 73:8d28a0cb7b43 78 #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
screamer 73:8d28a0cb7b43 79 #define SIE_CMD_GET_ERROR_CODE (0xFF)
screamer 73:8d28a0cb7b43 80 #define SIE_CMD_READ_ERROR_STATUS (0xFB)
screamer 73:8d28a0cb7b43 81
screamer 73:8d28a0cb7b43 82 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
screamer 73:8d28a0cb7b43 83 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
screamer 73:8d28a0cb7b43 84 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
screamer 73:8d28a0cb7b43 85
screamer 73:8d28a0cb7b43 86 #define SIE_CMD_CLEAR_BUFFER (0xF2)
screamer 73:8d28a0cb7b43 87 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
screamer 73:8d28a0cb7b43 88
screamer 73:8d28a0cb7b43 89 // SIE Device Status register
screamer 73:8d28a0cb7b43 90 #define SIE_DS_CON (1<<0)
screamer 73:8d28a0cb7b43 91 #define SIE_DS_CON_CH (1<<1)
screamer 73:8d28a0cb7b43 92 #define SIE_DS_SUS (1<<2)
screamer 73:8d28a0cb7b43 93 #define SIE_DS_SUS_CH (1<<3)
screamer 73:8d28a0cb7b43 94 #define SIE_DS_RST (1<<4)
screamer 73:8d28a0cb7b43 95
screamer 73:8d28a0cb7b43 96 // SIE Device Set Address register
screamer 73:8d28a0cb7b43 97 #define SIE_DSA_DEV_EN (1<<7)
screamer 73:8d28a0cb7b43 98
screamer 73:8d28a0cb7b43 99 // SIE Configue Device register
screamer 73:8d28a0cb7b43 100 #define SIE_CONF_DEVICE (1<<0)
screamer 73:8d28a0cb7b43 101
screamer 73:8d28a0cb7b43 102 // Select Endpoint register
screamer 73:8d28a0cb7b43 103 #define SIE_SE_FE (1<<0)
screamer 73:8d28a0cb7b43 104 #define SIE_SE_ST (1<<1)
screamer 73:8d28a0cb7b43 105 #define SIE_SE_STP (1<<2)
screamer 73:8d28a0cb7b43 106 #define SIE_SE_PO (1<<3)
screamer 73:8d28a0cb7b43 107 #define SIE_SE_EPN (1<<4)
screamer 73:8d28a0cb7b43 108 #define SIE_SE_B_1_FULL (1<<5)
screamer 73:8d28a0cb7b43 109 #define SIE_SE_B_2_FULL (1<<6)
screamer 73:8d28a0cb7b43 110
screamer 73:8d28a0cb7b43 111 // Set Endpoint Status command
screamer 73:8d28a0cb7b43 112 #define SIE_SES_ST (1<<0)
screamer 73:8d28a0cb7b43 113 #define SIE_SES_DA (1<<5)
screamer 73:8d28a0cb7b43 114 #define SIE_SES_RF_MO (1<<6)
screamer 73:8d28a0cb7b43 115 #define SIE_SES_CND_ST (1<<7)
screamer 73:8d28a0cb7b43 116
screamer 73:8d28a0cb7b43 117
screamer 73:8d28a0cb7b43 118 USBHAL * USBHAL::instance;
screamer 73:8d28a0cb7b43 119
screamer 73:8d28a0cb7b43 120 static volatile int epComplete;
screamer 73:8d28a0cb7b43 121 static uint32_t endpointStallState;
screamer 73:8d28a0cb7b43 122
screamer 73:8d28a0cb7b43 123 static void SIECommand(uint32_t command) {
screamer 73:8d28a0cb7b43 124 // The command phase of a SIE transaction
screamer 73:8d28a0cb7b43 125 LPC_USB->DevIntClr = CCEMPTY;
screamer 73:8d28a0cb7b43 126 LPC_USB->CmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
screamer 73:8d28a0cb7b43 127 while (!(LPC_USB->DevIntSt & CCEMPTY));
screamer 73:8d28a0cb7b43 128 }
screamer 73:8d28a0cb7b43 129
screamer 73:8d28a0cb7b43 130 static void SIEWriteData(uint8_t data) {
screamer 73:8d28a0cb7b43 131 // The data write phase of a SIE transaction
screamer 73:8d28a0cb7b43 132 LPC_USB->DevIntClr = CCEMPTY;
screamer 73:8d28a0cb7b43 133 LPC_USB->CmdCode = SIE_CMD_CODE(SIE_WRITE, data);
screamer 73:8d28a0cb7b43 134 while (!(LPC_USB->DevIntSt & CCEMPTY));
screamer 73:8d28a0cb7b43 135 }
screamer 73:8d28a0cb7b43 136
screamer 73:8d28a0cb7b43 137 static uint8_t SIEReadData(uint32_t command) {
screamer 73:8d28a0cb7b43 138 // The data read phase of a SIE transaction
screamer 73:8d28a0cb7b43 139 LPC_USB->DevIntClr = CDFULL;
screamer 73:8d28a0cb7b43 140 LPC_USB->CmdCode = SIE_CMD_CODE(SIE_READ, command);
screamer 73:8d28a0cb7b43 141 while (!(LPC_USB->DevIntSt & CDFULL));
screamer 73:8d28a0cb7b43 142 return (uint8_t)LPC_USB->CmdData;
screamer 73:8d28a0cb7b43 143 }
screamer 73:8d28a0cb7b43 144
screamer 73:8d28a0cb7b43 145 static void SIEsetDeviceStatus(uint8_t status) {
screamer 73:8d28a0cb7b43 146 // Write SIE device status register
screamer 73:8d28a0cb7b43 147 SIECommand(SIE_CMD_SET_DEVICE_STATUS);
screamer 73:8d28a0cb7b43 148 SIEWriteData(status);
screamer 73:8d28a0cb7b43 149 }
screamer 73:8d28a0cb7b43 150
screamer 73:8d28a0cb7b43 151 static uint8_t SIEgetDeviceStatus(void) {
screamer 73:8d28a0cb7b43 152 // Read SIE device status register
screamer 73:8d28a0cb7b43 153 SIECommand(SIE_CMD_GET_DEVICE_STATUS);
screamer 73:8d28a0cb7b43 154 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
screamer 73:8d28a0cb7b43 155 }
screamer 73:8d28a0cb7b43 156
screamer 73:8d28a0cb7b43 157 void SIEsetAddress(uint8_t address) {
screamer 73:8d28a0cb7b43 158 // Write SIE device address register
screamer 73:8d28a0cb7b43 159 SIECommand(SIE_CMD_SET_ADDRESS);
screamer 73:8d28a0cb7b43 160 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
screamer 73:8d28a0cb7b43 161 }
screamer 73:8d28a0cb7b43 162
screamer 73:8d28a0cb7b43 163 static uint8_t SIEselectEndpoint(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 164 // SIE select endpoint command
screamer 73:8d28a0cb7b43 165 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
screamer 73:8d28a0cb7b43 166 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
screamer 73:8d28a0cb7b43 167 }
screamer 73:8d28a0cb7b43 168
screamer 73:8d28a0cb7b43 169 static uint8_t SIEclearBuffer(void) {
screamer 73:8d28a0cb7b43 170 // SIE clear buffer command
screamer 73:8d28a0cb7b43 171 SIECommand(SIE_CMD_CLEAR_BUFFER);
screamer 73:8d28a0cb7b43 172 return SIEReadData(SIE_CMD_CLEAR_BUFFER);
screamer 73:8d28a0cb7b43 173 }
screamer 73:8d28a0cb7b43 174
screamer 73:8d28a0cb7b43 175 static void SIEvalidateBuffer(void) {
screamer 73:8d28a0cb7b43 176 // SIE validate buffer command
screamer 73:8d28a0cb7b43 177 SIECommand(SIE_CMD_VALIDATE_BUFFER);
screamer 73:8d28a0cb7b43 178 }
screamer 73:8d28a0cb7b43 179
screamer 73:8d28a0cb7b43 180 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
screamer 73:8d28a0cb7b43 181 // SIE set endpoint status command
screamer 73:8d28a0cb7b43 182 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
screamer 73:8d28a0cb7b43 183 SIEWriteData(status);
screamer 73:8d28a0cb7b43 184 }
screamer 73:8d28a0cb7b43 185
screamer 73:8d28a0cb7b43 186 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
screamer 73:8d28a0cb7b43 187 static uint16_t SIEgetFrameNumber(void) {
screamer 73:8d28a0cb7b43 188 // Read current frame number
screamer 73:8d28a0cb7b43 189 uint16_t lowByte;
screamer 73:8d28a0cb7b43 190 uint16_t highByte;
screamer 73:8d28a0cb7b43 191
screamer 73:8d28a0cb7b43 192 SIECommand(SIE_CMD_READ_FRAME_NUMBER);
screamer 73:8d28a0cb7b43 193 lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
screamer 73:8d28a0cb7b43 194 highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
screamer 73:8d28a0cb7b43 195
screamer 73:8d28a0cb7b43 196 return (highByte << 8) | lowByte;
screamer 73:8d28a0cb7b43 197 }
screamer 73:8d28a0cb7b43 198
screamer 73:8d28a0cb7b43 199 static void SIEconfigureDevice(void) {
screamer 73:8d28a0cb7b43 200 // SIE Configure device command
screamer 73:8d28a0cb7b43 201 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
screamer 73:8d28a0cb7b43 202 SIEWriteData(SIE_CONF_DEVICE);
screamer 73:8d28a0cb7b43 203 }
screamer 73:8d28a0cb7b43 204
screamer 73:8d28a0cb7b43 205 static void SIEunconfigureDevice(void) {
screamer 73:8d28a0cb7b43 206 // SIE Configure device command
screamer 73:8d28a0cb7b43 207 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
screamer 73:8d28a0cb7b43 208 SIEWriteData(0);
screamer 73:8d28a0cb7b43 209 }
screamer 73:8d28a0cb7b43 210
screamer 73:8d28a0cb7b43 211 static void SIEconnect(void) {
screamer 73:8d28a0cb7b43 212 // Connect USB device
screamer 73:8d28a0cb7b43 213 uint8_t status = SIEgetDeviceStatus();
screamer 73:8d28a0cb7b43 214 SIEsetDeviceStatus(status | SIE_DS_CON);
screamer 73:8d28a0cb7b43 215 }
screamer 73:8d28a0cb7b43 216
screamer 73:8d28a0cb7b43 217
screamer 73:8d28a0cb7b43 218 static void SIEdisconnect(void) {
screamer 73:8d28a0cb7b43 219 // Disconnect USB device
screamer 73:8d28a0cb7b43 220 uint8_t status = SIEgetDeviceStatus();
screamer 73:8d28a0cb7b43 221 SIEsetDeviceStatus(status & ~SIE_DS_CON);
screamer 73:8d28a0cb7b43 222 }
screamer 73:8d28a0cb7b43 223
screamer 73:8d28a0cb7b43 224
screamer 73:8d28a0cb7b43 225 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 226 // Implemented using using EP_INT_CLR.
screamer 73:8d28a0cb7b43 227 LPC_USB->EpIntClr = EP(endpoint);
screamer 73:8d28a0cb7b43 228 while (!(LPC_USB->DevIntSt & CDFULL));
screamer 73:8d28a0cb7b43 229 return (uint8_t)LPC_USB->CmdData;
screamer 73:8d28a0cb7b43 230 }
screamer 73:8d28a0cb7b43 231
screamer 73:8d28a0cb7b43 232
screamer 73:8d28a0cb7b43 233 static void enableEndpointEvent(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 234 // Enable an endpoint interrupt
screamer 73:8d28a0cb7b43 235 LPC_USB->EpIntEn |= EP(endpoint);
screamer 73:8d28a0cb7b43 236 }
screamer 73:8d28a0cb7b43 237
screamer 73:8d28a0cb7b43 238 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
screamer 73:8d28a0cb7b43 239 static void disableEndpointEvent(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 240 // Disable an endpoint interrupt
screamer 73:8d28a0cb7b43 241 LPC_USB->EpIntEn &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 242 }
screamer 73:8d28a0cb7b43 243
screamer 73:8d28a0cb7b43 244 static volatile uint32_t __attribute__((used)) dummyRead;
screamer 73:8d28a0cb7b43 245 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
screamer 73:8d28a0cb7b43 246 // Read from an OUT endpoint
screamer 73:8d28a0cb7b43 247 uint32_t size;
screamer 73:8d28a0cb7b43 248 uint32_t i;
screamer 73:8d28a0cb7b43 249 uint32_t data = 0;
screamer 73:8d28a0cb7b43 250 uint8_t offset;
screamer 73:8d28a0cb7b43 251
screamer 73:8d28a0cb7b43 252 LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | RD_EN;
screamer 73:8d28a0cb7b43 253 while (!(LPC_USB->RxPLen & PKT_RDY));
screamer 73:8d28a0cb7b43 254
screamer 73:8d28a0cb7b43 255 size = LPC_USB->RxPLen & PKT_LNGTH_MASK;
screamer 73:8d28a0cb7b43 256
screamer 73:8d28a0cb7b43 257 offset = 0;
screamer 73:8d28a0cb7b43 258
screamer 73:8d28a0cb7b43 259 if (size > 0) {
screamer 73:8d28a0cb7b43 260 for (i=0; i<size; i++) {
screamer 73:8d28a0cb7b43 261 if (offset==0) {
screamer 73:8d28a0cb7b43 262 // Fetch up to four bytes of data as a word
screamer 73:8d28a0cb7b43 263 data = LPC_USB->RxData;
screamer 73:8d28a0cb7b43 264 }
screamer 73:8d28a0cb7b43 265
screamer 73:8d28a0cb7b43 266 // extract a byte
screamer 73:8d28a0cb7b43 267 *buffer = (data>>offset) & 0xff;
screamer 73:8d28a0cb7b43 268 buffer++;
screamer 73:8d28a0cb7b43 269
screamer 73:8d28a0cb7b43 270 // move on to the next byte
screamer 73:8d28a0cb7b43 271 offset = (offset + 8) % 32;
screamer 73:8d28a0cb7b43 272 }
screamer 73:8d28a0cb7b43 273 } else {
screamer 73:8d28a0cb7b43 274 dummyRead = LPC_USB->RxData;
screamer 73:8d28a0cb7b43 275 }
screamer 73:8d28a0cb7b43 276
screamer 73:8d28a0cb7b43 277 LPC_USB->Ctrl = 0;
screamer 73:8d28a0cb7b43 278
screamer 73:8d28a0cb7b43 279 if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
screamer 73:8d28a0cb7b43 280 SIEselectEndpoint(endpoint);
screamer 73:8d28a0cb7b43 281 SIEclearBuffer();
screamer 73:8d28a0cb7b43 282 }
screamer 73:8d28a0cb7b43 283
screamer 73:8d28a0cb7b43 284 return size;
screamer 73:8d28a0cb7b43 285 }
screamer 73:8d28a0cb7b43 286
screamer 73:8d28a0cb7b43 287 static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
screamer 73:8d28a0cb7b43 288 // Write to an IN endpoint
screamer 73:8d28a0cb7b43 289 uint32_t temp, data;
screamer 73:8d28a0cb7b43 290 uint8_t offset;
screamer 73:8d28a0cb7b43 291
screamer 73:8d28a0cb7b43 292 LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | WR_EN;
screamer 73:8d28a0cb7b43 293
screamer 73:8d28a0cb7b43 294 LPC_USB->TxPLen = size;
screamer 73:8d28a0cb7b43 295 offset = 0;
screamer 73:8d28a0cb7b43 296 data = 0;
screamer 73:8d28a0cb7b43 297
screamer 73:8d28a0cb7b43 298 if (size>0) {
screamer 73:8d28a0cb7b43 299 do {
screamer 73:8d28a0cb7b43 300 // Fetch next data byte into a word-sized temporary variable
screamer 73:8d28a0cb7b43 301 temp = *buffer++;
screamer 73:8d28a0cb7b43 302
screamer 73:8d28a0cb7b43 303 // Add to current data word
screamer 73:8d28a0cb7b43 304 temp = temp << offset;
screamer 73:8d28a0cb7b43 305 data = data | temp;
screamer 73:8d28a0cb7b43 306
screamer 73:8d28a0cb7b43 307 // move on to the next byte
screamer 73:8d28a0cb7b43 308 offset = (offset + 8) % 32;
screamer 73:8d28a0cb7b43 309 size--;
screamer 73:8d28a0cb7b43 310
screamer 73:8d28a0cb7b43 311 if ((offset==0) || (size==0)) {
screamer 73:8d28a0cb7b43 312 // Write the word to the endpoint
screamer 73:8d28a0cb7b43 313 LPC_USB->TxData = data;
screamer 73:8d28a0cb7b43 314 data = 0;
screamer 73:8d28a0cb7b43 315 }
screamer 73:8d28a0cb7b43 316 } while (size>0);
screamer 73:8d28a0cb7b43 317 } else {
screamer 73:8d28a0cb7b43 318 LPC_USB->TxData = 0;
screamer 73:8d28a0cb7b43 319 }
screamer 73:8d28a0cb7b43 320
screamer 73:8d28a0cb7b43 321 // Clear WR_EN to cover zero length packet case
screamer 73:8d28a0cb7b43 322 LPC_USB->Ctrl=0;
screamer 73:8d28a0cb7b43 323
screamer 73:8d28a0cb7b43 324 SIEselectEndpoint(endpoint);
screamer 73:8d28a0cb7b43 325 SIEvalidateBuffer();
screamer 73:8d28a0cb7b43 326 }
screamer 73:8d28a0cb7b43 327
screamer 73:8d28a0cb7b43 328 USBHAL::USBHAL(void) {
screamer 73:8d28a0cb7b43 329 // Disable IRQ
screamer 73:8d28a0cb7b43 330 NVIC_DisableIRQ(USB_IRQn);
screamer 73:8d28a0cb7b43 331
screamer 73:8d28a0cb7b43 332 // fill in callback array
screamer 73:8d28a0cb7b43 333 epCallback[0] = &USBHAL::EP1_OUT_callback;
screamer 73:8d28a0cb7b43 334 epCallback[1] = &USBHAL::EP1_IN_callback;
screamer 73:8d28a0cb7b43 335 epCallback[2] = &USBHAL::EP2_OUT_callback;
screamer 73:8d28a0cb7b43 336 epCallback[3] = &USBHAL::EP2_IN_callback;
screamer 73:8d28a0cb7b43 337 epCallback[4] = &USBHAL::EP3_OUT_callback;
screamer 73:8d28a0cb7b43 338 epCallback[5] = &USBHAL::EP3_IN_callback;
screamer 73:8d28a0cb7b43 339 epCallback[6] = &USBHAL::EP4_OUT_callback;
screamer 73:8d28a0cb7b43 340 epCallback[7] = &USBHAL::EP4_IN_callback;
screamer 73:8d28a0cb7b43 341 epCallback[8] = &USBHAL::EP5_OUT_callback;
screamer 73:8d28a0cb7b43 342 epCallback[9] = &USBHAL::EP5_IN_callback;
screamer 73:8d28a0cb7b43 343 epCallback[10] = &USBHAL::EP6_OUT_callback;
screamer 73:8d28a0cb7b43 344 epCallback[11] = &USBHAL::EP6_IN_callback;
screamer 73:8d28a0cb7b43 345 epCallback[12] = &USBHAL::EP7_OUT_callback;
screamer 73:8d28a0cb7b43 346 epCallback[13] = &USBHAL::EP7_IN_callback;
screamer 73:8d28a0cb7b43 347 epCallback[14] = &USBHAL::EP8_OUT_callback;
screamer 73:8d28a0cb7b43 348 epCallback[15] = &USBHAL::EP8_IN_callback;
screamer 73:8d28a0cb7b43 349 epCallback[16] = &USBHAL::EP9_OUT_callback;
screamer 73:8d28a0cb7b43 350 epCallback[17] = &USBHAL::EP9_IN_callback;
screamer 73:8d28a0cb7b43 351 epCallback[18] = &USBHAL::EP10_OUT_callback;
screamer 73:8d28a0cb7b43 352 epCallback[19] = &USBHAL::EP10_IN_callback;
screamer 73:8d28a0cb7b43 353 epCallback[20] = &USBHAL::EP11_OUT_callback;
screamer 73:8d28a0cb7b43 354 epCallback[21] = &USBHAL::EP11_IN_callback;
screamer 73:8d28a0cb7b43 355 epCallback[22] = &USBHAL::EP12_OUT_callback;
screamer 73:8d28a0cb7b43 356 epCallback[23] = &USBHAL::EP12_IN_callback;
screamer 73:8d28a0cb7b43 357 epCallback[24] = &USBHAL::EP13_OUT_callback;
screamer 73:8d28a0cb7b43 358 epCallback[25] = &USBHAL::EP13_IN_callback;
screamer 73:8d28a0cb7b43 359 epCallback[26] = &USBHAL::EP14_OUT_callback;
screamer 73:8d28a0cb7b43 360 epCallback[27] = &USBHAL::EP14_IN_callback;
screamer 73:8d28a0cb7b43 361 epCallback[28] = &USBHAL::EP15_OUT_callback;
screamer 73:8d28a0cb7b43 362 epCallback[29] = &USBHAL::EP15_IN_callback;
screamer 73:8d28a0cb7b43 363
screamer 73:8d28a0cb7b43 364 // Enable power to USB device controller
screamer 73:8d28a0cb7b43 365 LPC_SC->PCONP |= PCUSB;
screamer 73:8d28a0cb7b43 366
screamer 73:8d28a0cb7b43 367 // Enable USB clocks
screamer 73:8d28a0cb7b43 368 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
screamer 73:8d28a0cb7b43 369 while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
screamer 73:8d28a0cb7b43 370
screamer 73:8d28a0cb7b43 371 // Select port USB2
screamer 73:8d28a0cb7b43 372 LPC_USB->StCtrl |= 3;
screamer 73:8d28a0cb7b43 373
screamer 73:8d28a0cb7b43 374
screamer 73:8d28a0cb7b43 375 // Configure pin P0.31 to be USB2
screamer 73:8d28a0cb7b43 376 LPC_IOCON->P0_31 &= ~0x07;
screamer 73:8d28a0cb7b43 377 LPC_IOCON->P0_31 |= 0x01;
screamer 73:8d28a0cb7b43 378
screamer 73:8d28a0cb7b43 379 // Disconnect USB device
screamer 73:8d28a0cb7b43 380 SIEdisconnect();
screamer 73:8d28a0cb7b43 381
screamer 73:8d28a0cb7b43 382 // Configure pin P0.14 to be Connect
screamer 73:8d28a0cb7b43 383 LPC_IOCON->P0_14 &= ~0x07;
screamer 73:8d28a0cb7b43 384 LPC_IOCON->P0_14 |= 0x03;
screamer 73:8d28a0cb7b43 385
screamer 73:8d28a0cb7b43 386 // Connect must be low for at least 2.5uS
screamer 73:8d28a0cb7b43 387 wait(0.3);
screamer 73:8d28a0cb7b43 388
screamer 73:8d28a0cb7b43 389 // Set the maximum packet size for the control endpoints
screamer 73:8d28a0cb7b43 390 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
screamer 73:8d28a0cb7b43 391 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
screamer 73:8d28a0cb7b43 392
screamer 73:8d28a0cb7b43 393 // Attach IRQ
screamer 73:8d28a0cb7b43 394 instance = this;
screamer 73:8d28a0cb7b43 395 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
screamer 73:8d28a0cb7b43 396
screamer 73:8d28a0cb7b43 397 // Enable interrupts for device events and EP0
screamer 73:8d28a0cb7b43 398 LPC_USB->DevIntEn = EP_SLOW | DEV_STAT | FRAME;
screamer 73:8d28a0cb7b43 399 enableEndpointEvent(EP0IN);
screamer 73:8d28a0cb7b43 400 enableEndpointEvent(EP0OUT);
screamer 73:8d28a0cb7b43 401 }
screamer 73:8d28a0cb7b43 402
screamer 73:8d28a0cb7b43 403 USBHAL::~USBHAL(void) {
screamer 73:8d28a0cb7b43 404 // Ensure device disconnected
screamer 73:8d28a0cb7b43 405 SIEdisconnect();
screamer 73:8d28a0cb7b43 406 // Disable USB interrupts
screamer 73:8d28a0cb7b43 407 NVIC_DisableIRQ(USB_IRQn);
screamer 73:8d28a0cb7b43 408 }
screamer 73:8d28a0cb7b43 409
screamer 73:8d28a0cb7b43 410 void USBHAL::connect(void) {
screamer 73:8d28a0cb7b43 411 NVIC_EnableIRQ(USB_IRQn);
screamer 73:8d28a0cb7b43 412 // Connect USB device
screamer 73:8d28a0cb7b43 413 SIEconnect();
screamer 73:8d28a0cb7b43 414 }
screamer 73:8d28a0cb7b43 415
screamer 73:8d28a0cb7b43 416 void USBHAL::disconnect(void) {
screamer 73:8d28a0cb7b43 417 NVIC_DisableIRQ(USB_IRQn);
screamer 73:8d28a0cb7b43 418 // Disconnect USB device
screamer 73:8d28a0cb7b43 419 SIEdisconnect();
screamer 73:8d28a0cb7b43 420 }
screamer 73:8d28a0cb7b43 421
screamer 73:8d28a0cb7b43 422 void USBHAL::configureDevice(void) {
screamer 73:8d28a0cb7b43 423 SIEconfigureDevice();
screamer 73:8d28a0cb7b43 424 }
screamer 73:8d28a0cb7b43 425
screamer 73:8d28a0cb7b43 426 void USBHAL::unconfigureDevice(void) {
screamer 73:8d28a0cb7b43 427 SIEunconfigureDevice();
screamer 73:8d28a0cb7b43 428 }
screamer 73:8d28a0cb7b43 429
screamer 73:8d28a0cb7b43 430 void USBHAL::setAddress(uint8_t address) {
screamer 73:8d28a0cb7b43 431 SIEsetAddress(address);
screamer 73:8d28a0cb7b43 432 }
screamer 73:8d28a0cb7b43 433
screamer 73:8d28a0cb7b43 434 void USBHAL::EP0setup(uint8_t *buffer) {
screamer 73:8d28a0cb7b43 435 endpointReadcore(EP0OUT, buffer);
screamer 73:8d28a0cb7b43 436 }
screamer 73:8d28a0cb7b43 437
screamer 73:8d28a0cb7b43 438 void USBHAL::EP0read(void) {
screamer 73:8d28a0cb7b43 439 // Not required
screamer 73:8d28a0cb7b43 440 }
screamer 73:8d28a0cb7b43 441
screamer 73:8d28a0cb7b43 442 void USBHAL::EP0readStage(void) {
screamer 73:8d28a0cb7b43 443 // Not required
screamer 73:8d28a0cb7b43 444 }
screamer 73:8d28a0cb7b43 445
screamer 73:8d28a0cb7b43 446 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
screamer 73:8d28a0cb7b43 447 return endpointReadcore(EP0OUT, buffer);
screamer 73:8d28a0cb7b43 448 }
screamer 73:8d28a0cb7b43 449
screamer 73:8d28a0cb7b43 450 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
screamer 73:8d28a0cb7b43 451 endpointWritecore(EP0IN, buffer, size);
screamer 73:8d28a0cb7b43 452 }
screamer 73:8d28a0cb7b43 453
screamer 73:8d28a0cb7b43 454 void USBHAL::EP0getWriteResult(void) {
screamer 73:8d28a0cb7b43 455 // Not required
screamer 73:8d28a0cb7b43 456 }
screamer 73:8d28a0cb7b43 457
screamer 73:8d28a0cb7b43 458 void USBHAL::EP0stall(void) {
screamer 73:8d28a0cb7b43 459 // This will stall both control endpoints
screamer 73:8d28a0cb7b43 460 stallEndpoint(EP0OUT);
screamer 73:8d28a0cb7b43 461 }
screamer 73:8d28a0cb7b43 462
screamer 73:8d28a0cb7b43 463 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
screamer 73:8d28a0cb7b43 464 return EP_PENDING;
screamer 73:8d28a0cb7b43 465 }
screamer 73:8d28a0cb7b43 466
screamer 73:8d28a0cb7b43 467 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
screamer 73:8d28a0cb7b43 468
screamer 73:8d28a0cb7b43 469 //for isochronous endpoint, we don't wait an interrupt
screamer 73:8d28a0cb7b43 470 if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
screamer 73:8d28a0cb7b43 471 if (!(epComplete & EP(endpoint)))
screamer 73:8d28a0cb7b43 472 return EP_PENDING;
screamer 73:8d28a0cb7b43 473 }
screamer 73:8d28a0cb7b43 474
screamer 73:8d28a0cb7b43 475 *bytesRead = endpointReadcore(endpoint, buffer);
screamer 73:8d28a0cb7b43 476 epComplete &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 477 return EP_COMPLETED;
screamer 73:8d28a0cb7b43 478 }
screamer 73:8d28a0cb7b43 479
screamer 73:8d28a0cb7b43 480 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
screamer 73:8d28a0cb7b43 481 if (getEndpointStallState(endpoint)) {
screamer 73:8d28a0cb7b43 482 return EP_STALLED;
screamer 73:8d28a0cb7b43 483 }
screamer 73:8d28a0cb7b43 484
screamer 73:8d28a0cb7b43 485 epComplete &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 486
screamer 73:8d28a0cb7b43 487 endpointWritecore(endpoint, data, size);
screamer 73:8d28a0cb7b43 488 return EP_PENDING;
screamer 73:8d28a0cb7b43 489 }
screamer 73:8d28a0cb7b43 490
screamer 73:8d28a0cb7b43 491 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 492 if (epComplete & EP(endpoint)) {
screamer 73:8d28a0cb7b43 493 epComplete &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 494 return EP_COMPLETED;
screamer 73:8d28a0cb7b43 495 }
screamer 73:8d28a0cb7b43 496
screamer 73:8d28a0cb7b43 497 return EP_PENDING;
screamer 73:8d28a0cb7b43 498 }
screamer 73:8d28a0cb7b43 499
screamer 73:8d28a0cb7b43 500 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
screamer 73:8d28a0cb7b43 501 // Realise an endpoint
screamer 73:8d28a0cb7b43 502 LPC_USB->DevIntClr = EP_RLZED;
screamer 73:8d28a0cb7b43 503 LPC_USB->ReEp |= EP(endpoint);
screamer 73:8d28a0cb7b43 504 LPC_USB->EpInd = endpoint;
screamer 73:8d28a0cb7b43 505 LPC_USB->MaxPSize = maxPacket;
screamer 73:8d28a0cb7b43 506
screamer 73:8d28a0cb7b43 507 while (!(LPC_USB->DevIntSt & EP_RLZED));
screamer 73:8d28a0cb7b43 508 LPC_USB->DevIntClr = EP_RLZED;
screamer 73:8d28a0cb7b43 509
screamer 73:8d28a0cb7b43 510 // Clear stall state
screamer 73:8d28a0cb7b43 511 endpointStallState &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 512
screamer 73:8d28a0cb7b43 513 enableEndpointEvent(endpoint);
screamer 73:8d28a0cb7b43 514 return true;
screamer 73:8d28a0cb7b43 515 }
screamer 73:8d28a0cb7b43 516
screamer 73:8d28a0cb7b43 517 void USBHAL::stallEndpoint(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 518 // Stall an endpoint
screamer 73:8d28a0cb7b43 519 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
screamer 73:8d28a0cb7b43 520 // Conditionally stall both control endpoints
screamer 73:8d28a0cb7b43 521 SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
screamer 73:8d28a0cb7b43 522 } else {
screamer 73:8d28a0cb7b43 523 SIEsetEndpointStatus(endpoint, SIE_SES_ST);
screamer 73:8d28a0cb7b43 524
screamer 73:8d28a0cb7b43 525 // Update stall state
screamer 73:8d28a0cb7b43 526 endpointStallState |= EP(endpoint);
screamer 73:8d28a0cb7b43 527 }
screamer 73:8d28a0cb7b43 528 }
screamer 73:8d28a0cb7b43 529
screamer 73:8d28a0cb7b43 530 void USBHAL::unstallEndpoint(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 531 // Unstall an endpoint. The endpoint will also be reinitialised
screamer 73:8d28a0cb7b43 532 SIEsetEndpointStatus(endpoint, 0);
screamer 73:8d28a0cb7b43 533
screamer 73:8d28a0cb7b43 534 // Update stall state
screamer 73:8d28a0cb7b43 535 endpointStallState &= ~EP(endpoint);
screamer 73:8d28a0cb7b43 536 }
screamer 73:8d28a0cb7b43 537
screamer 73:8d28a0cb7b43 538 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
screamer 73:8d28a0cb7b43 539 // Returns true if endpoint stalled
screamer 73:8d28a0cb7b43 540 return endpointStallState & EP(endpoint);
screamer 73:8d28a0cb7b43 541 }
screamer 73:8d28a0cb7b43 542
screamer 73:8d28a0cb7b43 543 void USBHAL::remoteWakeup(void) {
screamer 73:8d28a0cb7b43 544 // Remote wakeup
screamer 73:8d28a0cb7b43 545 uint8_t status;
screamer 73:8d28a0cb7b43 546
screamer 73:8d28a0cb7b43 547 // Enable USB clocks
screamer 73:8d28a0cb7b43 548 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
screamer 73:8d28a0cb7b43 549 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
screamer 73:8d28a0cb7b43 550
screamer 73:8d28a0cb7b43 551 status = SIEgetDeviceStatus();
screamer 73:8d28a0cb7b43 552 SIEsetDeviceStatus(status & ~SIE_DS_SUS);
screamer 73:8d28a0cb7b43 553 }
screamer 73:8d28a0cb7b43 554
screamer 73:8d28a0cb7b43 555 void USBHAL::_usbisr(void) {
screamer 73:8d28a0cb7b43 556 instance->usbisr();
screamer 73:8d28a0cb7b43 557 }
screamer 73:8d28a0cb7b43 558
screamer 73:8d28a0cb7b43 559
screamer 73:8d28a0cb7b43 560 void USBHAL::usbisr(void) {
screamer 73:8d28a0cb7b43 561 uint8_t devStat;
screamer 73:8d28a0cb7b43 562
screamer 73:8d28a0cb7b43 563 if (LPC_USB->DevIntSt & FRAME) {
screamer 73:8d28a0cb7b43 564 // Start of frame event
screamer 73:8d28a0cb7b43 565 SOF(SIEgetFrameNumber());
screamer 73:8d28a0cb7b43 566 // Clear interrupt status flag
screamer 73:8d28a0cb7b43 567 LPC_USB->DevIntClr = FRAME;
screamer 73:8d28a0cb7b43 568 }
screamer 73:8d28a0cb7b43 569
screamer 73:8d28a0cb7b43 570 if (LPC_USB->DevIntSt & DEV_STAT) {
screamer 73:8d28a0cb7b43 571 // Device Status interrupt
screamer 73:8d28a0cb7b43 572 // Must clear the interrupt status flag before reading the device status from the SIE
screamer 73:8d28a0cb7b43 573 LPC_USB->DevIntClr = DEV_STAT;
screamer 73:8d28a0cb7b43 574
screamer 73:8d28a0cb7b43 575 // Read device status from SIE
screamer 73:8d28a0cb7b43 576 devStat = SIEgetDeviceStatus();
screamer 73:8d28a0cb7b43 577 //printf("devStat: %d\r\n", devStat);
screamer 73:8d28a0cb7b43 578
screamer 73:8d28a0cb7b43 579 if (devStat & SIE_DS_SUS_CH) {
screamer 73:8d28a0cb7b43 580 // Suspend status changed
screamer 73:8d28a0cb7b43 581 if((devStat & SIE_DS_SUS) != 0) {
screamer 73:8d28a0cb7b43 582 suspendStateChanged(0);
screamer 73:8d28a0cb7b43 583 }
screamer 73:8d28a0cb7b43 584 }
screamer 73:8d28a0cb7b43 585
screamer 73:8d28a0cb7b43 586 if (devStat & SIE_DS_RST) {
screamer 73:8d28a0cb7b43 587 // Bus reset
screamer 73:8d28a0cb7b43 588 if((devStat & SIE_DS_SUS) == 0) {
screamer 73:8d28a0cb7b43 589 suspendStateChanged(1);
screamer 73:8d28a0cb7b43 590 }
screamer 73:8d28a0cb7b43 591 busReset();
screamer 73:8d28a0cb7b43 592 }
screamer 73:8d28a0cb7b43 593 }
screamer 73:8d28a0cb7b43 594
screamer 73:8d28a0cb7b43 595 if (LPC_USB->DevIntSt & EP_SLOW) {
screamer 73:8d28a0cb7b43 596 // (Slow) Endpoint Interrupt
screamer 73:8d28a0cb7b43 597
screamer 73:8d28a0cb7b43 598 // Process each endpoint interrupt
screamer 73:8d28a0cb7b43 599 if (LPC_USB->EpIntSt & EP(EP0OUT)) {
screamer 73:8d28a0cb7b43 600 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
screamer 73:8d28a0cb7b43 601 // this is a setup packet
screamer 73:8d28a0cb7b43 602 EP0setupCallback();
screamer 73:8d28a0cb7b43 603 } else {
screamer 73:8d28a0cb7b43 604 EP0out();
screamer 73:8d28a0cb7b43 605 }
screamer 73:8d28a0cb7b43 606 LPC_USB->DevIntClr = EP_SLOW;
screamer 73:8d28a0cb7b43 607 }
screamer 73:8d28a0cb7b43 608
screamer 73:8d28a0cb7b43 609 if (LPC_USB->EpIntSt & EP(EP0IN)) {
screamer 73:8d28a0cb7b43 610 selectEndpointClearInterrupt(EP0IN);
screamer 73:8d28a0cb7b43 611 LPC_USB->DevIntClr = EP_SLOW;
screamer 73:8d28a0cb7b43 612 EP0in();
screamer 73:8d28a0cb7b43 613 }
screamer 73:8d28a0cb7b43 614
screamer 73:8d28a0cb7b43 615 for (uint8_t num = 2; num < 16*2; num++) {
screamer 73:8d28a0cb7b43 616 if (LPC_USB->EpIntSt & EP(num)) {
screamer 73:8d28a0cb7b43 617 selectEndpointClearInterrupt(num);
screamer 73:8d28a0cb7b43 618 epComplete |= EP(num);
screamer 73:8d28a0cb7b43 619 LPC_USB->DevIntClr = EP_SLOW;
screamer 73:8d28a0cb7b43 620 if ((instance->*(epCallback[num - 2]))()) {
screamer 73:8d28a0cb7b43 621 epComplete &= ~EP(num);
screamer 73:8d28a0cb7b43 622 }
screamer 73:8d28a0cb7b43 623 }
screamer 73:8d28a0cb7b43 624 }
screamer 73:8d28a0cb7b43 625 }
screamer 73:8d28a0cb7b43 626 }
screamer 73:8d28a0cb7b43 627
screamer 73:8d28a0cb7b43 628 #endif