Teensy 4.1 core updated for 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.

632 lines
21KB

  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_BULK_IN, EP_SIZE(MIDI_TX_SIZE) | MIDI_TX_BUFFER,
  34. 1, EP_TYPE_BULK_OUT, EP_SIZE(MIDI_RX_SIZE) | MIDI_RX_BUFFER
  35. };
  36. /**************************************************************************
  37. *
  38. * Descriptor Data
  39. *
  40. **************************************************************************/
  41. // Descriptors are the data that your computer reads when it auto-detects
  42. // this USB device (called "enumeration" in USB lingo). The most commonly
  43. // changed items are editable at the top of this file. Changing things
  44. // in here should only be done by those who've read chapter 9 of the USB
  45. // spec and relevant portions of any USB class specifications!
  46. static const uint8_t PROGMEM device_descriptor[] = {
  47. 18, // bLength
  48. 1, // bDescriptorType
  49. 0x00, 0x02, // bcdUSB
  50. 0, // bDeviceClass
  51. 0, // bDeviceSubClass
  52. 0, // bDeviceProtocol
  53. ENDPOINT0_SIZE, // bMaxPacketSize0
  54. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  55. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  56. 0x00, 0x01, // bcdDevice
  57. 0, // iManufacturer
  58. 1, // iProduct
  59. 0, // iSerialNumber
  60. 1 // bNumConfigurations
  61. };
  62. static const uint8_t PROGMEM debug_hid_report_desc[] = {
  63. 0x06, 0xC9, 0xFF, // Usage Page 0xFFC9 (vendor defined)
  64. 0x09, 0x04, // Usage 0x04
  65. 0xA1, 0x5C, // Collection 0x5C
  66. 0x75, 0x08, // report size = 8 bits (global)
  67. 0x15, 0x00, // logical minimum = 0 (global)
  68. 0x26, 0xFF, 0x00, // logical maximum = 255 (global)
  69. 0x95, DEBUG_TX_SIZE, // report count (global)
  70. 0x09, 0x75, // usage (local)
  71. 0x81, 0x02, // Input
  72. 0x95, DEBUG_RX_SIZE, // report count (global)
  73. 0x09, 0x76, // usage (local)
  74. 0x91, 0x02, // Output
  75. 0x95, 0x04, // report count (global)
  76. 0x09, 0x76, // usage (local)
  77. 0xB1, 0x02, // Feature
  78. 0xC0 // end collection
  79. };
  80. #define CONFIG1_DESC_SIZE ( 9 + 74 + 32 )
  81. #define DEBUG_HID_DESC_OFFSET ( 9 + 74 + 9 )
  82. //#define CONFIG1_DESC_SIZE ( 9 + 92 + 32 )
  83. //#define DEBUG_HID_DESC_OFFSET ( 9 + 92 + 9 )
  84. static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  85. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  86. 9, // bLength;
  87. 2, // bDescriptorType;
  88. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  89. MSB(CONFIG1_DESC_SIZE),
  90. NUM_INTERFACE, // bNumInterfaces
  91. 1, // bConfigurationValue
  92. 0, // iConfiguration
  93. 0xC0, // bmAttributes
  94. 50, // bMaxPower
  95. // This MIDI stuff is a copy of the example from the Audio Class
  96. // MIDI spec 1.0 (Nov 1, 1999), Appendix B, pages 37 to 43.
  97. #if 0
  98. http://www.usb.org/developers/devclass_docs/midi10.pdf
  99. Section B.3 seems to say these extra descriptors are required,
  100. but when I add them, MIDI breaks on Linux (haven't tried Mac and
  101. Windows yet). TODO: investigate these....
  102. reported by "John K." on May 7, 2012, subject "USB MIDI descriptors"
  103. // Standard AC Interface Descriptor
  104. 9, // bLength
  105. 4, // bDescriptorType = INTERFACE
  106. 0, // bInterfaceNumber
  107. 0, // bAlternateSetting
  108. 0, // bNumEndpoints
  109. 1, // bInterfaceClass = AUDIO
  110. 1, // bInterfaceSubclass = AUDIO_CONTROL
  111. 0, // bInterfaceProtocol
  112. 0, // iInterface
  113. // Class-specific AC Interface Descriptor
  114. 9, // bLength
  115. 0x24, // bDescriptorType = CS_INTERFACE
  116. 1, // bDescriptorSubtype = HEADER
  117. 0x00, 0x01, // bcdADC
  118. 0x09, 0x00, // wTotalLength
  119. 1, // bInCollection
  120. 1, // baInterfaceNr(1)
  121. #endif
  122. // Standard MS Interface Descriptor,
  123. 9, // bLength
  124. 4, // bDescriptorType
  125. MIDI_INTERFACE, // bInterfaceNumber
  126. 0, // bAlternateSetting
  127. 2, // bNumEndpoints
  128. 0x01, // bInterfaceClass (0x01 = Audio)
  129. 0x03, // bInterfaceSubClass (0x03 = MIDI)
  130. 0x00, // bInterfaceProtocol (unused for MIDI)
  131. 0, // iInterface
  132. // MIDI MS Interface Header, USB MIDI 6.1.2.1, page 21, Table 6-2
  133. 7, // bLength
  134. 0x24, // bDescriptorType = CS_INTERFACE
  135. 0x01, // bDescriptorSubtype = MS_HEADER
  136. 0x00, 0x01, // bcdMSC = revision 01.00
  137. 0x41, 0x00, // wTotalLength
  138. // MIDI IN Jack Descriptor, B.4.3, Table B-7 (embedded), page 40
  139. 6, // bLength
  140. 0x24, // bDescriptorType = CS_INTERFACE
  141. 0x02, // bDescriptorSubtype = MIDI_IN_JACK
  142. 0x01, // bJackType = EMBEDDED
  143. 1, // bJackID, ID = 1
  144. 0, // iJack
  145. // MIDI IN Jack Descriptor, B.4.3, Table B-8 (external), page 40
  146. 6, // bLength
  147. 0x24, // bDescriptorType = CS_INTERFACE
  148. 0x02, // bDescriptorSubtype = MIDI_IN_JACK
  149. 0x02, // bJackType = EXTERNAL
  150. 2, // bJackID, ID = 2
  151. 0, // iJack
  152. // MIDI OUT Jack Descriptor, B.4.4, Table B-9, page 41
  153. 9,
  154. 0x24, // bDescriptorType = CS_INTERFACE
  155. 0x03, // bDescriptorSubtype = MIDI_OUT_JACK
  156. 0x01, // bJackType = EMBEDDED
  157. 3, // bJackID, ID = 3
  158. 1, // bNrInputPins = 1 pin
  159. 2, // BaSourceID(1) = 2
  160. 1, // BaSourcePin(1) = first pin
  161. 0, // iJack
  162. // MIDI OUT Jack Descriptor, B.4.4, Table B-10, page 41
  163. 9,
  164. 0x24, // bDescriptorType = CS_INTERFACE
  165. 0x03, // bDescriptorSubtype = MIDI_OUT_JACK
  166. 0x02, // bJackType = EXTERNAL
  167. 4, // bJackID, ID = 4
  168. 1, // bNrInputPins = 1 pin
  169. 1, // BaSourceID(1) = 1
  170. 1, // BaSourcePin(1) = first pin
  171. 0, // iJack
  172. // Standard Bulk OUT Endpoint Descriptor, B.5.1, Table B-11, pae 42
  173. 9, // bLength
  174. 5, // bDescriptorType = ENDPOINT
  175. MIDI_RX_ENDPOINT, // bEndpointAddress
  176. 0x02, // bmAttributes (0x02=bulk)
  177. MIDI_RX_SIZE, 0, // wMaxPacketSize
  178. 0, // bInterval
  179. 0, // bRefresh
  180. 0, // bSynchAddress
  181. // Class-specific MS Bulk OUT Endpoint Descriptor, B.5.2, Table B-12, page 42
  182. 5, // bLength
  183. 0x25, // bDescriptorSubtype = CS_ENDPOINT
  184. 0x01, // bJackType = MS_GENERAL
  185. 1, // bNumEmbMIDIJack = 1 jack
  186. 1, // BaAssocJackID(1) = jack ID #1
  187. // Standard Bulk IN Endpoint Descriptor, B.5.1, Table B-11, pae 42
  188. 9, // bLength
  189. 5, // bDescriptorType = ENDPOINT
  190. MIDI_TX_ENDPOINT | 0x80, // bEndpointAddress
  191. 0x02, // bmAttributes (0x02=bulk)
  192. MIDI_TX_SIZE, 0, // wMaxPacketSize
  193. 0, // bInterval
  194. 0, // bRefresh
  195. 0, // bSynchAddress
  196. // Class-specific MS Bulk IN Endpoint Descriptor, B.5.2, Table B-12, page 42
  197. 5, // bLength
  198. 0x25, // bDescriptorSubtype = CS_ENDPOINT
  199. 0x01, // bJackType = MS_GENERAL
  200. 1, // bNumEmbMIDIJack = 1 jack
  201. 3, // BaAssocJackID(1) = jack ID #3
  202. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  203. 9, // bLength
  204. 4, // bDescriptorType
  205. DEBUG_INTERFACE, // bInterfaceNumber
  206. 0, // bAlternateSetting
  207. 2, // bNumEndpoints
  208. 0x03, // bInterfaceClass (0x03 = HID)
  209. 0x00, // bInterfaceSubClass
  210. 0x00, // bInterfaceProtocol
  211. 0, // iInterface
  212. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  213. 9, // bLength
  214. 0x21, // bDescriptorType
  215. 0x11, 0x01, // bcdHID
  216. 0, // bCountryCode
  217. 1, // bNumDescriptors
  218. 0x22, // bDescriptorType
  219. sizeof(debug_hid_report_desc), // wDescriptorLength
  220. 0,
  221. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  222. 7, // bLength
  223. 5, // bDescriptorType
  224. DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
  225. 0x03, // bmAttributes (0x03=intr)
  226. DEBUG_TX_SIZE, 0, // wMaxPacketSize
  227. DEBUG_TX_INTERVAL, // bInterval
  228. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  229. 7, // bLength
  230. 5, // bDescriptorType
  231. DEBUG_RX_ENDPOINT, // bEndpointAddress
  232. 0x03, // bmAttributes (0x03=intr)
  233. DEBUG_RX_SIZE, 0, // wMaxPacketSize
  234. DEBUG_RX_INTERVAL, // bInterval
  235. };
  236. // If you're desperate for a little extra code memory, these strings
  237. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  238. // in the device desciptor are changed to zeros.
  239. struct usb_string_descriptor_struct {
  240. uint8_t bLength;
  241. uint8_t bDescriptorType;
  242. int16_t wString[];
  243. };
  244. static const struct usb_string_descriptor_struct PROGMEM string0 = {
  245. 4,
  246. 3,
  247. {0x0409}
  248. };
  249. static const struct usb_string_descriptor_struct PROGMEM string1 = {
  250. sizeof(STR_PRODUCT),
  251. 3,
  252. STR_PRODUCT
  253. };
  254. // This table defines which descriptor data is sent for each specific
  255. // request from the host (in wValue and wIndex).
  256. static const struct descriptor_list_struct {
  257. uint16_t wValue;
  258. uint16_t wIndex;
  259. const uint8_t *addr;
  260. uint8_t length;
  261. } PROGMEM descriptor_list[] = {
  262. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  263. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  264. {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
  265. {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
  266. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  267. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_PRODUCT)},
  268. };
  269. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  270. /**************************************************************************
  271. *
  272. * Variables - these are the only non-stack RAM usage
  273. *
  274. **************************************************************************/
  275. // zero when we are not configured, non-zero when enumerated
  276. volatile uint8_t usb_configuration USBSTATE;
  277. volatile uint8_t usb_suspended USBSTATE;
  278. // the time remaining before we transmit any partially full
  279. // packet, or send a zero length packet.
  280. volatile uint8_t debug_flush_timer USBSTATE;
  281. /**************************************************************************
  282. *
  283. * Public Functions - these are the API intended for the user
  284. *
  285. **************************************************************************/
  286. // initialize USB serial
  287. void usb_init(void)
  288. {
  289. uint8_t u;
  290. u = USBCON;
  291. if ((u & (1<<USBE)) && !(u & (1<<FRZCLK))) return;
  292. HW_CONFIG();
  293. USB_FREEZE(); // enable USB
  294. PLL_CONFIG(); // config PLL
  295. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  296. USB_CONFIG(); // start USB clock
  297. UDCON = 0; // enable attach resistor
  298. usb_configuration = 0;
  299. usb_suspended = 0;
  300. debug_flush_timer = 0;
  301. UDINT = 0;
  302. UDIEN = (1<<EORSTE)|(1<<SOFE);
  303. //sei(); // init() in wiring.c does this
  304. }
  305. void usb_shutdown(void)
  306. {
  307. UDIEN = 0; // disable interrupts
  308. UDCON = 1; // disconnect attach resistor
  309. USBCON = 0; // shut off USB periperal
  310. PLLCSR = 0; // shut off PLL
  311. usb_configuration = 0;
  312. usb_suspended = 1;
  313. }
  314. // Public API functions moved to usb_api.cpp
  315. /**************************************************************************
  316. *
  317. * Private Functions - not intended for general user consumption....
  318. *
  319. **************************************************************************/
  320. // USB Device Interrupt - handle all device-level events
  321. // the transmit buffer flushing is triggered by the start of frame
  322. //
  323. ISR(USB_GEN_vect)
  324. {
  325. uint8_t intbits, t;
  326. intbits = UDINT;
  327. UDINT = 0;
  328. if (intbits & (1<<EORSTI)) {
  329. UENUM = 0;
  330. UECONX = 1;
  331. UECFG0X = EP_TYPE_CONTROL;
  332. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  333. UEIENX = (1<<RXSTPE);
  334. usb_configuration = 0;
  335. }
  336. if ((intbits & (1<<SOFI)) && usb_configuration) {
  337. t = debug_flush_timer;
  338. if (t) {
  339. debug_flush_timer = --t;
  340. if (!t) {
  341. UENUM = DEBUG_TX_ENDPOINT;
  342. while ((UEINTX & (1<<RWAL))) {
  343. UEDATX = 0;
  344. }
  345. UEINTX = 0x3A;
  346. }
  347. }
  348. UENUM = MIDI_TX_ENDPOINT;
  349. if (UEBCLX) UEINTX = 0x3A;
  350. }
  351. if (intbits & (1<<SUSPI)) {
  352. // USB Suspend (inactivity for 3ms)
  353. UDIEN = (1<<WAKEUPE);
  354. usb_configuration = 0;
  355. usb_suspended = 1;
  356. #if (F_CPU >= 8000000L)
  357. // WAKEUPI does not work with USB clock freeze
  358. // when CPU is running less than 8 MHz.
  359. // Is this a hardware bug?
  360. USB_FREEZE(); // shut off USB
  361. PLLCSR = 0; // shut off PLL
  362. #endif
  363. // to properly meet the USB spec, current must
  364. // reduce to less than 2.5 mA, which means using
  365. // powerdown mode, but that breaks the Arduino
  366. // user's paradigm....
  367. }
  368. if (usb_suspended && (intbits & (1<<WAKEUPI))) {
  369. // USB Resume (pretty much any activity)
  370. #if (F_CPU >= 8000000L)
  371. PLL_CONFIG();
  372. while (!(PLLCSR & (1<<PLOCK))) ;
  373. USB_CONFIG();
  374. #endif
  375. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  376. usb_suspended = 0;
  377. return;
  378. }
  379. }
  380. // Misc functions to wait for ready and send/receive packets
  381. static inline void usb_wait_in_ready(void)
  382. {
  383. while (!(UEINTX & (1<<TXINI))) ;
  384. }
  385. static inline void usb_send_in(void)
  386. {
  387. UEINTX = ~(1<<TXINI);
  388. }
  389. static inline void usb_wait_receive_out(void)
  390. {
  391. while (!(UEINTX & (1<<RXOUTI))) ;
  392. }
  393. static inline void usb_ack_out(void)
  394. {
  395. UEINTX = ~(1<<RXOUTI);
  396. }
  397. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  398. // other endpoints are manipulated by the user-callable
  399. // functions, and the start-of-frame interrupt.
  400. //
  401. ISR(USB_COM_vect)
  402. {
  403. uint8_t intbits;
  404. const uint8_t *list;
  405. const uint8_t *cfg;
  406. uint8_t i, n, len, en;
  407. uint8_t bmRequestType;
  408. uint8_t bRequest;
  409. uint16_t wValue;
  410. uint16_t wIndex;
  411. uint16_t wLength;
  412. uint16_t desc_val;
  413. const uint8_t *desc_addr;
  414. uint8_t desc_length;
  415. UENUM = 0;
  416. intbits = UEINTX;
  417. if (intbits & (1<<RXSTPI)) {
  418. bmRequestType = UEDATX;
  419. bRequest = UEDATX;
  420. read_word_lsbfirst(wValue, UEDATX);
  421. read_word_lsbfirst(wIndex, UEDATX);
  422. read_word_lsbfirst(wLength, UEDATX);
  423. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  424. if (bRequest == GET_DESCRIPTOR) {
  425. list = (const uint8_t *)descriptor_list;
  426. for (i=0; ; i++) {
  427. if (i >= NUM_DESC_LIST) {
  428. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  429. return;
  430. }
  431. pgm_read_word_postinc(desc_val, list);
  432. if (desc_val != wValue) {
  433. list += sizeof(struct descriptor_list_struct)-2;
  434. continue;
  435. }
  436. pgm_read_word_postinc(desc_val, list);
  437. if (desc_val != wIndex) {
  438. list += sizeof(struct descriptor_list_struct)-4;
  439. continue;
  440. }
  441. pgm_read_word_postinc(desc_addr, list);
  442. desc_length = pgm_read_byte(list);
  443. break;
  444. }
  445. len = (wLength < 256) ? wLength : 255;
  446. if (len > desc_length) len = desc_length;
  447. list = desc_addr;
  448. do {
  449. // wait for host ready for IN packet
  450. do {
  451. i = UEINTX;
  452. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  453. if (i & (1<<RXOUTI)) return; // abort
  454. // send IN packet
  455. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  456. for (i = n; i; i--) {
  457. pgm_read_byte_postinc(UEDATX, list);
  458. }
  459. len -= n;
  460. usb_send_in();
  461. } while (len || n == ENDPOINT0_SIZE);
  462. return;
  463. }
  464. if (bRequest == SET_ADDRESS) {
  465. usb_send_in();
  466. usb_wait_in_ready();
  467. UDADDR = wValue | (1<<ADDEN);
  468. return;
  469. }
  470. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  471. usb_configuration = wValue;
  472. debug_flush_timer = 0;
  473. usb_send_in();
  474. cfg = endpoint_config_table;
  475. for (i=1; i<NUM_ENDPOINTS; i++) {
  476. UENUM = i;
  477. pgm_read_byte_postinc(en, cfg);
  478. UECONX = en;
  479. if (en) {
  480. pgm_read_byte_postinc(UECFG0X, cfg);
  481. pgm_read_byte_postinc(UECFG1X, cfg);
  482. }
  483. }
  484. UERST = 0x1E;
  485. UERST = 0;
  486. return;
  487. }
  488. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  489. usb_wait_in_ready();
  490. UEDATX = usb_configuration;
  491. usb_send_in();
  492. return;
  493. }
  494. if (bRequest == GET_STATUS) {
  495. usb_wait_in_ready();
  496. i = 0;
  497. if (bmRequestType == 0x82) {
  498. UENUM = wIndex;
  499. if (UECONX & (1<<STALLRQ)) i = 1;
  500. UENUM = 0;
  501. }
  502. UEDATX = i;
  503. UEDATX = 0;
  504. usb_send_in();
  505. return;
  506. }
  507. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  508. && bmRequestType == 0x02 && wValue == 0) {
  509. i = wIndex & 0x7F;
  510. if (i >= 1 && i <= MAX_ENDPOINT) {
  511. usb_send_in();
  512. UENUM = i;
  513. if (bRequest == SET_FEATURE) {
  514. UECONX = (1<<STALLRQ)|(1<<EPEN);
  515. } else {
  516. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  517. UERST = (1 << i);
  518. UERST = 0;
  519. }
  520. return;
  521. }
  522. }
  523. if (wIndex == DEBUG_INTERFACE) {
  524. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  525. len = wLength;
  526. do {
  527. // wait for host ready for IN packet
  528. do {
  529. i = UEINTX;
  530. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  531. if (i & (1<<RXOUTI)) return; // abort
  532. // send IN packet
  533. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  534. for (i = n; i; i--) {
  535. UEDATX = 0;
  536. }
  537. len -= n;
  538. usb_send_in();
  539. } while (len || n == ENDPOINT0_SIZE);
  540. return;
  541. }
  542. if (bRequest == HID_SET_REPORT && bmRequestType == 0x21) {
  543. if (wValue == 0x0300 && wLength == 0x0004) {
  544. uint8_t b1, b2, b3, b4;
  545. usb_wait_receive_out();
  546. b1 = UEDATX;
  547. b2 = UEDATX;
  548. b3 = UEDATX;
  549. b4 = UEDATX;
  550. usb_ack_out();
  551. usb_send_in();
  552. if (b1 == 0xA9 && b2 == 0x45 && b3 == 0xC2 && b4 == 0x6B)
  553. _reboot_Teensyduino_();
  554. if (b1 == 0x8B && b2 == 0xC5 && b3 == 0x1D && b4 == 0x70)
  555. _restart_Teensyduino_();
  556. }
  557. }
  558. }
  559. if (bRequest == 0xC9 && bmRequestType == 0x40) {
  560. usb_send_in();
  561. usb_wait_in_ready();
  562. _restart_Teensyduino_();
  563. }
  564. }
  565. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  566. }