Forked to make modifications to bring the USBHID into USB compliance and add additional features.

Dependents:   HW4_AudioControl

Fork of USBDevice by mbed official

As of Revision 18 everything in the USBHID specification is now implemented, except Multi-reports.

Revision comments for changelist 18

USBHID.cpp

  • Added SET_PROTOCOL support
  • Added GET_PROTOCOL support
  • protocolSate is set to 1 by default to match USB HID specification. This variable should be checked to determine which format theinput report should have. 1 - Use the user specified report format. 0 - Use the BOOT protocol report format.

Revision comments for changelist 16

  • HID_REPORT transformed from structure to class. This was done for several reasons.
  1. When multiple reports are used the 64 byte size for every report becomes a problem.
  2. The length value should always remain the same for a report, Make the constructor set the vale at the same time it allocates memory for the DATA area.
  • By default the data will be an array of MAX_HID_REPORT_SIZE like the structure,
  • When given a length argument, the hid_report.length will be set, and hid_report.data will be an array of the size given.
  • Length zero causes data to be NULL
  • Mostly backwards compatible. The definition of a destructor caused a compiler error in USBMouse::update and USBMousekeyboard::update. This error was caused by instatiation of HID_REPORT in the middle of an IF logic statement. These files have been modified. The error complained that the logic skipped object initialization. The HID_REPORT has been moved to the class definition. Since both ABSOLUTE and RELATIVE modes used the HID_REPORT, this seems to make more sense. Previously the hid_report would be instatiated in <class>::mousesend and <class>::update.

Revision comments for changelist 14

USBdevice.cpp

  • Modified USB device state to change from Configure when disconnect is called.
  • Modified the call back function for when the suspend state changes. This should be used to turn off peripherals to conserve power.

Revision comments for changelist 13

USBdevice.cpp

  • ) Changed DEBUG messages to be more descriptive for string descriptor
  • ) Bug fix: Control Transfers did not actually transfer the data from Buffer to transfer->ptr

USBHIDTypes.h

  • ) Added ALL CLASS request to KEYWORD list
  • ) Added KEYWORDS for report type

USBHID.h

  • ) Added a new constructor to specify size of feature report
  • ) Added HID_REPORT inputReport and featureReport
  • ) Added data structures to support IDLE rate
  • ) Added data structures to support callback functions

USBHID.cpp

  • ) Changed constructor to initialize new feature data structures
  • ) Implemented Set_IDLE/GET_IDLE and the periodic resend of non-changed data
  • ) Implemented HID specification required control transfer GET_REPORT
  • ) Fixed issue where Intreput transfers and control transfers did not access the same data structures.
  • ) Implemented Feature reports
  • ) Implemented Callback Hooks for get_report/set_report actions.
  • ) Added callback hooks for interupt actions in the new functions.
  • ) interupt transfer can now write to outputReport
  • ) Modified SET_REPORT code to function for multiple types.
  • ) Refactored some code in preperation to add multi report support
Test NumberTest DescriptionTest ResultNotes
1Use USBmouse to verify backward compatibility of constructor and methodsPass
2Test SET_REPORT can set a feature reportPass
3Test GET_REPORT can retrieve a feature reportPass
4Test SET_IDLE sets up a reoccuring triggerPassIOCTL_SET_POLL_FREQUENCY_MSEC does not function for the windows HID driver. A Special test program is used to rearm the IDLE rate after windows sets it to zero
5Test SET_IDLE disables a triggerPassWindows automatically sends this command to a HID device when it is inserted.
6Enabled DEBUG in USBDevice.cpp and generated str descriptor requests.Pass
7Test SET_REPORT can set an output reportPass
8Test GET_REPORT can retrieve an output reportPass
9ReadFile, accesses the input_reportPass
10WriteFile accesses the output_report, via interupt transfer when ep1_out is used.Pass
11WriteFile accesses the output_report, via control transfer when ep1_out is NOT used.Not Tested
12Callback hooks trigger independently for each type of set_report/get_reportPass
13New constructor sets feature_report sizePass
14Control transfer SET_REPORT and writeFile access the same data structureBUGThe same data structure is accessed, but the data transfer size is different. The writeFile strips the leading byte which is the report ID, The Control transfer keeps the byte.
15Control transfer GET_REPORT and readFile access the same data structureBUGThe same dtat structure is accessed, but the data transfer size is different. The readFile strips the leading byte which is the report ID, The Control transfer keeps the byte.
16Test GET_IDLE retrieves the IDLE rateUnknownWindows HID driver does not implement IOCTL_HID_GET_POLL_FREQUENCY_MSEC
Committer:
jakowisp
Date:
Thu Aug 08 08:02:46 2013 +0000
Revision:
18:cb3afa532fcd
Parent:
10:1e3d126a322b
Default ProtocolState was incorrectly being set to 0:Boot when the HID specification states that the default should be 1:Report

Who changed what in which revision?

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