Acts a USB HID keyboard, and socket server. Forwards characters from TCP ip socket to keyboard

Dependencies:   mbed EthernetNetIf

Committer:
henryeherman
Date:
Tue Aug 02 02:58:40 2011 +0000
Revision:
0:beb124b81ef5
Just barley work

Who changed what in which revision?

UserRevisionLine numberNew contents of line
henryeherman 0:beb124b81ef5 1 /* usbdc.cpp */
henryeherman 0:beb124b81ef5 2 /* USB device controller */
henryeherman 0:beb124b81ef5 3 /* Copyright (c) Phil Wright 2008 */
henryeherman 0:beb124b81ef5 4
henryeherman 0:beb124b81ef5 5 #include "mbed.h"
henryeherman 0:beb124b81ef5 6 #include "usbdc.h"
henryeherman 0:beb124b81ef5 7 #include "cmsis.h"
henryeherman 0:beb124b81ef5 8
henryeherman 0:beb124b81ef5 9 #ifdef TARGET_LPC2368
henryeherman 0:beb124b81ef5 10 #undef LPC_USB_BASE
henryeherman 0:beb124b81ef5 11 #define LPC_USB_BASE (0xFFE0C000) /* TODO */
henryeherman 0:beb124b81ef5 12 #endif
henryeherman 0:beb124b81ef5 13
henryeherman 0:beb124b81ef5 14 /* Power Control for Peripherals register */
henryeherman 0:beb124b81ef5 15 #define PCUSB ((unsigned long)1<<31)
henryeherman 0:beb124b81ef5 16
henryeherman 0:beb124b81ef5 17 /* USB Clock Control register */
henryeherman 0:beb124b81ef5 18 #define DEV_CLK_EN ((unsigned long)1<<1)
henryeherman 0:beb124b81ef5 19 #define AHB_CLK_EN ((unsigned long)1<<4)
henryeherman 0:beb124b81ef5 20
henryeherman 0:beb124b81ef5 21 /* USB Clock Status register */
henryeherman 0:beb124b81ef5 22 #define DEV_CLK_ON ((unsigned long)1<<1)
henryeherman 0:beb124b81ef5 23 #define AHB_CLK_ON ((unsigned long)1<<4)
henryeherman 0:beb124b81ef5 24
henryeherman 0:beb124b81ef5 25 /* USB Device Interupt registers */
henryeherman 0:beb124b81ef5 26 #define FRAME ((unsigned long)1<<0)
henryeherman 0:beb124b81ef5 27 #define EP_FAST ((unsigned long)1<<1)
henryeherman 0:beb124b81ef5 28 #define EP_SLOW ((unsigned long)1<<2)
henryeherman 0:beb124b81ef5 29 #define DEV_STAT ((unsigned long)1<<3)
henryeherman 0:beb124b81ef5 30 #define CCEMPTY ((unsigned long)1<<4)
henryeherman 0:beb124b81ef5 31 #define CDFULL ((unsigned long)1<<5)
henryeherman 0:beb124b81ef5 32 #define RxENDPKT ((unsigned long)1<<6)
henryeherman 0:beb124b81ef5 33 #define TxENDPKT ((unsigned long)1<<7)
henryeherman 0:beb124b81ef5 34 #define EP_RLZED ((unsigned long)1<<8)
henryeherman 0:beb124b81ef5 35 #define ERR_INT ((unsigned long)1<<9)
henryeherman 0:beb124b81ef5 36
henryeherman 0:beb124b81ef5 37 /* Endpoint Interrupt Registers */
henryeherman 0:beb124b81ef5 38 #define EP(endpoint) (1<<endpoint)
henryeherman 0:beb124b81ef5 39
henryeherman 0:beb124b81ef5 40 /* USB Control register */
henryeherman 0:beb124b81ef5 41 #define RD_EN (1<<0)
henryeherman 0:beb124b81ef5 42 #define WR_EN (1<<1)
henryeherman 0:beb124b81ef5 43 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
henryeherman 0:beb124b81ef5 44
henryeherman 0:beb124b81ef5 45 /* USB Receive Packet Length register */
henryeherman 0:beb124b81ef5 46 #define DV ((unsigned long)1<<10)
henryeherman 0:beb124b81ef5 47 #define PKT_RDY ((unsigned long)1<<11)
henryeherman 0:beb124b81ef5 48 #define PKT_LNGTH_MASK (0x3ff)
henryeherman 0:beb124b81ef5 49
henryeherman 0:beb124b81ef5 50 /* Serial Interface Engine (SIE) */
henryeherman 0:beb124b81ef5 51 #define SIE_WRITE (0x01)
henryeherman 0:beb124b81ef5 52 #define SIE_READ (0x02)
henryeherman 0:beb124b81ef5 53 #define SIE_COMMAND (0x05)
henryeherman 0:beb124b81ef5 54 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
henryeherman 0:beb124b81ef5 55
henryeherman 0:beb124b81ef5 56 /* SIE Command codes */
henryeherman 0:beb124b81ef5 57 #define SIE_CMD_SET_ADDRESS (0xD0)
henryeherman 0:beb124b81ef5 58 #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
henryeherman 0:beb124b81ef5 59 #define SIE_CMD_SET_MODE (0xF3)
henryeherman 0:beb124b81ef5 60 #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
henryeherman 0:beb124b81ef5 61 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
henryeherman 0:beb124b81ef5 62 #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
henryeherman 0:beb124b81ef5 63 #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
henryeherman 0:beb124b81ef5 64 #define SIE_CMD_GET_ERROR_CODE (0xFF)
henryeherman 0:beb124b81ef5 65 #define SIE_CMD_READ_ERROR_STATUS (0xFB)
henryeherman 0:beb124b81ef5 66
henryeherman 0:beb124b81ef5 67 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
henryeherman 0:beb124b81ef5 68 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
henryeherman 0:beb124b81ef5 69 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
henryeherman 0:beb124b81ef5 70
henryeherman 0:beb124b81ef5 71 #define SIE_CMD_CLEAR_BUFFER (0xF2)
henryeherman 0:beb124b81ef5 72 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
henryeherman 0:beb124b81ef5 73
henryeherman 0:beb124b81ef5 74 /* SIE Device Status register */
henryeherman 0:beb124b81ef5 75 #define SIE_DS_CON (1<<0)
henryeherman 0:beb124b81ef5 76 #define SIE_DS_CON_CH (1<<1)
henryeherman 0:beb124b81ef5 77 #define SIE_DS_SUS (1<<2)
henryeherman 0:beb124b81ef5 78 #define SIE_DS_SUS_CH (1<<3)
henryeherman 0:beb124b81ef5 79 #define SIE_DS_RST (1<<4)
henryeherman 0:beb124b81ef5 80
henryeherman 0:beb124b81ef5 81 /* SIE Device Set Address register */
henryeherman 0:beb124b81ef5 82 #define SIE_DSA_DEV_EN (1<<7)
henryeherman 0:beb124b81ef5 83
henryeherman 0:beb124b81ef5 84 /* SIE Configue Device register */
henryeherman 0:beb124b81ef5 85 #define SIE_CONF_DEVICE (1<<0)
henryeherman 0:beb124b81ef5 86
henryeherman 0:beb124b81ef5 87 /* Select Endpoint register */
henryeherman 0:beb124b81ef5 88 #define SIE_SE_FE (1<<0)
henryeherman 0:beb124b81ef5 89 #define SIE_SE_ST (1<<1)
henryeherman 0:beb124b81ef5 90 #define SIE_SE_STP (1<<2)
henryeherman 0:beb124b81ef5 91 #define SIE_SE_PO (1<<3)
henryeherman 0:beb124b81ef5 92 #define SIE_SE_EPN (1<<4)
henryeherman 0:beb124b81ef5 93 #define SIE_SE_B_1_FULL (1<<5)
henryeherman 0:beb124b81ef5 94 #define SIE_SE_B_2_FULL (1<<6)
henryeherman 0:beb124b81ef5 95
henryeherman 0:beb124b81ef5 96 /* Set Endpoint Status command */
henryeherman 0:beb124b81ef5 97 #define SIE_SES_ST (1<<0)
henryeherman 0:beb124b81ef5 98 #define SIE_SES_DA (1<<5)
henryeherman 0:beb124b81ef5 99 #define SIE_SES_RF_MO (1<<6)
henryeherman 0:beb124b81ef5 100 #define SIE_SES_CND_ST (1<<7)
henryeherman 0:beb124b81ef5 101
henryeherman 0:beb124b81ef5 102 usbdc *usbdc::instance;
henryeherman 0:beb124b81ef5 103
henryeherman 0:beb124b81ef5 104 usbdc::usbdc()
henryeherman 0:beb124b81ef5 105 {
henryeherman 0:beb124b81ef5 106 #ifdef TARGET_LPC1768
henryeherman 0:beb124b81ef5 107 LPC_SC->USBCLKCFG=5; /* TODO */
henryeherman 0:beb124b81ef5 108 #endif
henryeherman 0:beb124b81ef5 109
henryeherman 0:beb124b81ef5 110 /* Enable power to USB device controller */
henryeherman 0:beb124b81ef5 111 LPC_SC->PCONP |= PCUSB;
henryeherman 0:beb124b81ef5 112
henryeherman 0:beb124b81ef5 113 /* Enable USB clocks */
henryeherman 0:beb124b81ef5 114 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
henryeherman 0:beb124b81ef5 115 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
henryeherman 0:beb124b81ef5 116
henryeherman 0:beb124b81ef5 117 /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
henryeherman 0:beb124b81ef5 118 LPC_PINCON->PINSEL1 &= 0xc3ffffff;
henryeherman 0:beb124b81ef5 119 LPC_PINCON->PINSEL1 |= 0x14000000;
henryeherman 0:beb124b81ef5 120
henryeherman 0:beb124b81ef5 121 #ifdef ENABLE_VBUS
henryeherman 0:beb124b81ef5 122 /* Configure pin P1.30 to be VBUS */
henryeherman 0:beb124b81ef5 123 LPC_PINCON->PINSEL3 &= 0xcfffffff;
henryeherman 0:beb124b81ef5 124 LPC_PINCON->PINSEL3 |= 0x20000000;
henryeherman 0:beb124b81ef5 125
henryeherman 0:beb124b81ef5 126 /* Configure pin P1.30 to have pull-down */
henryeherman 0:beb124b81ef5 127 LPC_PINCON->PINMODE3 |= 0x30000000;
henryeherman 0:beb124b81ef5 128 #endif
henryeherman 0:beb124b81ef5 129
henryeherman 0:beb124b81ef5 130 /* Configure pin P2.9 to be Connect */
henryeherman 0:beb124b81ef5 131 LPC_PINCON->PINSEL4 &= 0xfffcffff;
henryeherman 0:beb124b81ef5 132 LPC_PINCON->PINSEL4 |= 0x00040000;
henryeherman 0:beb124b81ef5 133
henryeherman 0:beb124b81ef5 134 /* Connect must be low for at least 2.5uS */
henryeherman 0:beb124b81ef5 135 wait_ms(1);
henryeherman 0:beb124b81ef5 136
henryeherman 0:beb124b81ef5 137 /* Attach IRQ */
henryeherman 0:beb124b81ef5 138 instance = this;
henryeherman 0:beb124b81ef5 139 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
henryeherman 0:beb124b81ef5 140 NVIC_EnableIRQ(USB_IRQn);
henryeherman 0:beb124b81ef5 141
henryeherman 0:beb124b81ef5 142 /* Enable device interrupts */
henryeherman 0:beb124b81ef5 143 enableEvents();
henryeherman 0:beb124b81ef5 144 }
henryeherman 0:beb124b81ef5 145
henryeherman 0:beb124b81ef5 146 void usbdc::connect(void)
henryeherman 0:beb124b81ef5 147 {
henryeherman 0:beb124b81ef5 148 /* Connect USB device */
henryeherman 0:beb124b81ef5 149 unsigned char status;
henryeherman 0:beb124b81ef5 150
henryeherman 0:beb124b81ef5 151 status = getDeviceStatus();
henryeherman 0:beb124b81ef5 152 setDeviceStatus(status | SIE_DS_CON);
henryeherman 0:beb124b81ef5 153 }
henryeherman 0:beb124b81ef5 154
henryeherman 0:beb124b81ef5 155 void usbdc::disconnect(void)
henryeherman 0:beb124b81ef5 156 {
henryeherman 0:beb124b81ef5 157 /* Disconnect USB device */
henryeherman 0:beb124b81ef5 158 unsigned char status;
henryeherman 0:beb124b81ef5 159
henryeherman 0:beb124b81ef5 160 status = getDeviceStatus();
henryeherman 0:beb124b81ef5 161 setDeviceStatus(status & ~SIE_DS_CON);
henryeherman 0:beb124b81ef5 162 }
henryeherman 0:beb124b81ef5 163
henryeherman 0:beb124b81ef5 164 void usbdc::SIECommand(unsigned long command)
henryeherman 0:beb124b81ef5 165 {
henryeherman 0:beb124b81ef5 166 /* The command phase of a SIE transaction */
henryeherman 0:beb124b81ef5 167 LPC_USB->USBDevIntClr = CCEMPTY;
henryeherman 0:beb124b81ef5 168 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
henryeherman 0:beb124b81ef5 169 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
henryeherman 0:beb124b81ef5 170 }
henryeherman 0:beb124b81ef5 171
henryeherman 0:beb124b81ef5 172 void usbdc::SIEWriteData(unsigned char data)
henryeherman 0:beb124b81ef5 173 {
henryeherman 0:beb124b81ef5 174 /* The data write phase of a SIE transaction */
henryeherman 0:beb124b81ef5 175 LPC_USB->USBDevIntClr = CCEMPTY;
henryeherman 0:beb124b81ef5 176 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
henryeherman 0:beb124b81ef5 177 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
henryeherman 0:beb124b81ef5 178 }
henryeherman 0:beb124b81ef5 179
henryeherman 0:beb124b81ef5 180 unsigned char usbdc::SIEReadData(unsigned long command)
henryeherman 0:beb124b81ef5 181 {
henryeherman 0:beb124b81ef5 182 /* The data read phase of a SIE transaction */
henryeherman 0:beb124b81ef5 183 LPC_USB->USBDevIntClr = CDFULL;
henryeherman 0:beb124b81ef5 184 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
henryeherman 0:beb124b81ef5 185 while (!(LPC_USB->USBDevIntSt & CDFULL));
henryeherman 0:beb124b81ef5 186 return (unsigned char)LPC_USB->USBCmdData;
henryeherman 0:beb124b81ef5 187 }
henryeherman 0:beb124b81ef5 188
henryeherman 0:beb124b81ef5 189 void usbdc::setDeviceStatus(unsigned char status)
henryeherman 0:beb124b81ef5 190 {
henryeherman 0:beb124b81ef5 191 /* Write SIE device status register */
henryeherman 0:beb124b81ef5 192 SIECommand(SIE_CMD_SET_DEVICE_STATUS);
henryeherman 0:beb124b81ef5 193 SIEWriteData(status);
henryeherman 0:beb124b81ef5 194 }
henryeherman 0:beb124b81ef5 195
henryeherman 0:beb124b81ef5 196 unsigned char usbdc::getDeviceStatus(void)
henryeherman 0:beb124b81ef5 197 {
henryeherman 0:beb124b81ef5 198 /* Read SIE device status register */
henryeherman 0:beb124b81ef5 199 SIECommand(SIE_CMD_GET_DEVICE_STATUS);
henryeherman 0:beb124b81ef5 200 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
henryeherman 0:beb124b81ef5 201 }
henryeherman 0:beb124b81ef5 202
henryeherman 0:beb124b81ef5 203 void usbdc::setAddress(unsigned char address)
henryeherman 0:beb124b81ef5 204 {
henryeherman 0:beb124b81ef5 205 /* Write SIE device address register */
henryeherman 0:beb124b81ef5 206 SIECommand(SIE_CMD_SET_ADDRESS);
henryeherman 0:beb124b81ef5 207 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
henryeherman 0:beb124b81ef5 208 }
henryeherman 0:beb124b81ef5 209
henryeherman 0:beb124b81ef5 210 unsigned char usbdc::selectEndpoint(unsigned char endpoint)
henryeherman 0:beb124b81ef5 211 {
henryeherman 0:beb124b81ef5 212 /* SIE select endpoint command */
henryeherman 0:beb124b81ef5 213 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
henryeherman 0:beb124b81ef5 214 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
henryeherman 0:beb124b81ef5 215 }
henryeherman 0:beb124b81ef5 216
henryeherman 0:beb124b81ef5 217 #if 1
henryeherman 0:beb124b81ef5 218 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
henryeherman 0:beb124b81ef5 219 {
henryeherman 0:beb124b81ef5 220 /* SIE select endpoint and clear interrupt command */
henryeherman 0:beb124b81ef5 221 /* Using the Select Endpoint / Clear Interrupt SIE command does not seem */
henryeherman 0:beb124b81ef5 222 /* to clear the appropriate bit in EP_INT_STAT? - using EP_INT_CLR instead */
henryeherman 0:beb124b81ef5 223 LPC_USB->USBEpIntClr = EP(endpoint);
henryeherman 0:beb124b81ef5 224 while (!(LPC_USB->USBDevIntSt & CDFULL));
henryeherman 0:beb124b81ef5 225 return (unsigned char)LPC_USB->USBCmdData;
henryeherman 0:beb124b81ef5 226 }
henryeherman 0:beb124b81ef5 227 #else
henryeherman 0:beb124b81ef5 228 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
henryeherman 0:beb124b81ef5 229 {
henryeherman 0:beb124b81ef5 230 /* SIE select endpoint and clear interrupt command */
henryeherman 0:beb124b81ef5 231 SIECommand(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
henryeherman 0:beb124b81ef5 232 return SIEReadData(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
henryeherman 0:beb124b81ef5 233 }
henryeherman 0:beb124b81ef5 234 #endif
henryeherman 0:beb124b81ef5 235
henryeherman 0:beb124b81ef5 236 unsigned char usbdc::clearBuffer(void)
henryeherman 0:beb124b81ef5 237 {
henryeherman 0:beb124b81ef5 238 /* SIE clear buffer command */
henryeherman 0:beb124b81ef5 239 SIECommand(SIE_CMD_CLEAR_BUFFER);
henryeherman 0:beb124b81ef5 240 return SIEReadData(SIE_CMD_CLEAR_BUFFER);
henryeherman 0:beb124b81ef5 241 }
henryeherman 0:beb124b81ef5 242
henryeherman 0:beb124b81ef5 243 void usbdc::validateBuffer(void)
henryeherman 0:beb124b81ef5 244 {
henryeherman 0:beb124b81ef5 245 /* SIE validate buffer command */
henryeherman 0:beb124b81ef5 246 SIECommand(SIE_CMD_VALIDATE_BUFFER);
henryeherman 0:beb124b81ef5 247 }
henryeherman 0:beb124b81ef5 248
henryeherman 0:beb124b81ef5 249 void usbdc::setEndpointStatus(unsigned char endpoint, unsigned char status)
henryeherman 0:beb124b81ef5 250 {
henryeherman 0:beb124b81ef5 251 /* SIE set endpoint status command */
henryeherman 0:beb124b81ef5 252 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
henryeherman 0:beb124b81ef5 253 SIEWriteData(status);
henryeherman 0:beb124b81ef5 254 }
henryeherman 0:beb124b81ef5 255
henryeherman 0:beb124b81ef5 256 void usbdc::realiseEndpoint(unsigned char endpoint, unsigned long maxPacket)
henryeherman 0:beb124b81ef5 257 {
henryeherman 0:beb124b81ef5 258 /* Realise an endpoint */
henryeherman 0:beb124b81ef5 259 LPC_USB->USBDevIntClr = EP_RLZED;
henryeherman 0:beb124b81ef5 260 LPC_USB->USBReEp |= EP(endpoint);
henryeherman 0:beb124b81ef5 261 LPC_USB->USBEpInd = endpoint;
henryeherman 0:beb124b81ef5 262 LPC_USB->USBMaxPSize = maxPacket;
henryeherman 0:beb124b81ef5 263
henryeherman 0:beb124b81ef5 264 while (!(LPC_USB->USBDevIntSt & EP_RLZED));
henryeherman 0:beb124b81ef5 265 LPC_USB->USBDevIntClr = EP_RLZED;
henryeherman 0:beb124b81ef5 266
henryeherman 0:beb124b81ef5 267 /* Clear stall state */
henryeherman 0:beb124b81ef5 268 endpointStallState &= ~EP(endpoint);
henryeherman 0:beb124b81ef5 269 }
henryeherman 0:beb124b81ef5 270
henryeherman 0:beb124b81ef5 271 void usbdc::enableEndpointEvent(unsigned char endpoint)
henryeherman 0:beb124b81ef5 272 {
henryeherman 0:beb124b81ef5 273 /* Enable an endpoint interrupt */
henryeherman 0:beb124b81ef5 274 LPC_USB->USBEpIntEn |= EP(endpoint);
henryeherman 0:beb124b81ef5 275 }
henryeherman 0:beb124b81ef5 276
henryeherman 0:beb124b81ef5 277 void usbdc::disableEndpointEvent(unsigned char endpoint)
henryeherman 0:beb124b81ef5 278 {
henryeherman 0:beb124b81ef5 279 /* Disable an endpoint interrupt */
henryeherman 0:beb124b81ef5 280 LPC_USB->USBEpIntEn &= ~EP(endpoint);
henryeherman 0:beb124b81ef5 281 }
henryeherman 0:beb124b81ef5 282
henryeherman 0:beb124b81ef5 283 void usbdc::stallEndpoint(unsigned char endpoint)
henryeherman 0:beb124b81ef5 284 {
henryeherman 0:beb124b81ef5 285 /* Stall an endpoint */
henryeherman 0:beb124b81ef5 286 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
henryeherman 0:beb124b81ef5 287 {
henryeherman 0:beb124b81ef5 288 /* Conditionally stall both control endpoints */
henryeherman 0:beb124b81ef5 289 setEndpointStatus(EP0OUT, SIE_SES_CND_ST);
henryeherman 0:beb124b81ef5 290 }
henryeherman 0:beb124b81ef5 291 else
henryeherman 0:beb124b81ef5 292 {
henryeherman 0:beb124b81ef5 293 setEndpointStatus(endpoint, SIE_SES_ST);
henryeherman 0:beb124b81ef5 294
henryeherman 0:beb124b81ef5 295 /* Update stall state */
henryeherman 0:beb124b81ef5 296 endpointStallState |= EP(endpoint);
henryeherman 0:beb124b81ef5 297 }
henryeherman 0:beb124b81ef5 298 }
henryeherman 0:beb124b81ef5 299
henryeherman 0:beb124b81ef5 300 void usbdc::unstallEndpoint(unsigned char endpoint)
henryeherman 0:beb124b81ef5 301 {
henryeherman 0:beb124b81ef5 302 /* Unstall an endpoint. The endpoint will also be reinitialised */
henryeherman 0:beb124b81ef5 303 setEndpointStatus(endpoint, 0);
henryeherman 0:beb124b81ef5 304
henryeherman 0:beb124b81ef5 305 /* Update stall state */
henryeherman 0:beb124b81ef5 306 endpointStallState &= ~EP(endpoint);
henryeherman 0:beb124b81ef5 307 }
henryeherman 0:beb124b81ef5 308
henryeherman 0:beb124b81ef5 309 bool usbdc::getEndpointStallState(unsigned char endpoint)
henryeherman 0:beb124b81ef5 310 {
henryeherman 0:beb124b81ef5 311 /* Returns true if endpoint stalled */
henryeherman 0:beb124b81ef5 312 return endpointStallState & EP(endpoint);
henryeherman 0:beb124b81ef5 313 }
henryeherman 0:beb124b81ef5 314
henryeherman 0:beb124b81ef5 315 void usbdc::configureDevice(void)
henryeherman 0:beb124b81ef5 316 {
henryeherman 0:beb124b81ef5 317 /* SIE Configure device command */
henryeherman 0:beb124b81ef5 318 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
henryeherman 0:beb124b81ef5 319 SIEWriteData(SIE_CONF_DEVICE);
henryeherman 0:beb124b81ef5 320 }
henryeherman 0:beb124b81ef5 321
henryeherman 0:beb124b81ef5 322 void usbdc::unconfigureDevice(void)
henryeherman 0:beb124b81ef5 323 {
henryeherman 0:beb124b81ef5 324 /* SIE Configure device command */
henryeherman 0:beb124b81ef5 325 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
henryeherman 0:beb124b81ef5 326 SIEWriteData(0);
henryeherman 0:beb124b81ef5 327 }
henryeherman 0:beb124b81ef5 328
henryeherman 0:beb124b81ef5 329 unsigned long usbdc::endpointRead(unsigned char endpoint, unsigned char *buffer)
henryeherman 0:beb124b81ef5 330 {
henryeherman 0:beb124b81ef5 331 /* Read from an OUT endpoint */
henryeherman 0:beb124b81ef5 332 unsigned long size;
henryeherman 0:beb124b81ef5 333 unsigned long i;
henryeherman 0:beb124b81ef5 334 unsigned long data;
henryeherman 0:beb124b81ef5 335 unsigned char offset;
henryeherman 0:beb124b81ef5 336
henryeherman 0:beb124b81ef5 337 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
henryeherman 0:beb124b81ef5 338 while (!(LPC_USB->USBRxPLen & PKT_RDY));
henryeherman 0:beb124b81ef5 339
henryeherman 0:beb124b81ef5 340 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
henryeherman 0:beb124b81ef5 341
henryeherman 0:beb124b81ef5 342 offset = 0;
henryeherman 0:beb124b81ef5 343
henryeherman 0:beb124b81ef5 344 for (i=0; i<size; i++)
henryeherman 0:beb124b81ef5 345 {
henryeherman 0:beb124b81ef5 346 if (offset==0)
henryeherman 0:beb124b81ef5 347 {
henryeherman 0:beb124b81ef5 348 /* Fetch up to four bytes of data as a word */
henryeherman 0:beb124b81ef5 349 data = LPC_USB->USBRxData;
henryeherman 0:beb124b81ef5 350 }
henryeherman 0:beb124b81ef5 351
henryeherman 0:beb124b81ef5 352 /* extract a byte */
henryeherman 0:beb124b81ef5 353 *buffer++ = data>>offset;
henryeherman 0:beb124b81ef5 354
henryeherman 0:beb124b81ef5 355 /* move on to the next byte */
henryeherman 0:beb124b81ef5 356 offset = (offset + 8) % 32;
henryeherman 0:beb124b81ef5 357 }
henryeherman 0:beb124b81ef5 358
henryeherman 0:beb124b81ef5 359 /* Clear RD_EN to cover zero length packet case */
henryeherman 0:beb124b81ef5 360 LPC_USB->USBCtrl=0;
henryeherman 0:beb124b81ef5 361
henryeherman 0:beb124b81ef5 362 selectEndpoint(endpoint);
henryeherman 0:beb124b81ef5 363 clearBuffer();
henryeherman 0:beb124b81ef5 364
henryeherman 0:beb124b81ef5 365 return size;
henryeherman 0:beb124b81ef5 366 }
henryeherman 0:beb124b81ef5 367
henryeherman 0:beb124b81ef5 368 void usbdc::endpointWrite(unsigned char endpoint, unsigned char *buffer, unsigned long size)
henryeherman 0:beb124b81ef5 369 {
henryeherman 0:beb124b81ef5 370 /* Write to an IN endpoint */
henryeherman 0:beb124b81ef5 371 unsigned long temp, data;
henryeherman 0:beb124b81ef5 372 unsigned char offset;
henryeherman 0:beb124b81ef5 373
henryeherman 0:beb124b81ef5 374 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
henryeherman 0:beb124b81ef5 375
henryeherman 0:beb124b81ef5 376 LPC_USB->USBTxPLen = size;
henryeherman 0:beb124b81ef5 377 offset = 0;
henryeherman 0:beb124b81ef5 378 data = 0;
henryeherman 0:beb124b81ef5 379
henryeherman 0:beb124b81ef5 380 if (size>0)
henryeherman 0:beb124b81ef5 381 {
henryeherman 0:beb124b81ef5 382 do {
henryeherman 0:beb124b81ef5 383 /* Fetch next data byte into a word-sized temporary variable */
henryeherman 0:beb124b81ef5 384 temp = *buffer++;
henryeherman 0:beb124b81ef5 385
henryeherman 0:beb124b81ef5 386 /* Add to current data word */
henryeherman 0:beb124b81ef5 387 temp = temp << offset;
henryeherman 0:beb124b81ef5 388 data = data | temp;
henryeherman 0:beb124b81ef5 389
henryeherman 0:beb124b81ef5 390 /* move on to the next byte */
henryeherman 0:beb124b81ef5 391 offset = (offset + 8) % 32;
henryeherman 0:beb124b81ef5 392 size--;
henryeherman 0:beb124b81ef5 393
henryeherman 0:beb124b81ef5 394 if ((offset==0) || (size==0))
henryeherman 0:beb124b81ef5 395 {
henryeherman 0:beb124b81ef5 396 /* Write the word to the endpoint */
henryeherman 0:beb124b81ef5 397 LPC_USB->USBTxData = data;
henryeherman 0:beb124b81ef5 398 data = 0;
henryeherman 0:beb124b81ef5 399 }
henryeherman 0:beb124b81ef5 400 } while (size>0);
henryeherman 0:beb124b81ef5 401 }
henryeherman 0:beb124b81ef5 402
henryeherman 0:beb124b81ef5 403 /* Clear WR_EN to cover zero length packet case */
henryeherman 0:beb124b81ef5 404 LPC_USB->USBCtrl=0;
henryeherman 0:beb124b81ef5 405
henryeherman 0:beb124b81ef5 406 selectEndpoint(endpoint);
henryeherman 0:beb124b81ef5 407 validateBuffer();
henryeherman 0:beb124b81ef5 408 }
henryeherman 0:beb124b81ef5 409
henryeherman 0:beb124b81ef5 410 void usbdc::enableEvents(void)
henryeherman 0:beb124b81ef5 411 {
henryeherman 0:beb124b81ef5 412 /* Enable interrupt sources */
henryeherman 0:beb124b81ef5 413 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
henryeherman 0:beb124b81ef5 414 }
henryeherman 0:beb124b81ef5 415
henryeherman 0:beb124b81ef5 416 void usbdc::disableEvents(void)
henryeherman 0:beb124b81ef5 417 {
henryeherman 0:beb124b81ef5 418 /* Disable interrupt sources */
henryeherman 0:beb124b81ef5 419 LPC_USB->USBDevIntClr = EP_SLOW | DEV_STAT;
henryeherman 0:beb124b81ef5 420 }
henryeherman 0:beb124b81ef5 421
henryeherman 0:beb124b81ef5 422 void usbdc::usbisr(void)
henryeherman 0:beb124b81ef5 423 {
henryeherman 0:beb124b81ef5 424 unsigned char devStat;
henryeherman 0:beb124b81ef5 425
henryeherman 0:beb124b81ef5 426 if (LPC_USB->USBDevIntSt & FRAME)
henryeherman 0:beb124b81ef5 427 {
henryeherman 0:beb124b81ef5 428 /* Frame event */
henryeherman 0:beb124b81ef5 429 deviceEventFrame();
henryeherman 0:beb124b81ef5 430 /* Clear interrupt status flag */
henryeherman 0:beb124b81ef5 431 LPC_USB->USBDevIntClr = FRAME;
henryeherman 0:beb124b81ef5 432 }
henryeherman 0:beb124b81ef5 433
henryeherman 0:beb124b81ef5 434 if (LPC_USB->USBDevIntSt & DEV_STAT)
henryeherman 0:beb124b81ef5 435 {
henryeherman 0:beb124b81ef5 436 /* Device Status interrupt */
henryeherman 0:beb124b81ef5 437 /* Must clear the interrupt status flag before reading the device status from the SIE */
henryeherman 0:beb124b81ef5 438 LPC_USB->USBDevIntClr = DEV_STAT;
henryeherman 0:beb124b81ef5 439
henryeherman 0:beb124b81ef5 440 /* Read device status from SIE */
henryeherman 0:beb124b81ef5 441 devStat = getDeviceStatus();
henryeherman 0:beb124b81ef5 442
henryeherman 0:beb124b81ef5 443 if (devStat & SIE_DS_RST)
henryeherman 0:beb124b81ef5 444 {
henryeherman 0:beb124b81ef5 445 /* Bus reset */
henryeherman 0:beb124b81ef5 446 deviceEventReset();
henryeherman 0:beb124b81ef5 447 }
henryeherman 0:beb124b81ef5 448 }
henryeherman 0:beb124b81ef5 449
henryeherman 0:beb124b81ef5 450 if (LPC_USB->USBDevIntSt & EP_SLOW)
henryeherman 0:beb124b81ef5 451 {
henryeherman 0:beb124b81ef5 452 /* (Slow) Endpoint Interrupt */
henryeherman 0:beb124b81ef5 453
henryeherman 0:beb124b81ef5 454 /* Process each endpoint interrupt */
henryeherman 0:beb124b81ef5 455 if (LPC_USB->USBEpIntSt & EP(EP0OUT))
henryeherman 0:beb124b81ef5 456 {
henryeherman 0:beb124b81ef5 457 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
henryeherman 0:beb124b81ef5 458 {
henryeherman 0:beb124b81ef5 459 /* this is a setup packet */
henryeherman 0:beb124b81ef5 460 endpointEventEP0Setup();
henryeherman 0:beb124b81ef5 461 }
henryeherman 0:beb124b81ef5 462 else
henryeherman 0:beb124b81ef5 463 {
henryeherman 0:beb124b81ef5 464 endpointEventEP0Out();
henryeherman 0:beb124b81ef5 465 }
henryeherman 0:beb124b81ef5 466 }
henryeherman 0:beb124b81ef5 467
henryeherman 0:beb124b81ef5 468 if (LPC_USB->USBEpIntSt & EP(EP0IN))
henryeherman 0:beb124b81ef5 469 {
henryeherman 0:beb124b81ef5 470 selectEndpointClearInterrupt(EP0IN);
henryeherman 0:beb124b81ef5 471 endpointEventEP0In();
henryeherman 0:beb124b81ef5 472 }
henryeherman 0:beb124b81ef5 473
henryeherman 0:beb124b81ef5 474 if (LPC_USB->USBEpIntSt & EP(EP1OUT))
henryeherman 0:beb124b81ef5 475 {
henryeherman 0:beb124b81ef5 476 selectEndpointClearInterrupt(EP1OUT);
henryeherman 0:beb124b81ef5 477 endpointEventEP1Out();
henryeherman 0:beb124b81ef5 478 }
henryeherman 0:beb124b81ef5 479
henryeherman 0:beb124b81ef5 480 if (LPC_USB->USBEpIntSt & EP(EP1IN))
henryeherman 0:beb124b81ef5 481 {
henryeherman 0:beb124b81ef5 482 selectEndpointClearInterrupt(EP1IN);
henryeherman 0:beb124b81ef5 483 endpointEventEP1In();
henryeherman 0:beb124b81ef5 484 }
henryeherman 0:beb124b81ef5 485
henryeherman 0:beb124b81ef5 486 if (LPC_USB->USBEpIntSt & EP(EP2OUT))
henryeherman 0:beb124b81ef5 487 {
henryeherman 0:beb124b81ef5 488 selectEndpointClearInterrupt(EP2OUT);
henryeherman 0:beb124b81ef5 489 endpointEventEP2Out();
henryeherman 0:beb124b81ef5 490 }
henryeherman 0:beb124b81ef5 491
henryeherman 0:beb124b81ef5 492 if (LPC_USB->USBEpIntSt & EP(EP2IN))
henryeherman 0:beb124b81ef5 493 {
henryeherman 0:beb124b81ef5 494 selectEndpointClearInterrupt(EP2IN);
henryeherman 0:beb124b81ef5 495 endpointEventEP2In();
henryeherman 0:beb124b81ef5 496 }
henryeherman 0:beb124b81ef5 497
henryeherman 0:beb124b81ef5 498 /* Clear interrupt status flag */
henryeherman 0:beb124b81ef5 499 /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
henryeherman 0:beb124b81ef5 500 LPC_USB->USBDevIntClr = EP_SLOW;
henryeherman 0:beb124b81ef5 501 }
henryeherman 0:beb124b81ef5 502 }
henryeherman 0:beb124b81ef5 503
henryeherman 0:beb124b81ef5 504
henryeherman 0:beb124b81ef5 505 void usbdc::_usbisr(void)
henryeherman 0:beb124b81ef5 506 {
henryeherman 0:beb124b81ef5 507 instance->usbisr();
henryeherman 0:beb124b81ef5 508 }
henryeherman 0:beb124b81ef5 509
henryeherman 0:beb124b81ef5 510 void usbdc::deviceEventReset(void)
henryeherman 0:beb124b81ef5 511 {
henryeherman 0:beb124b81ef5 512 }
henryeherman 0:beb124b81ef5 513
henryeherman 0:beb124b81ef5 514 void usbdc::deviceEventFrame(void)
henryeherman 0:beb124b81ef5 515 {
henryeherman 0:beb124b81ef5 516 }
henryeherman 0:beb124b81ef5 517
henryeherman 0:beb124b81ef5 518 void usbdc::endpointEventEP0Setup(void)
henryeherman 0:beb124b81ef5 519 {
henryeherman 0:beb124b81ef5 520 }
henryeherman 0:beb124b81ef5 521
henryeherman 0:beb124b81ef5 522 void usbdc::endpointEventEP0In(void)
henryeherman 0:beb124b81ef5 523 {
henryeherman 0:beb124b81ef5 524 }
henryeherman 0:beb124b81ef5 525
henryeherman 0:beb124b81ef5 526 void usbdc::endpointEventEP0Out(void)
henryeherman 0:beb124b81ef5 527 {
henryeherman 0:beb124b81ef5 528 }
henryeherman 0:beb124b81ef5 529
henryeherman 0:beb124b81ef5 530 void usbdc::endpointEventEP1In(void)
henryeherman 0:beb124b81ef5 531 {
henryeherman 0:beb124b81ef5 532 }
henryeherman 0:beb124b81ef5 533
henryeherman 0:beb124b81ef5 534 void usbdc::endpointEventEP1Out(void)
henryeherman 0:beb124b81ef5 535 {
henryeherman 0:beb124b81ef5 536 }
henryeherman 0:beb124b81ef5 537
henryeherman 0:beb124b81ef5 538 void usbdc::endpointEventEP2In(void)
henryeherman 0:beb124b81ef5 539 {
henryeherman 0:beb124b81ef5 540 }
henryeherman 0:beb124b81ef5 541
henryeherman 0:beb124b81ef5 542 void usbdc::endpointEventEP2Out(void)
henryeherman 0:beb124b81ef5 543 {
henryeherman 0:beb124b81ef5 544 }