Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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