PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

614 line
22KB

  1. /* USB Serial Example for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/usb_serial.html
  3. * Copyright (c) 2008 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include "usb_common.h"
  24. #include "usb_private.h"
  25. /**************************************************************************
  26. *
  27. * Endpoint Buffer Configuration
  28. *
  29. **************************************************************************/
  30. static const uint8_t PROGMEM endpoint_config_table[] = {
  31. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER,
  32. 1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER,
  33. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(RAWHID_TX_SIZE) | RAWHID_TX_BUFFER,
  34. 1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(RAWHID_RX_SIZE) | RAWHID_RX_BUFFER,
  35. 0
  36. };
  37. /**************************************************************************
  38. *
  39. * Descriptor Data
  40. *
  41. **************************************************************************/
  42. // Descriptors are the data that your computer reads when it auto-detects
  43. // this USB device (called "enumeration" in USB lingo). The most commonly
  44. // changed items are editable at the top of this file. Changing things
  45. // in here should only be done by those who've read chapter 9 of the USB
  46. // spec and relevant portions of any USB class specifications!
  47. static const uint8_t PROGMEM device_descriptor[] = {
  48. 18, // bLength
  49. 1, // bDescriptorType
  50. 0x00, 0x02, // bcdUSB
  51. 0, // bDeviceClass
  52. 0, // bDeviceSubClass
  53. 0, // bDeviceProtocol
  54. ENDPOINT0_SIZE, // bMaxPacketSize0
  55. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  56. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  57. 0x02, 0x01, // bcdDevice
  58. 0, // iManufacturer
  59. 1, // iProduct
  60. 0, // iSerialNumber
  61. 1 // bNumConfigurations
  62. };
  63. static const uint8_t PROGMEM rawhid_hid_report_desc[] = {
  64. 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),
  65. 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
  66. 0xA1, 0x01, // Collection 0x01
  67. 0x75, 0x08, // report size = 8 bits
  68. 0x15, 0x00, // logical minimum = 0
  69. 0x26, 0xFF, 0x00, // logical maximum = 255
  70. 0x95, RAWHID_TX_SIZE, // report count
  71. 0x09, 0x01, // usage
  72. 0x81, 0x02, // Input (array)
  73. 0x95, RAWHID_RX_SIZE, // report count
  74. 0x09, 0x02, // usage
  75. 0x91, 0x02, // Output (array)
  76. 0xC0 // end collection
  77. };
  78. static const uint8_t PROGMEM debug_hid_report_desc[] = {
  79. 0x06, 0xC9, 0xFF, // Usage Page 0xFFC9 (vendor defined)
  80. 0x09, 0x04, // Usage 0x04
  81. 0xA1, 0x5C, // Collection 0x5C
  82. 0x75, 0x08, // report size = 8 bits (global)
  83. 0x15, 0x00, // logical minimum = 0 (global)
  84. 0x26, 0xFF, 0x00, // logical maximum = 255 (global)
  85. 0x95, DEBUG_TX_SIZE, // report count (global)
  86. 0x09, 0x75, // usage (local)
  87. 0x81, 0x02, // Input
  88. 0x95, DEBUG_RX_SIZE, // report count (global)
  89. 0x09, 0x76, // usage (local)
  90. 0x91, 0x02, // Output
  91. 0x95, 0x04, // report count (global)
  92. 0x09, 0x76, // usage (local)
  93. 0xB1, 0x02, // Feature
  94. 0xC0 // end collection
  95. };
  96. #define RAWHID_HID_DESC_OFFSET ( 9 + 9 )
  97. #define DEBUG_HID_DESC_OFFSET ( 9 + 9+9+7+7 + 9 )
  98. #define CONFIG1_DESC_SIZE ( 9 + 9+9+7+7 + 9+9+7+7 )
  99. static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  100. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  101. 9, // bLength;
  102. 2, // bDescriptorType;
  103. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  104. MSB(CONFIG1_DESC_SIZE),
  105. NUM_INTERFACE, // bNumInterfaces
  106. 1, // bConfigurationValue
  107. 0, // iConfiguration
  108. 0xC0, // bmAttributes
  109. 50, // bMaxPower
  110. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  111. 9, // bLength
  112. 4, // bDescriptorType
  113. RAWHID_INTERFACE, // bInterfaceNumber
  114. 0, // bAlternateSetting
  115. 2, // bNumEndpoints
  116. 0x03, // bInterfaceClass (0x03 = HID)
  117. 0x00, // bInterfaceSubClass (0x01 = Boot)
  118. 0x00, // bInterfaceProtocol (0x01 = Keyboard)
  119. 2, // iInterface
  120. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  121. 9, // bLength
  122. 0x21, // bDescriptorType
  123. 0x11, 0x01, // bcdHID
  124. 0, // bCountryCode
  125. 1, // bNumDescriptors
  126. 0x22, // bDescriptorType
  127. sizeof(rawhid_hid_report_desc), // wDescriptorLength
  128. 0,
  129. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  130. 7, // bLength
  131. 5, // bDescriptorType
  132. RAWHID_TX_ENDPOINT | 0x80, // bEndpointAddress
  133. 0x03, // bmAttributes (0x03=intr)
  134. RAWHID_TX_SIZE, 0, // wMaxPacketSize
  135. RAWHID_TX_INTERVAL, // bInterval
  136. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  137. 7, // bLength
  138. 5, // bDescriptorType
  139. RAWHID_RX_ENDPOINT, // bEndpointAddress
  140. 0x03, // bmAttributes (0x03=intr)
  141. RAWHID_RX_SIZE, 0, // wMaxPacketSize
  142. RAWHID_RX_INTERVAL, // bInterval
  143. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  144. 9, // bLength
  145. 4, // bDescriptorType
  146. DEBUG_INTERFACE, // bInterfaceNumber
  147. 0, // bAlternateSetting
  148. 2, // bNumEndpoints
  149. 0x03, // bInterfaceClass (0x03 = HID)
  150. 0x00, // bInterfaceSubClass
  151. 0x00, // bInterfaceProtocol
  152. 3, // iInterface
  153. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  154. 9, // bLength
  155. 0x21, // bDescriptorType
  156. 0x11, 0x01, // bcdHID
  157. 0, // bCountryCode
  158. 1, // bNumDescriptors
  159. 0x22, // bDescriptorType
  160. sizeof(debug_hid_report_desc), // wDescriptorLength
  161. 0,
  162. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  163. 7, // bLength
  164. 5, // bDescriptorType
  165. DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
  166. 0x03, // bmAttributes (0x03=intr)
  167. DEBUG_TX_SIZE, 0, // wMaxPacketSize
  168. DEBUG_TX_INTERVAL, // bInterval
  169. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  170. 7, // bLength
  171. 5, // bDescriptorType
  172. DEBUG_RX_ENDPOINT, // bEndpointAddress
  173. 0x03, // bmAttributes (0x03=intr)
  174. DEBUG_RX_SIZE, 0, // wMaxPacketSize
  175. DEBUG_RX_INTERVAL // bInterval
  176. };
  177. // If you're desperate for a little extra code memory, these strings
  178. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  179. // in the device desciptor are changed to zeros.
  180. struct usb_string_descriptor_struct {
  181. uint8_t bLength;
  182. uint8_t bDescriptorType;
  183. int16_t wString[];
  184. };
  185. static const struct usb_string_descriptor_struct PROGMEM string0 = {
  186. 4,
  187. 3,
  188. {0x0409}
  189. };
  190. static const struct usb_string_descriptor_struct PROGMEM string1 = {
  191. sizeof(STR_PRODUCT),
  192. 3,
  193. STR_PRODUCT
  194. };
  195. static const struct usb_string_descriptor_struct PROGMEM string2 = {
  196. sizeof(STR_RAWHID),
  197. 3,
  198. STR_RAWHID
  199. };
  200. static const struct usb_string_descriptor_struct PROGMEM string3 = {
  201. sizeof(STR_DEBUG),
  202. 3,
  203. STR_DEBUG
  204. };
  205. // This table defines which descriptor data is sent for each specific
  206. // request from the host (in wValue and wIndex).
  207. static const struct descriptor_list_struct {
  208. uint16_t wValue;
  209. uint16_t wIndex;
  210. const uint8_t *addr;
  211. uint8_t length;
  212. } PROGMEM descriptor_list[] = {
  213. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  214. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  215. {0x2200, RAWHID_INTERFACE, rawhid_hid_report_desc, sizeof(rawhid_hid_report_desc)},
  216. {0x2100, RAWHID_INTERFACE, config1_descriptor+RAWHID_HID_DESC_OFFSET, 9},
  217. {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
  218. {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
  219. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  220. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_PRODUCT)},
  221. {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_RAWHID)},
  222. {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_DEBUG)},
  223. };
  224. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  225. /**************************************************************************
  226. *
  227. * Variables - these are the only non-stack RAM usage
  228. *
  229. **************************************************************************/
  230. // zero when we are not configured, non-zero when enumerated
  231. volatile uint8_t usb_configuration USBSTATE;
  232. volatile uint8_t usb_suspended USBSTATE;
  233. // the time remaining before we transmit any partially full
  234. // packet, or send a zero length packet.
  235. volatile uint8_t debug_flush_timer USBSTATE;
  236. // these are a more reliable timeout than polling the
  237. // frame counter (UDFNUML)
  238. volatile uint16_t rawhid_rx_timeout_count USBSTATE;
  239. volatile uint16_t rawhid_tx_timeout_count USBSTATE;
  240. /**************************************************************************
  241. *
  242. * Public Functions - these are the API intended for the user
  243. *
  244. **************************************************************************/
  245. // initialize USB serial
  246. void usb_init(void)
  247. {
  248. uint8_t u;
  249. u = USBCON;
  250. if ((u & (1<<USBE)) && !(u & (1<<FRZCLK))) return;
  251. HW_CONFIG();
  252. USB_FREEZE(); // enable USB
  253. PLL_CONFIG(); // config PLL
  254. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  255. USB_CONFIG(); // start USB clock
  256. UDCON = 0; // enable attach resistor
  257. usb_configuration = 0;
  258. usb_suspended = 0;
  259. debug_flush_timer = 0;
  260. rawhid_rx_timeout_count = 0;
  261. rawhid_tx_timeout_count = 0;
  262. UDINT = 0;
  263. UDIEN = (1<<EORSTE)|(1<<SOFE);
  264. //sei(); // init() in wiring.c does this
  265. }
  266. void usb_shutdown(void)
  267. {
  268. UDIEN = 0; // disable interrupts
  269. UDCON = 1; // disconnect attach resistor
  270. USBCON = 0; // shut off USB periperal
  271. PLLCSR = 0; // shut off PLL
  272. usb_configuration = 0;
  273. usb_suspended = 1;
  274. }
  275. // Public API functions moved to usb_api.cpp
  276. /**************************************************************************
  277. *
  278. * Private Functions - not intended for general user consumption....
  279. *
  280. **************************************************************************/
  281. // USB Device Interrupt - handle all device-level events
  282. // the transmit buffer flushing is triggered by the start of frame
  283. //
  284. ISR(USB_GEN_vect)
  285. {
  286. uint8_t intbits, t;
  287. intbits = UDINT;
  288. UDINT = 0;
  289. if (intbits & (1<<EORSTI)) {
  290. UENUM = 0;
  291. UECONX = 1;
  292. UECFG0X = EP_TYPE_CONTROL;
  293. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  294. UEIENX = (1<<RXSTPE);
  295. usb_configuration = 0;
  296. }
  297. if ((intbits & (1<<SOFI)) && usb_configuration) {
  298. t = debug_flush_timer;
  299. if (t) {
  300. debug_flush_timer = -- t;
  301. if (!t) {
  302. UENUM = DEBUG_TX_ENDPOINT;
  303. while ((UEINTX & (1<<RWAL))) {
  304. UEDATX = 0;
  305. }
  306. UEINTX = 0x3A;
  307. }
  308. }
  309. t = rawhid_rx_timeout_count;
  310. if (t) rawhid_rx_timeout_count = --t;
  311. t = rawhid_tx_timeout_count;
  312. if (t) rawhid_tx_timeout_count = --t;
  313. }
  314. if (intbits & (1<<SUSPI)) {
  315. // USB Suspend (inactivity for 3ms)
  316. UDIEN = (1<<WAKEUPE);
  317. usb_configuration = 0;
  318. usb_suspended = 1;
  319. #if (F_CPU >= 8000000L)
  320. // WAKEUPI does not work with USB clock freeze
  321. // when CPU is running less than 8 MHz.
  322. // Is this a hardware bug?
  323. USB_FREEZE(); // shut off USB
  324. PLLCSR = 0; // shut off PLL
  325. #endif
  326. // to properly meet the USB spec, current must
  327. // reduce to less than 2.5 mA, which means using
  328. // powerdown mode, but that breaks the Arduino
  329. // user's paradigm....
  330. }
  331. if (usb_suspended && (intbits & (1<<WAKEUPI))) {
  332. // USB Resume (pretty much any activity)
  333. #if (F_CPU >= 8000000L)
  334. PLL_CONFIG();
  335. while (!(PLLCSR & (1<<PLOCK))) ;
  336. USB_CONFIG();
  337. #endif
  338. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  339. usb_suspended = 0;
  340. return;
  341. }
  342. }
  343. // Misc functions to wait for ready and send/receive packets
  344. static inline void usb_wait_in_ready(void)
  345. {
  346. while (!(UEINTX & (1<<TXINI))) ;
  347. }
  348. static inline void usb_send_in(void)
  349. {
  350. UEINTX = ~(1<<TXINI);
  351. }
  352. static inline void usb_wait_receive_out(void)
  353. {
  354. while (!(UEINTX & (1<<RXOUTI))) ;
  355. }
  356. static inline void usb_ack_out(void)
  357. {
  358. UEINTX = ~(1<<RXOUTI);
  359. }
  360. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  361. // other endpoints are manipulated by the user-callable
  362. // functions, and the start-of-frame interrupt.
  363. //
  364. ISR(USB_COM_vect)
  365. {
  366. uint8_t intbits;
  367. const uint8_t *list;
  368. const uint8_t *cfg;
  369. uint8_t i, n, len, en;
  370. uint8_t bmRequestType;
  371. uint8_t bRequest;
  372. uint16_t wValue;
  373. uint16_t wIndex;
  374. uint16_t wLength;
  375. uint16_t desc_val;
  376. const uint8_t *desc_addr;
  377. uint8_t desc_length;
  378. UENUM = 0;
  379. intbits = UEINTX;
  380. if (intbits & (1<<RXSTPI)) {
  381. bmRequestType = UEDATX;
  382. bRequest = UEDATX;
  383. read_word_lsbfirst(wValue, UEDATX);
  384. read_word_lsbfirst(wIndex, UEDATX);
  385. read_word_lsbfirst(wLength, UEDATX);
  386. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  387. if (bRequest == GET_DESCRIPTOR) {
  388. list = (const uint8_t *)descriptor_list;
  389. for (i=0; ; i++) {
  390. if (i >= NUM_DESC_LIST) {
  391. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  392. return;
  393. }
  394. pgm_read_word_postinc(desc_val, list);
  395. if (desc_val != wValue) {
  396. list += sizeof(struct descriptor_list_struct)-2;
  397. continue;
  398. }
  399. pgm_read_word_postinc(desc_val, list);
  400. if (desc_val != wIndex) {
  401. list += sizeof(struct descriptor_list_struct)-4;
  402. continue;
  403. }
  404. pgm_read_word_postinc(desc_addr, list);
  405. desc_length = pgm_read_byte(list);
  406. break;
  407. }
  408. len = (wLength < 256) ? wLength : 255;
  409. if (len > desc_length) len = desc_length;
  410. list = desc_addr;
  411. do {
  412. // wait for host ready for IN packet
  413. do {
  414. i = UEINTX;
  415. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  416. if (i & (1<<RXOUTI)) return; // abort
  417. // send IN packet
  418. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  419. for (i = n; i; i--) {
  420. pgm_read_byte_postinc(UEDATX, list);
  421. }
  422. len -= n;
  423. usb_send_in();
  424. } while (len || n == ENDPOINT0_SIZE);
  425. return;
  426. }
  427. if (bRequest == SET_ADDRESS) {
  428. usb_send_in();
  429. usb_wait_in_ready();
  430. UDADDR = wValue | (1<<ADDEN);
  431. return;
  432. }
  433. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  434. usb_configuration = wValue;
  435. debug_flush_timer = 0;
  436. usb_send_in();
  437. cfg = endpoint_config_table;
  438. for (i=1; i<NUM_ENDPOINTS; i++) {
  439. UENUM = i;
  440. pgm_read_byte_postinc(en, cfg);
  441. UECONX = en;
  442. if (en) {
  443. pgm_read_byte_postinc(UECFG0X, cfg);
  444. pgm_read_byte_postinc(UECFG1X, cfg);
  445. }
  446. }
  447. UERST = 0x1E;
  448. UERST = 0;
  449. return;
  450. }
  451. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  452. usb_wait_in_ready();
  453. UEDATX = usb_configuration;
  454. usb_send_in();
  455. return;
  456. }
  457. if (bRequest == GET_STATUS) {
  458. usb_wait_in_ready();
  459. i = 0;
  460. if (bmRequestType == 0x82) {
  461. UENUM = wIndex;
  462. if (UECONX & (1<<STALLRQ)) i = 1;
  463. UENUM = 0;
  464. }
  465. UEDATX = i;
  466. UEDATX = 0;
  467. usb_send_in();
  468. return;
  469. }
  470. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  471. && bmRequestType == 0x02 && wValue == 0) {
  472. i = wIndex & 0x7F;
  473. if (i >= 1 && i <= NUM_ENDPOINTS) {
  474. usb_send_in();
  475. UENUM = i;
  476. if (bRequest == SET_FEATURE) {
  477. UECONX = (1<<STALLRQ)|(1<<EPEN);
  478. } else {
  479. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  480. UERST = (1 << i);
  481. UERST = 0;
  482. }
  483. return;
  484. }
  485. }
  486. if (wIndex == RAWHID_INTERFACE) {
  487. if (bmRequestType == 0xA1 && bRequest == HID_GET_REPORT) {
  488. len = RAWHID_TX_SIZE;
  489. do {
  490. // wait for host ready for IN packet
  491. do {
  492. i = UEINTX;
  493. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  494. if (i & (1<<RXOUTI)) return; // abort
  495. // send IN packet
  496. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  497. for (i = n; i; i--) {
  498. // just send zeros
  499. UEDATX = 0;
  500. }
  501. len -= n;
  502. usb_send_in();
  503. } while (len || n == ENDPOINT0_SIZE);
  504. return;
  505. }
  506. if (bmRequestType == 0x21 && bRequest == HID_SET_REPORT) {
  507. len = RAWHID_RX_SIZE;
  508. do {
  509. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  510. usb_wait_receive_out();
  511. // ignore incoming bytes
  512. usb_ack_out();
  513. len -= n;
  514. } while (len);
  515. usb_wait_in_ready();
  516. usb_send_in();
  517. return;
  518. }
  519. }
  520. if (wIndex == DEBUG_INTERFACE) {
  521. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  522. len = wLength;
  523. do {
  524. // wait for host ready for IN packet
  525. do {
  526. i = UEINTX;
  527. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  528. if (i & (1<<RXOUTI)) return; // abort
  529. // send IN packet
  530. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  531. for (i = n; i; i--) {
  532. UEDATX = 0;
  533. }
  534. len -= n;
  535. usb_send_in();
  536. } while (len || n == ENDPOINT0_SIZE);
  537. return;
  538. }
  539. if (bRequest == HID_SET_REPORT && bmRequestType == 0x21) {
  540. if (wValue == 0x0300 && wLength == 0x0004) {
  541. uint8_t b1, b2, b3, b4;
  542. usb_wait_receive_out();
  543. b1 = UEDATX;
  544. b2 = UEDATX;
  545. b3 = UEDATX;
  546. b4 = UEDATX;
  547. usb_ack_out();
  548. usb_send_in();
  549. if (b1 == 0xA9 && b2 == 0x45 && b3 == 0xC2 && b4 == 0x6B)
  550. _reboot_Teensyduino_();
  551. if (b1 == 0x8B && b2 == 0xC5 && b3 == 0x1D && b4 == 0x70)
  552. _restart_Teensyduino_();
  553. }
  554. }
  555. }
  556. if (bRequest == 0xC9 && bmRequestType == 0x40) {
  557. usb_send_in();
  558. usb_wait_in_ready();
  559. _restart_Teensyduino_();
  560. }
  561. }
  562. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  563. }