A USB foot pedal for turning pages of PDF piano sheet music
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

usb_keyboard.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /* USB Keyboard Example for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/usb_keyboard.html
  3. * Copyright (c) 2009 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. // Version 1.0: Initial Release
  24. // Version 1.1: Add support for Teensy 2.0
  25. #define USB_SERIAL_PRIVATE_INCLUDE
  26. #include "usb_keyboard.h"
  27. /**************************************************************************
  28. *
  29. * Configurable Options
  30. *
  31. **************************************************************************/
  32. // You can change these to give your code its own name.
  33. #define STR_MANUFACTURER L"Clayton G. Hobbs"
  34. #define STR_PRODUCT L"Music Score Foot Pedal"
  35. // Mac OS-X and Linux automatically load the correct drivers. On
  36. // Windows, even though the driver is supplied by Microsoft, an
  37. // INF file is needed to load the driver. These numbers need to
  38. // match the INF file.
  39. #define VENDOR_ID 0x16C0
  40. #define PRODUCT_ID 0x047C
  41. // USB devices are supposed to implment a halt feature, which is
  42. // rarely (if ever) used. If you comment this line out, the halt
  43. // code will be removed, saving 102 bytes of space (gcc 4.3.0).
  44. // This is not strictly USB compliant, but works with all major
  45. // operating systems.
  46. #define SUPPORT_ENDPOINT_HALT
  47. /**************************************************************************
  48. *
  49. * Endpoint Buffer Configuration
  50. *
  51. **************************************************************************/
  52. #define ENDPOINT0_SIZE 32
  53. #define KEYBOARD_INTERFACE 0
  54. #define KEYBOARD_ENDPOINT 3
  55. #define KEYBOARD_SIZE 8
  56. #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
  57. static const uint8_t PROGMEM endpoint_config_table[] = {
  58. 0,
  59. 0,
  60. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
  61. 0
  62. };
  63. /**************************************************************************
  64. *
  65. * Descriptor Data
  66. *
  67. **************************************************************************/
  68. // Descriptors are the data that your computer reads when it auto-detects
  69. // this USB device (called "enumeration" in USB lingo). The most commonly
  70. // changed items are editable at the top of this file. Changing things
  71. // in here should only be done by those who've read chapter 9 of the USB
  72. // spec and relevant portions of any USB class specifications!
  73. static const uint8_t PROGMEM device_descriptor[] = {
  74. 18, // bLength
  75. 1, // bDescriptorType
  76. 0x00, 0x02, // bcdUSB
  77. 0, // bDeviceClass
  78. 0, // bDeviceSubClass
  79. 0, // bDeviceProtocol
  80. ENDPOINT0_SIZE, // bMaxPacketSize0
  81. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  82. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  83. 0x00, 0x01, // bcdDevice
  84. 1, // iManufacturer
  85. 2, // iProduct
  86. 0, // iSerialNumber
  87. 1 // bNumConfigurations
  88. };
  89. // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
  90. static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
  91. 0x05, 0x01, // Usage Page (Generic Desktop),
  92. 0x09, 0x06, // Usage (Keyboard),
  93. 0xA1, 0x01, // Collection (Application),
  94. 0x75, 0x01, // Report Size (1),
  95. 0x95, 0x08, // Report Count (8),
  96. 0x05, 0x07, // Usage Page (Key Codes),
  97. 0x19, 0xE0, // Usage Minimum (224),
  98. 0x29, 0xE7, // Usage Maximum (231),
  99. 0x15, 0x00, // Logical Minimum (0),
  100. 0x25, 0x01, // Logical Maximum (1),
  101. 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
  102. 0x95, 0x01, // Report Count (1),
  103. 0x75, 0x08, // Report Size (8),
  104. 0x81, 0x03, // Input (Constant), ;Reserved byte
  105. 0x95, 0x05, // Report Count (5),
  106. 0x75, 0x01, // Report Size (1),
  107. 0x05, 0x08, // Usage Page (LEDs),
  108. 0x19, 0x01, // Usage Minimum (1),
  109. 0x29, 0x05, // Usage Maximum (5),
  110. 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
  111. 0x95, 0x01, // Report Count (1),
  112. 0x75, 0x03, // Report Size (3),
  113. 0x91, 0x03, // Output (Constant), ;LED report padding
  114. 0x95, 0x06, // Report Count (6),
  115. 0x75, 0x08, // Report Size (8),
  116. 0x15, 0x00, // Logical Minimum (0),
  117. 0x25, 0x68, // Logical Maximum(104),
  118. 0x05, 0x07, // Usage Page (Key Codes),
  119. 0x19, 0x00, // Usage Minimum (0),
  120. 0x29, 0x68, // Usage Maximum (104),
  121. 0x81, 0x00, // Input (Data, Array),
  122. 0xc0 // End Collection
  123. };
  124. #define CONFIG1_DESC_SIZE (9+9+9+7)
  125. #define KEYBOARD_HID_DESC_OFFSET (9+9)
  126. static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  127. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  128. 9, // bLength;
  129. 2, // bDescriptorType;
  130. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  131. MSB(CONFIG1_DESC_SIZE),
  132. 1, // bNumInterfaces
  133. 1, // bConfigurationValue
  134. 0, // iConfiguration
  135. 0xC0, // bmAttributes
  136. 50, // bMaxPower
  137. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  138. 9, // bLength
  139. 4, // bDescriptorType
  140. KEYBOARD_INTERFACE, // bInterfaceNumber
  141. 0, // bAlternateSetting
  142. 1, // bNumEndpoints
  143. 0x03, // bInterfaceClass (0x03 = HID)
  144. 0x01, // bInterfaceSubClass (0x01 = Boot)
  145. 0x01, // bInterfaceProtocol (0x01 = Keyboard)
  146. 0, // iInterface
  147. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  148. 9, // bLength
  149. 0x21, // bDescriptorType
  150. 0x11, 0x01, // bcdHID
  151. 0, // bCountryCode
  152. 1, // bNumDescriptors
  153. 0x22, // bDescriptorType
  154. sizeof(keyboard_hid_report_desc), // wDescriptorLength
  155. 0,
  156. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  157. 7, // bLength
  158. 5, // bDescriptorType
  159. KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
  160. 0x03, // bmAttributes (0x03=intr)
  161. KEYBOARD_SIZE, 0, // wMaxPacketSize
  162. 1 // bInterval
  163. };
  164. // If you're desperate for a little extra code memory, these strings
  165. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  166. // in the device desciptor are changed to zeros.
  167. struct usb_string_descriptor_struct {
  168. uint8_t bLength;
  169. uint8_t bDescriptorType;
  170. int16_t wString[];
  171. };
  172. static const struct usb_string_descriptor_struct PROGMEM string0 = {
  173. 4,
  174. 3,
  175. {0x0409}
  176. };
  177. static const struct usb_string_descriptor_struct PROGMEM string1 = {
  178. sizeof(STR_MANUFACTURER),
  179. 3,
  180. STR_MANUFACTURER
  181. };
  182. static const struct usb_string_descriptor_struct PROGMEM string2 = {
  183. sizeof(STR_PRODUCT),
  184. 3,
  185. STR_PRODUCT
  186. };
  187. // This table defines which descriptor data is sent for each specific
  188. // request from the host (in wValue and wIndex).
  189. static struct descriptor_list_struct {
  190. uint16_t wValue;
  191. uint16_t wIndex;
  192. const uint8_t *addr;
  193. uint8_t length;
  194. } const PROGMEM descriptor_list[] = {
  195. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  196. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  197. {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
  198. {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
  199. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  200. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
  201. {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
  202. };
  203. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  204. /**************************************************************************
  205. *
  206. * Variables - these are the only non-stack RAM usage
  207. *
  208. **************************************************************************/
  209. // zero when we are not configured, non-zero when enumerated
  210. static volatile uint8_t usb_configuration=0;
  211. // which modifier keys are currently pressed
  212. // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
  213. // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
  214. uint8_t keyboard_modifier_keys=0;
  215. // which keys are currently pressed, up to 6 keys may be down at once
  216. uint8_t keyboard_keys[6]={0,0,0,0,0,0};
  217. // protocol setting from the host. We use exactly the same report
  218. // either way, so this variable only stores the setting since we
  219. // are required to be able to report which setting is in use.
  220. static uint8_t keyboard_protocol=1;
  221. // the idle configuration, how often we send the report to the
  222. // host (ms * 4) even when it hasn't changed
  223. static uint8_t keyboard_idle_config=125;
  224. // count until idle timeout
  225. static uint8_t keyboard_idle_count=0;
  226. // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
  227. volatile uint8_t keyboard_leds=0;
  228. /**************************************************************************
  229. *
  230. * Public Functions - these are the API intended for the user
  231. *
  232. **************************************************************************/
  233. // initialize USB
  234. void usb_init(void)
  235. {
  236. HW_CONFIG();
  237. USB_FREEZE(); // enable USB
  238. PLL_CONFIG(); // config PLL
  239. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  240. USB_CONFIG(); // start USB clock
  241. UDCON = 0; // enable attach resistor
  242. usb_configuration = 0;
  243. UDIEN = (1<<EORSTE)|(1<<SOFE);
  244. sei();
  245. }
  246. // return 0 if the USB is not configured, or the configuration
  247. // number selected by the HOST
  248. uint8_t usb_configured(void)
  249. {
  250. return usb_configuration;
  251. }
  252. // perform a single keystroke
  253. int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
  254. {
  255. int8_t r;
  256. keyboard_modifier_keys = modifier;
  257. keyboard_keys[0] = key;
  258. r = usb_keyboard_send();
  259. if (r) return r;
  260. keyboard_modifier_keys = 0;
  261. keyboard_keys[0] = 0;
  262. return usb_keyboard_send();
  263. }
  264. // send the contents of keyboard_keys and keyboard_modifier_keys
  265. int8_t usb_keyboard_send(void)
  266. {
  267. uint8_t i, intr_state, timeout;
  268. if (!usb_configuration) return -1;
  269. intr_state = SREG;
  270. cli();
  271. UENUM = KEYBOARD_ENDPOINT;
  272. timeout = UDFNUML + 50;
  273. while (1) {
  274. // are we ready to transmit?
  275. if (UEINTX & (1<<RWAL)) break;
  276. SREG = intr_state;
  277. // has the USB gone offline?
  278. if (!usb_configuration) return -1;
  279. // have we waited too long?
  280. if (UDFNUML == timeout) return -1;
  281. // get ready to try checking again
  282. intr_state = SREG;
  283. cli();
  284. UENUM = KEYBOARD_ENDPOINT;
  285. }
  286. UEDATX = keyboard_modifier_keys;
  287. UEDATX = 0;
  288. for (i=0; i<6; i++) {
  289. UEDATX = keyboard_keys[i];
  290. }
  291. UEINTX = 0x3A;
  292. keyboard_idle_count = 0;
  293. SREG = intr_state;
  294. return 0;
  295. }
  296. /**************************************************************************
  297. *
  298. * Private Functions - not intended for general user consumption....
  299. *
  300. **************************************************************************/
  301. // USB Device Interrupt - handle all device-level events
  302. // the transmit buffer flushing is triggered by the start of frame
  303. //
  304. ISR(USB_GEN_vect)
  305. {
  306. uint8_t intbits, t, i;
  307. static uint8_t div4=0;
  308. intbits = UDINT;
  309. UDINT = 0;
  310. if (intbits & (1<<EORSTI)) {
  311. UENUM = 0;
  312. UECONX = 1;
  313. UECFG0X = EP_TYPE_CONTROL;
  314. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  315. UEIENX = (1<<RXSTPE);
  316. usb_configuration = 0;
  317. }
  318. if ((intbits & (1<<SOFI)) && usb_configuration) {
  319. if (keyboard_idle_config && (++div4 & 3) == 0) {
  320. UENUM = KEYBOARD_ENDPOINT;
  321. if (UEINTX & (1<<RWAL)) {
  322. keyboard_idle_count++;
  323. if (keyboard_idle_count == keyboard_idle_config) {
  324. keyboard_idle_count = 0;
  325. UEDATX = keyboard_modifier_keys;
  326. UEDATX = 0;
  327. for (i=0; i<6; i++) {
  328. UEDATX = keyboard_keys[i];
  329. }
  330. UEINTX = 0x3A;
  331. }
  332. }
  333. }
  334. }
  335. }
  336. // Misc functions to wait for ready and send/receive packets
  337. static inline void usb_wait_in_ready(void)
  338. {
  339. while (!(UEINTX & (1<<TXINI))) ;
  340. }
  341. static inline void usb_send_in(void)
  342. {
  343. UEINTX = ~(1<<TXINI);
  344. }
  345. static inline void usb_wait_receive_out(void)
  346. {
  347. while (!(UEINTX & (1<<RXOUTI))) ;
  348. }
  349. static inline void usb_ack_out(void)
  350. {
  351. UEINTX = ~(1<<RXOUTI);
  352. }
  353. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  354. // other endpoints are manipulated by the user-callable
  355. // functions, and the start-of-frame interrupt.
  356. //
  357. ISR(USB_COM_vect)
  358. {
  359. uint8_t intbits;
  360. const uint8_t *list;
  361. const uint8_t *cfg;
  362. uint8_t i, n, len, en;
  363. uint8_t bmRequestType;
  364. uint8_t bRequest;
  365. uint16_t wValue;
  366. uint16_t wIndex;
  367. uint16_t wLength;
  368. uint16_t desc_val;
  369. const uint8_t *desc_addr;
  370. uint8_t desc_length;
  371. UENUM = 0;
  372. intbits = UEINTX;
  373. if (intbits & (1<<RXSTPI)) {
  374. bmRequestType = UEDATX;
  375. bRequest = UEDATX;
  376. wValue = UEDATX;
  377. wValue |= (UEDATX << 8);
  378. wIndex = UEDATX;
  379. wIndex |= (UEDATX << 8);
  380. wLength = UEDATX;
  381. wLength |= (UEDATX << 8);
  382. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  383. if (bRequest == GET_DESCRIPTOR) {
  384. list = (const uint8_t *)descriptor_list;
  385. for (i=0; ; i++) {
  386. if (i >= NUM_DESC_LIST) {
  387. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  388. return;
  389. }
  390. desc_val = pgm_read_word(list);
  391. if (desc_val != wValue) {
  392. list += sizeof(struct descriptor_list_struct);
  393. continue;
  394. }
  395. list += 2;
  396. desc_val = pgm_read_word(list);
  397. if (desc_val != wIndex) {
  398. list += sizeof(struct descriptor_list_struct)-2;
  399. continue;
  400. }
  401. list += 2;
  402. desc_addr = (const uint8_t *)pgm_read_word(list);
  403. list += 2;
  404. desc_length = pgm_read_byte(list);
  405. break;
  406. }
  407. len = (wLength < 256) ? wLength : 255;
  408. if (len > desc_length) len = desc_length;
  409. do {
  410. // wait for host ready for IN packet
  411. do {
  412. i = UEINTX;
  413. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  414. if (i & (1<<RXOUTI)) return; // abort
  415. // send IN packet
  416. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  417. for (i = n; i; i--) {
  418. UEDATX = pgm_read_byte(desc_addr++);
  419. }
  420. len -= n;
  421. usb_send_in();
  422. } while (len || n == ENDPOINT0_SIZE);
  423. return;
  424. }
  425. if (bRequest == SET_ADDRESS) {
  426. usb_send_in();
  427. usb_wait_in_ready();
  428. UDADDR = wValue | (1<<ADDEN);
  429. return;
  430. }
  431. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  432. usb_configuration = wValue;
  433. usb_send_in();
  434. cfg = endpoint_config_table;
  435. for (i=1; i<5; i++) {
  436. UENUM = i;
  437. en = pgm_read_byte(cfg++);
  438. UECONX = en;
  439. if (en) {
  440. UECFG0X = pgm_read_byte(cfg++);
  441. UECFG1X = pgm_read_byte(cfg++);
  442. }
  443. }
  444. UERST = 0x1E;
  445. UERST = 0;
  446. return;
  447. }
  448. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  449. usb_wait_in_ready();
  450. UEDATX = usb_configuration;
  451. usb_send_in();
  452. return;
  453. }
  454. if (bRequest == GET_STATUS) {
  455. usb_wait_in_ready();
  456. i = 0;
  457. #ifdef SUPPORT_ENDPOINT_HALT
  458. if (bmRequestType == 0x82) {
  459. UENUM = wIndex;
  460. if (UECONX & (1<<STALLRQ)) i = 1;
  461. UENUM = 0;
  462. }
  463. #endif
  464. UEDATX = i;
  465. UEDATX = 0;
  466. usb_send_in();
  467. return;
  468. }
  469. #ifdef SUPPORT_ENDPOINT_HALT
  470. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  471. && bmRequestType == 0x02 && wValue == 0) {
  472. i = wIndex & 0x7F;
  473. if (i >= 1 && i <= MAX_ENDPOINT) {
  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. #endif
  487. if (wIndex == KEYBOARD_INTERFACE) {
  488. if (bmRequestType == 0xA1) {
  489. if (bRequest == HID_GET_REPORT) {
  490. usb_wait_in_ready();
  491. UEDATX = keyboard_modifier_keys;
  492. UEDATX = 0;
  493. for (i=0; i<6; i++) {
  494. UEDATX = keyboard_keys[i];
  495. }
  496. usb_send_in();
  497. return;
  498. }
  499. if (bRequest == HID_GET_IDLE) {
  500. usb_wait_in_ready();
  501. UEDATX = keyboard_idle_config;
  502. usb_send_in();
  503. return;
  504. }
  505. if (bRequest == HID_GET_PROTOCOL) {
  506. usb_wait_in_ready();
  507. UEDATX = keyboard_protocol;
  508. usb_send_in();
  509. return;
  510. }
  511. }
  512. if (bmRequestType == 0x21) {
  513. if (bRequest == HID_SET_REPORT) {
  514. usb_wait_receive_out();
  515. keyboard_leds = UEDATX;
  516. usb_ack_out();
  517. usb_send_in();
  518. return;
  519. }
  520. if (bRequest == HID_SET_IDLE) {
  521. keyboard_idle_config = (wValue >> 8);
  522. keyboard_idle_count = 0;
  523. usb_send_in();
  524. return;
  525. }
  526. if (bRequest == HID_SET_PROTOCOL) {
  527. keyboard_protocol = wValue;
  528. usb_send_in();
  529. return;
  530. }
  531. }
  532. }
  533. }
  534. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  535. }