PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  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. #include "pauls_ugly_debug.h"
  26. /**************************************************************************
  27. *
  28. * Endpoint Buffer Configuration
  29. *
  30. **************************************************************************/
  31. static const uint8_t PROGMEM endpoint_config_table[] = {
  32. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER,
  33. 1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER,
  34. 1, EP_TYPE_BULK_OUT, EP_SIZE(DISK_RX_SIZE) | DISK_RX_BUFFER,
  35. 1, EP_TYPE_BULK_IN, EP_SIZE(DISK_TX_SIZE) | DISK_TX_BUFFER,
  36. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
  37. 0
  38. };
  39. /**************************************************************************
  40. *
  41. * Descriptor Data
  42. *
  43. **************************************************************************/
  44. // Descriptors are the data that your computer reads when it auto-detects
  45. // this USB device (called "enumeration" in USB lingo). The most commonly
  46. // changed items are editable at the top of this file. Changing things
  47. // in here should only be done by those who've read chapter 9 of the USB
  48. // spec and relevant portions of any USB class specifications!
  49. static const uint8_t PROGMEM device_descriptor[] = {
  50. 18, // bLength
  51. 1, // bDescriptorType
  52. 0x00, 0x02, // bcdUSB
  53. 0, // bDeviceClass
  54. 0, // bDeviceSubClass
  55. 0, // bDeviceProtocol
  56. ENDPOINT0_SIZE, // bMaxPacketSize0
  57. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  58. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  59. 0x00, 0x01, // bcdDevice
  60. 0, // iManufacturer
  61. 1, // iProduct
  62. 2, // iSerialNumber
  63. 1 // bNumConfigurations
  64. };
  65. // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
  66. static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
  67. 0x05, 0x01, // Usage Page (Generic Desktop),
  68. 0x09, 0x06, // Usage (Keyboard),
  69. 0xA1, 0x01, // Collection (Application),
  70. 0x75, 0x01, // Report Size (1),
  71. 0x95, 0x08, // Report Count (8),
  72. 0x05, 0x07, // Usage Page (Key Codes),
  73. 0x19, 0xE0, // Usage Minimum (224),
  74. 0x29, 0xE7, // Usage Maximum (231),
  75. 0x15, 0x00, // Logical Minimum (0),
  76. 0x25, 0x01, // Logical Maximum (1),
  77. 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
  78. 0x95, 0x01, // Report Count (1),
  79. 0x75, 0x08, // Report Size (8),
  80. 0x81, 0x03, // Input (Constant), ;Reserved byte
  81. 0x95, 0x05, // Report Count (5),
  82. 0x75, 0x01, // Report Size (1),
  83. 0x05, 0x08, // Usage Page (LEDs),
  84. 0x19, 0x01, // Usage Minimum (1),
  85. 0x29, 0x05, // Usage Maximum (5),
  86. 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
  87. 0x95, 0x01, // Report Count (1),
  88. 0x75, 0x03, // Report Size (3),
  89. 0x91, 0x03, // Output (Constant), ;LED report padding
  90. 0x95, 0x06, // Report Count (6),
  91. 0x75, 0x08, // Report Size (8),
  92. 0x15, 0x00, // Logical Minimum (0),
  93. 0x25, 0x7F, // Logical Maximum(104),
  94. 0x05, 0x07, // Usage Page (Key Codes),
  95. 0x19, 0x00, // Usage Minimum (0),
  96. 0x29, 0x7F, // Usage Maximum (104),
  97. 0x81, 0x00, // Input (Data, Array),
  98. 0xc0 // End Collection
  99. };
  100. static const uint8_t PROGMEM debug_hid_report_desc[] = {
  101. 0x06, 0xC9, 0xFF, // Usage Page 0xFFC9 (vendor defined)
  102. 0x09, 0x04, // Usage 0x04
  103. 0xA1, 0x5C, // Collection 0x5C
  104. 0x75, 0x08, // report size = 8 bits (global)
  105. 0x15, 0x00, // logical minimum = 0 (global)
  106. 0x26, 0xFF, 0x00, // logical maximum = 255 (global)
  107. 0x95, DEBUG_TX_SIZE, // report count (global)
  108. 0x09, 0x75, // usage (local)
  109. 0x81, 0x02, // Input
  110. 0x95, DEBUG_RX_SIZE, // report count (global)
  111. 0x09, 0x76, // usage (local)
  112. 0x91, 0x02, // Output
  113. 0x95, 0x04, // report count (global)
  114. 0x09, 0x76, // usage (local)
  115. 0xB1, 0x02, // Feature
  116. 0xC0 // end collection
  117. };
  118. #define CONFIG1_DESC_SIZE ( 9 + 9+7+7 + 9+9+7 + 9+9+7+7 )
  119. #define KEYBOARD_HID_DESC_OFFSET ( 9 + 9+7+7 + 9 )
  120. #define DEBUG_HID_DESC_OFFSET ( 9 + 9+7+7 + 9+9+7 + 9 )
  121. static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  122. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  123. 9, // bLength;
  124. 2, // bDescriptorType;
  125. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  126. MSB(CONFIG1_DESC_SIZE),
  127. NUM_INTERFACE, // bNumInterfaces
  128. 1, // bConfigurationValue
  129. 0, // iConfiguration
  130. 0xC0, // bmAttributes
  131. 50, // bMaxPower
  132. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  133. 9, // bLength
  134. 4, // bDescriptorType
  135. DISK_INTERFACE, // bInterfaceNumber
  136. 0, // bAlternateSetting
  137. 2, // bNumEndpoints
  138. 0x08, // bInterfaceClass (8 = Mass Storage)
  139. 0x06, // bInterfaceSubClass (6 = SCSI transparent)
  140. 0x50, // bInterfaceProtocol (0x50 = bulk only transport)
  141. 0, // iInterface
  142. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  143. 7, // bLength
  144. 5, // bDescriptorType
  145. DISK_RX_ENDPOINT, // bEndpointAddress
  146. 0x02, // bmAttributes (0x02=bulk)
  147. DISK_RX_SIZE, 0, // wMaxPacketSize
  148. 0, // bInterval
  149. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  150. 7, // bLength
  151. 5, // bDescriptorType
  152. DISK_TX_ENDPOINT | 0x80, // bEndpointAddress
  153. 0x02, // bmAttributes (0x02=bulk)
  154. DISK_TX_SIZE, 0, // wMaxPacketSize
  155. 0, // bInterval
  156. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  157. 9, // bLength
  158. 4, // bDescriptorType
  159. KEYBOARD_INTERFACE, // bInterfaceNumber
  160. 0, // bAlternateSetting
  161. 1, // bNumEndpoints
  162. 0x03, // bInterfaceClass (0x03 = HID)
  163. 0x01, // bInterfaceSubClass (0x01 = Boot)
  164. 0x01, // bInterfaceProtocol (0x01 = Keyboard)
  165. 0, // iInterface
  166. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  167. 9, // bLength
  168. 0x21, // bDescriptorType
  169. 0x11, 0x01, // bcdHID
  170. 0, // bCountryCode
  171. 1, // bNumDescriptors
  172. 0x22, // bDescriptorType
  173. sizeof(keyboard_hid_report_desc), // wDescriptorLength
  174. 0,
  175. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  176. 7, // bLength
  177. 5, // bDescriptorType
  178. KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
  179. 0x03, // bmAttributes (0x03=intr)
  180. KEYBOARD_SIZE, 0, // wMaxPacketSize
  181. KEYBOARD_INTERVAL, // bInterval
  182. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  183. 9, // bLength
  184. 4, // bDescriptorType
  185. DEBUG_INTERFACE, // bInterfaceNumber
  186. 0, // bAlternateSetting
  187. 2, // bNumEndpoints
  188. 0x03, // bInterfaceClass (0x03 = HID)
  189. 0x00, // bInterfaceSubClass
  190. 0x00, // bInterfaceProtocol
  191. 0, // iInterface
  192. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  193. 9, // bLength
  194. 0x21, // bDescriptorType
  195. 0x11, 0x01, // bcdHID
  196. 0, // bCountryCode
  197. 1, // bNumDescriptors
  198. 0x22, // bDescriptorType
  199. sizeof(debug_hid_report_desc), // wDescriptorLength
  200. 0,
  201. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  202. 7, // bLength
  203. 5, // bDescriptorType
  204. DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
  205. 0x03, // bmAttributes (0x03=intr)
  206. DEBUG_TX_SIZE, 0, // wMaxPacketSize
  207. DEBUG_TX_INTERVAL, // bInterval
  208. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  209. 7, // bLength
  210. 5, // bDescriptorType
  211. DEBUG_RX_ENDPOINT, // bEndpointAddress
  212. 0x03, // bmAttributes (0x03=intr)
  213. DEBUG_RX_SIZE, 0, // wMaxPacketSize
  214. DEBUG_RX_INTERVAL, // bInterval
  215. };
  216. // If you're desperate for a little extra code memory, these strings
  217. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  218. // in the device desciptor are changed to zeros.
  219. struct usb_string_descriptor_struct {
  220. uint8_t bLength;
  221. uint8_t bDescriptorType;
  222. int16_t wString[];
  223. };
  224. static const struct usb_string_descriptor_struct PROGMEM string0 = {
  225. 4,
  226. 3,
  227. {0x0409}
  228. };
  229. static const struct usb_string_descriptor_struct PROGMEM string1 = {
  230. sizeof(STR_PRODUCT),
  231. 3,
  232. STR_PRODUCT
  233. };
  234. static const struct usb_string_descriptor_struct PROGMEM string2 = {
  235. sizeof(STR_SERIAL_NUMBER),
  236. 3,
  237. STR_SERIAL_NUMBER
  238. };
  239. // This table defines which descriptor data is sent for each specific
  240. // request from the host (in wValue and wIndex).
  241. static const struct descriptor_list_struct {
  242. uint16_t wValue;
  243. uint16_t wIndex;
  244. const uint8_t *addr;
  245. uint8_t length;
  246. } PROGMEM descriptor_list[] = {
  247. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  248. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  249. {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
  250. {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
  251. {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
  252. {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
  253. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  254. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_PRODUCT)},
  255. {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_SERIAL_NUMBER)},
  256. };
  257. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  258. static const uint8_t PROGMEM scsi_inquiry_response[] = {
  259. 0x00, // 0x00 = direct-access device
  260. 0x80, // 0x80 = removable media
  261. 0x04, // 0x04 = SPC-2 commands
  262. 0x02, // response format
  263. 0x20, // # bytes past this point
  264. 0x00,
  265. 0x00,
  266. 0x00,
  267. 'G','e','n','e','r','i','c',' ',
  268. 'U','S','B',' ','F','l','a','s','h',' ','D','i','s','c',' ',' ',
  269. '1','.','0','0'
  270. };
  271. /**************************************************************************
  272. *
  273. * Variables - these are the only non-stack RAM usage
  274. *
  275. **************************************************************************/
  276. // zero when we are not configured, non-zero when enumerated
  277. volatile uint8_t usb_configuration USBSTATE;
  278. volatile uint8_t usb_suspended USBSTATE;
  279. // the time remaining before we transmit any partially full
  280. // packet, or send a zero length packet.
  281. volatile uint8_t debug_flush_timer USBSTATE;
  282. // byte0: which modifier keys are currently pressed
  283. // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
  284. // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
  285. // byte1: media keys (TODO: document these)
  286. // bytes2-7: which keys are currently pressed, up to 6 keys may be down at once
  287. uint8_t keyboard_report_data[8] USBSTATE;
  288. // protocol setting from the host. We use exactly the same report
  289. // either way, so this variable only stores the setting since we
  290. // are required to be able to report which setting is in use.
  291. static uint8_t keyboard_protocol USBSTATE;
  292. // the idle configuration, how often we send the report to the
  293. // host (ms * 4) even when it hasn't changed
  294. static uint8_t keyboard_idle_config USBSTATE;
  295. // count until idle timeout
  296. uint8_t keyboard_idle_count USBSTATE;
  297. // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
  298. volatile uint8_t keyboard_leds USBSTATE;
  299. static volatile uint8_t ms_state USBSTATE;
  300. static volatile uint8_t ms_rdonly USBSTATE;
  301. static volatile uint8_t media_lock_state USBSTATE;
  302. #define MEDIA_LOCKED_BY_USER 1 // user locked media
  303. #define MEDIA_LOCKED_BY_ISR 2 // isr locked media
  304. #define MEDIA_ISR_LOCK_PENDING 4 // isr request while user locked
  305. /**************************************************************************
  306. *
  307. * Public Functions - these are the API intended for the user
  308. *
  309. **************************************************************************/
  310. void media_init(void);
  311. void media_restart(void);
  312. // initialize USB serial
  313. void usb_init(void)
  314. {
  315. uint8_t u;
  316. u = USBCON;
  317. if ((u & (1<<USBE)) && !(u & (1<<FRZCLK))) {
  318. media_restart();
  319. return;
  320. }
  321. HW_CONFIG();
  322. USB_FREEZE(); // enable USB
  323. PLL_CONFIG(); // config PLL
  324. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  325. USB_CONFIG(); // start USB clock
  326. UDCON = 0; // enable attach resistor
  327. usb_configuration = 0;
  328. usb_suspended = 0;
  329. debug_flush_timer = 0;
  330. keyboard_report_data[0] = 0;
  331. keyboard_report_data[1] = 0;
  332. keyboard_report_data[2] = 0;
  333. keyboard_report_data[3] = 0;
  334. keyboard_report_data[4] = 0;
  335. keyboard_report_data[5] = 0;
  336. keyboard_report_data[6] = 0;
  337. keyboard_report_data[7] = 0;
  338. keyboard_protocol = 1;
  339. keyboard_idle_config = 125;
  340. keyboard_idle_count = 0;
  341. keyboard_leds = 0;
  342. ms_state = MS_STATE_IDLE;
  343. media_lock_state = 0;
  344. UDINT = 0;
  345. UDIEN = (1<<EORSTE)|(1<<SOFE);
  346. //sei(); // init() in wiring.c does this
  347. media_init();
  348. }
  349. void usb_shutdown(void)
  350. {
  351. UDIEN = 0; // disable interrupts
  352. UDCON = 1; // disconnect attach resistor
  353. USBCON = 0; // shut off USB periperal
  354. PLLCSR = 0; // shut off PLL
  355. usb_configuration = 0;
  356. usb_suspended = 1;
  357. }
  358. // Public API functions moved to usb_api.cpp
  359. /**************************************************************************
  360. *
  361. * Storage Media Access Functions
  362. *
  363. **************************************************************************/
  364. #if defined(USB_DISK_SDFLASH)
  365. #include "media_sdcard.c"
  366. #elif defined(USB_DISK)
  367. #include "media_internal.c"
  368. #else
  369. #error "No known media type specified\n"
  370. #endif
  371. // User program wants to use the media, which is simple
  372. // if it's available, set the lock, otherwise report
  373. // busy and the user will just have to try again later
  374. //
  375. uint8_t media_lock(void)
  376. {
  377. uint8_t intr_state;
  378. intr_state = SREG;
  379. cli();
  380. if (media_lock_state) {
  381. SREG = intr_state;
  382. return 0;
  383. }
  384. media_lock_state = 1;
  385. SREG = intr_state;
  386. print("User program locked media\n");
  387. return 1;
  388. }
  389. // User is done with the media. If the ISR requested
  390. // media while it was locked by the user, then interrupts
  391. // need to be reenabled so the ISR can do its work.
  392. //
  393. void media_unlock(void)
  394. {
  395. uint8_t lock, intr_state;
  396. intr_state = SREG;
  397. cli();
  398. lock = media_lock_state;
  399. if (lock & MEDIA_ISR_LOCK_PENDING) {
  400. UENUM = DISK_RX_ENDPOINT;
  401. UEIENX = (1<<RXOUTE);
  402. }
  403. media_lock_state = 0;
  404. SREG = intr_state;
  405. print("User program unlocking media\n");
  406. }
  407. // Interrupt (PC access) wants to lock the media.
  408. //
  409. static inline uint8_t media_lock_isr(void)
  410. {
  411. uint8_t lock, intr_state; // epnum;
  412. intr_state = SREG;
  413. cli();
  414. lock = media_lock_state;
  415. if (lock & MEDIA_LOCKED_BY_USER) {
  416. lock |= MEDIA_ISR_LOCK_PENDING;
  417. media_lock_state = lock;
  418. SREG = intr_state;
  419. print("ISR tried to lock, but must wait\n");
  420. return 0;
  421. }
  422. lock |= MEDIA_LOCKED_BY_ISR;
  423. media_lock_state = lock;
  424. SREG = intr_state;
  425. return 1;
  426. }
  427. // Interrupt is finished with the media.
  428. //
  429. static inline void media_unlock_isr(void)
  430. {
  431. media_lock_state = 0; // 1 byte write is atomic
  432. }
  433. /**************************************************************************
  434. *
  435. * Private Functions - not intended for general user consumption....
  436. *
  437. **************************************************************************/
  438. #define ENABLE_MORE_RX 1
  439. #define ENABLE_MORE_TX 2
  440. static inline uint8_t mass_storage_isr(uint8_t need_rx, uint8_t need_tx) __attribute__((always_inline));
  441. static inline uint8_t mass_storage_isr(uint8_t need_rx, uint8_t need_tx)
  442. {
  443. uint8_t n, state;
  444. const uint8_t *p;
  445. static uint32_t tag, xfer_len, lba;
  446. static uint8_t dir __attribute__ ((used));
  447. static uint8_t cmd_len __attribute__ ((used));
  448. static uint8_t status;
  449. static uint8_t scsi_sense, scsi_asense;
  450. static uint16_t sector_count;
  451. static uint8_t sector_chunk;
  452. static uint8_t previous_media_state, do_media_status;
  453. uint8_t cmd;
  454. if (need_rx) {
  455. UENUM = DISK_RX_ENDPOINT;
  456. if (!media_lock_isr()) {
  457. print("Media is locked, ISR exit\n");
  458. // if the user program is busy with the media
  459. // then disable our interrupt and hope the user
  460. // program enables it again when finished.
  461. //UEIENX = 0;
  462. return 0;
  463. }
  464. //print("rx ");
  465. n = UEBCLX;
  466. state = ms_state;
  467. if (state == MS_STATE_IDLE) {
  468. print("CBW ");
  469. //phex(n);
  470. if (n != 31) goto error_stall;
  471. if (UEDATX != 0x55) goto error_stall;
  472. if (UEDATX != 0x53) goto error_stall;
  473. if (UEDATX != 0x42) goto error_stall;
  474. if (UEDATX != 0x43) goto error_stall;
  475. read_dword_lsbfirst(tag, UEDATX);
  476. read_dword_lsbfirst(xfer_len, UEDATX);
  477. dir = UEDATX & 0x80;
  478. UEDATX; // LUN
  479. cmd_len = UEDATX;
  480. //print(", len=");
  481. //phex(cmd_len);
  482. status = 0;
  483. cmd = UEDATX;
  484. print(", cmd=");
  485. phex(cmd);
  486. //print(", dir=");
  487. //phex(dir);
  488. //print(", xfer=");
  489. //phex32(xfer_len);
  490. print("\n");
  491. do_media_status = 0;
  492. if (cmd == SCSI_CMD_REQUEST_SENSE) { // 0x03
  493. print("REQUEST_SENSE ");
  494. phex(scsi_sense);
  495. phex(scsi_asense);
  496. print("\n");
  497. if (media_state & MEDIA_STATE_CLAIMED)
  498. media_state |= MEDIA_STATE_CLAIMED_SENSE;
  499. UEINTX = 0x6B;
  500. UENUM = DISK_TX_ENDPOINT;
  501. UEDATX = 0x70;
  502. UEDATX = 0;
  503. UEDATX = scsi_sense;
  504. UEDATX = 0;
  505. UEDATX = 0;
  506. UEDATX = 0;
  507. UEDATX = 0;
  508. UEDATX = 10;
  509. UEDATX = 0;
  510. UEDATX = 0;
  511. UEDATX = 0;
  512. UEDATX = 0;
  513. UEDATX = scsi_asense;
  514. xfer_len -= 13;
  515. goto send_finishup;
  516. }
  517. scsi_sense = SCSI_SENSE_OK;
  518. scsi_asense = SCSI_ASENSE_NONE;
  519. if (cmd == SCSI_CMD_INQUIRY) { // 0x12
  520. // http://en.wikipedia.org/wiki/SCSI_Inquiry_Command
  521. uint16_t len;
  522. UEDATX; // ignore request bits
  523. UEDATX;
  524. read_word_msbfirst(len, UEDATX);
  525. print("INQUIRY\n");
  526. UEINTX = 0x6B;
  527. if (len > sizeof(scsi_inquiry_response))
  528. len = sizeof(scsi_inquiry_response);
  529. p = scsi_inquiry_response;
  530. UENUM = DISK_TX_ENDPOINT;
  531. for (n=len; n > 0; n--) {
  532. pgm_read_byte_postinc(UEDATX, p);
  533. }
  534. xfer_len -= len;
  535. goto send_finishup;
  536. }
  537. previous_media_state = media_state;
  538. do_media_status = 1;
  539. // all commands below this point need media access
  540. if (cmd == SCSI_CMD_TEST_UNIT_READY) { // 0x00
  541. print("TEST READY, ms=");
  542. phex(media_state);
  543. print("\n");
  544. media_poll();
  545. UEINTX = 0x3A;
  546. goto send_status;
  547. }
  548. // all commands below this point need the media
  549. // to be present
  550. if (!(previous_media_state & MEDIA_PRESENT_MASK)) {
  551. print("stall_in\n");
  552. UEINTX = 0x6B;
  553. UENUM = DISK_TX_ENDPOINT;
  554. //UEIENX = 0;
  555. UECONX = (1<<STALLRQ) | (1<<EPEN);
  556. ms_state = MS_STATE_SEND_STATUS;
  557. return ENABLE_MORE_RX;
  558. }
  559. if (cmd == SCSI_CMD_MODE_SENSE_6 // 0x1A
  560. || cmd == SCSI_CMD_MODE_SENSE_10) { // 0x5A
  561. // 1A 00 1C 00 C0 00 - from disk.sys
  562. // 1A 00 3F 00 C0 00 - from classpnp.sys
  563. // 1A 00 3F 00 C0 00 - from linux kernel
  564. print("MODE SENSE 6 or 10\n");
  565. // check allocation length...
  566. UEINTX = 0x6B;
  567. UENUM = DISK_TX_ENDPOINT;
  568. UEDATX = 0x03;
  569. UEDATX = 0x00;
  570. UEDATX = media_rdonly ? 0x80 : 0x00; // WP bit
  571. UEDATX = 0x00;
  572. xfer_len -= 4;
  573. goto send_finishup;
  574. } else if (cmd == SCSI_CMD_READ_CAPACITY) { // 0x25
  575. uint32_t capacity;
  576. print("CAPACITY\n");
  577. UEINTX = 0x6B;
  578. media_poll();
  579. capacity = media_size();
  580. UENUM = DISK_TX_ENDPOINT;
  581. write_dword_msbfirst(capacity - 1, UEDATX);
  582. UEDATX = 0x00;
  583. UEDATX = 0x00;
  584. UEDATX = 0x02;
  585. UEDATX = 0x00;
  586. xfer_len -= 8;
  587. goto send_finishup;
  588. } else if (cmd == SCSI_CMD_READ_FORMAT_CAPACITIES) { // 0x23
  589. uint32_t capacity;
  590. print("READ_FORMAT_CAPACITIES\n");
  591. UEINTX = 0x6B;
  592. media_poll();
  593. capacity = media_size();
  594. UENUM = DISK_TX_ENDPOINT;
  595. UEDATX = 0x00;
  596. UEDATX = 0x00;
  597. UEDATX = 0x00;
  598. UEDATX = 0x08;
  599. write_dword_msbfirst(capacity, UEDATX);
  600. UEDATX = 2 + status; // 2 = formatted, 3 = no media present
  601. UEDATX = 0x00;
  602. UEDATX = 0x02; // 512 byte blocks
  603. UEDATX = 0x00;
  604. xfer_len -= 12;
  605. goto send_finishup;
  606. } else if (cmd == SCSI_CMD_READ_10) { // 0x28
  607. // http://en.wikipedia.org/wiki/SCSI_Read_Commands#Read_.2810.29
  608. UEDATX;
  609. read_dword_msbfirst(lba, UEDATX);
  610. UEDATX;
  611. read_word_msbfirst(sector_count, UEDATX);
  612. print("READ_10: lba=");
  613. phex32(lba);
  614. print(", count=");
  615. phex16(sector_count);
  616. print("\n");
  617. UEINTX = 0x6B;
  618. if (!(media_state & MEDIA_PRESENT_MASK)) {
  619. UENUM = DISK_TX_ENDPOINT;
  620. goto send_finishup;
  621. }
  622. media_send_begin(lba);
  623. sector_chunk = 0;
  624. ms_state = MS_STATE_SEND_DATA;
  625. goto send_data;
  626. } else if (cmd == SCSI_CMD_WRITE_10) { // 0x2A
  627. UEDATX;
  628. read_dword_msbfirst(lba, UEDATX);
  629. UEDATX;
  630. read_word_msbfirst(sector_count, UEDATX);
  631. print("WRITE_10: lba=");
  632. phex32(lba);
  633. print(", count=");
  634. phex16(sector_count);
  635. print("\n");
  636. UEINTX = 0x6B;
  637. // TODO: how to handle write when media not ready
  638. //if (!(media_state & MEDIA_PRESENT_MASK)) goto send_finishup;
  639. sector_chunk = 0;
  640. media_receive_begin(lba);
  641. ms_state = MS_STATE_RECEIVE_DATA;
  642. n = UEBCLX;
  643. if (n > 0) goto receive_data;
  644. return ENABLE_MORE_RX;
  645. } else {
  646. print("Unimplemented, cmd=");
  647. phex(cmd);
  648. print("\n");
  649. UEINTX = 0x6B;
  650. scsi_sense = SCSI_SENSE_ILLEGAL_REQUEST;
  651. scsi_asense = SCSI_ASENSE_INVALID_COMMAND;
  652. status = 1;
  653. goto send_finishup;
  654. //TODO: what is the proper way to handle this error??
  655. //UENUM = DISK_TX_ENDPOINT;
  656. //UECONX = (1<<STALLRQ) | (1<<EPEN);
  657. //state = MS_STATE_SEND_STATUS;
  658. //UEIENX = (1<<TXINE);
  659. //return ENABLE_MORE_RX;
  660. }
  661. } else if (state == MS_STATE_RECEIVE_DATA) {
  662. receive_data:
  663. //print("receive, count=");
  664. //phex16(sector_count);
  665. //print (", lba=");
  666. //phex32(lba);
  667. //print(", chunk=");
  668. //phex(sector_chunk);
  669. //print("\n");
  670. if (sector_count > 0) {
  671. media_receive_chunk(lba, sector_chunk);
  672. xfer_len -= 64;
  673. if (++sector_chunk >= 8) {
  674. sector_chunk = 0;
  675. lba++;
  676. //if (--sector_count == 0) ms_state = MS_STATE_SEND_STATUS;
  677. if (--sector_count == 0) {
  678. media_receive_end();
  679. goto send_status;
  680. }
  681. }
  682. // if another interrupt already ending, do it now
  683. //if (UEINTX & (1<<RXOUTI)) goto receive_data;
  684. } else {
  685. UEINTX = 0x6B;
  686. }
  687. return ENABLE_MORE_RX;
  688. } else {
  689. //print("unexpected receive: n=");
  690. //phex(n);
  691. //print("\n");
  692. UEINTX = 0x6B;
  693. return ENABLE_MORE_RX;
  694. }
  695. }
  696. if (need_tx) {
  697. UENUM = DISK_TX_ENDPOINT;
  698. //print("tx ");
  699. state = ms_state;
  700. if (state == MS_STATE_SEND_STATUS) goto send_status_force;
  701. if (state == MS_STATE_SEND_ZEROPAD) goto send_finishup;
  702. if (state == MS_STATE_SEND_DATA) goto send_data;
  703. print("unhandled tx interrupt ");
  704. phex(state);
  705. print("\n");
  706. return 0;
  707. }
  708. return ENABLE_MORE_RX; // should never be called with both need_rx = 0 and need_tx = 0
  709. send_data:
  710. //print("send, count=");
  711. //phex16(sector_count);
  712. //print (", lba=");
  713. //phex32(lba);
  714. //print(", chunk=");
  715. //phex(sector_chunk);
  716. //print("\n");
  717. UENUM = DISK_TX_ENDPOINT;
  718. if (sector_count > 0 && (UEINTX & (1<<RWAL))) {
  719. media_send_chunk(lba, sector_chunk);
  720. xfer_len -= 64;
  721. if (++sector_chunk >= 8) {
  722. sector_chunk = 0;
  723. lba++;
  724. if (--sector_count == 0) {
  725. media_send_end();
  726. ms_state = MS_STATE_SEND_STATUS;
  727. }
  728. }
  729. // if more buffers ready, don't wait for another interrupt
  730. if (UEINTX & (1<<RWAL)) goto send_data;
  731. }
  732. //UEIENX = (1<<TXINE);
  733. return ENABLE_MORE_TX;
  734. send_finishup:
  735. while (xfer_len > 0 && (UEINTX & (1<<RWAL))) {
  736. UEDATX = 0;
  737. xfer_len--;
  738. }
  739. UEINTX = 0x3A;
  740. if (xfer_len) {
  741. print("short reply\n");
  742. ms_state = MS_STATE_SEND_ZEROPAD;
  743. //UEIENX = (1<<TXINE);
  744. return ENABLE_MORE_TX;
  745. }
  746. send_status:
  747. UENUM = DISK_TX_ENDPOINT;
  748. if (!(UEINTX & (1<<RWAL))) {
  749. print("wait tx\n");
  750. ms_state = MS_STATE_SEND_STATUS;
  751. //UEIENX = (1<<TXINE);
  752. return ENABLE_MORE_TX;
  753. }
  754. send_status_force:
  755. if (do_media_status) {
  756. uint8_t current_media_state = media_state;
  757. if (current_media_state & MEDIA_STATE_CLAIMED)
  758. media_state = current_media_state | MEDIA_STATE_CLAIMED_STATUS;
  759. if (status == 0) {
  760. if (!(current_media_state & MEDIA_PRESENT_MASK)) {
  761. scsi_sense = SCSI_SENSE_NOT_READY;
  762. scsi_asense = SCSI_ASENSE_MEDIUM_NOT_PRESENT;
  763. status = 1;
  764. } else {
  765. if (!(previous_media_state & MEDIA_PRESENT_MASK)) {
  766. scsi_sense = SCSI_SENSE_UNIT_ATTENTION;
  767. scsi_asense = SCSI_ASENSE_NOT_READY_TO_READY;
  768. status = 1;
  769. }
  770. }
  771. }
  772. do_media_status = 0;
  773. }
  774. print("status ");
  775. phex(status);
  776. if (status) {
  777. phex(scsi_sense);
  778. phex(scsi_asense);
  779. }
  780. print("\n");
  781. UEDATX = 0x55;
  782. UEDATX = 0x53;
  783. UEDATX = 0x42;
  784. UEDATX = 0x53;
  785. write_dword_lsbfirst(tag, UEDATX);
  786. write_dword_lsbfirst(xfer_len, UEDATX);
  787. UEDATX = status;
  788. UEINTX = 0x3A;
  789. //UEIENX = 0;
  790. ms_state = MS_STATE_IDLE;
  791. media_unlock_isr();
  792. return ENABLE_MORE_RX;
  793. error_stall:
  794. print("\nStall\n");
  795. ms_state = MS_STATE_STALLED;
  796. UENUM = DISK_RX_ENDPOINT;
  797. //UEIENX = 0;
  798. UECONX = (1<<STALLRQ) | (1<<EPEN);
  799. UENUM = DISK_TX_ENDPOINT;
  800. //UEIENX = 0;
  801. UECONX = (1<<STALLRQ) | (1<<EPEN);
  802. media_unlock_isr();
  803. return ENABLE_MORE_RX | ENABLE_MORE_TX;
  804. }
  805. // Misc functions to wait for ready and send/receive packets
  806. static inline void usb_wait_in_ready(void)
  807. {
  808. while (!(UEINTX & (1<<TXINI))) ;
  809. }
  810. static inline void usb_send_in(void)
  811. {
  812. UEINTX = ~(1<<TXINI);
  813. }
  814. static inline void usb_wait_receive_out(void)
  815. {
  816. while (!(UEINTX & (1<<RXOUTI))) ;
  817. }
  818. static inline void usb_ack_out(void)
  819. {
  820. UEINTX = ~(1<<RXOUTI);
  821. }
  822. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  823. // other endpoints are manipulated by the user-callable
  824. // functions, and the start-of-frame interrupt.
  825. //
  826. static inline void endpoint0_isr(void) __attribute__((always_inline));
  827. static inline void endpoint0_isr(void)
  828. {
  829. uint8_t intbits;
  830. const uint8_t *list;
  831. const uint8_t *cfg;
  832. uint8_t i, n, len, en;
  833. uint8_t bmRequestType;
  834. uint8_t bRequest;
  835. uint16_t wValue;
  836. uint16_t wIndex;
  837. uint16_t wLength;
  838. uint16_t desc_val;
  839. const uint8_t *desc_addr;
  840. uint8_t desc_length;
  841. UENUM = 0;
  842. intbits = UEINTX;
  843. if (intbits & (1<<RXSTPI)) {
  844. bmRequestType = UEDATX;
  845. bRequest = UEDATX;
  846. read_word_lsbfirst(wValue, UEDATX);
  847. read_word_lsbfirst(wIndex, UEDATX);
  848. read_word_lsbfirst(wLength, UEDATX);
  849. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  850. if (bRequest == GET_DESCRIPTOR) {
  851. list = (const uint8_t *)descriptor_list;
  852. for (i=0; ; i++) {
  853. if (i >= NUM_DESC_LIST) {
  854. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  855. return;
  856. }
  857. pgm_read_word_postinc(desc_val, list);
  858. if (desc_val != wValue) {
  859. list += sizeof(struct descriptor_list_struct)-2;
  860. continue;
  861. }
  862. pgm_read_word_postinc(desc_val, list);
  863. if (desc_val != wIndex) {
  864. list += sizeof(struct descriptor_list_struct)-4;
  865. continue;
  866. }
  867. pgm_read_word_postinc(desc_addr, list);
  868. desc_length = pgm_read_byte(list);
  869. break;
  870. }
  871. len = (wLength < 256) ? wLength : 255;
  872. if (len > desc_length) len = desc_length;
  873. list = desc_addr;
  874. do {
  875. // wait for host ready for IN packet
  876. do {
  877. i = UEINTX;
  878. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  879. if (i & (1<<RXOUTI)) return; // abort
  880. // send IN packet
  881. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  882. for (i = n; i; i--) {
  883. pgm_read_byte_postinc(UEDATX, list);
  884. }
  885. len -= n;
  886. usb_send_in();
  887. } while (len || n == ENDPOINT0_SIZE);
  888. return;
  889. }
  890. if (bRequest == SET_ADDRESS) {
  891. usb_send_in();
  892. usb_wait_in_ready();
  893. UDADDR = wValue | (1<<ADDEN);
  894. return;
  895. }
  896. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  897. usb_configuration = wValue;
  898. debug_flush_timer = 0;
  899. usb_send_in();
  900. cfg = endpoint_config_table;
  901. for (i=1; i<NUM_ENDPOINTS; i++) {
  902. UENUM = i;
  903. pgm_read_byte_postinc(en, cfg);
  904. UECONX = en;
  905. if (en) {
  906. pgm_read_byte_postinc(UECFG0X, cfg);
  907. pgm_read_byte_postinc(UECFG1X, cfg);
  908. }
  909. }
  910. UERST = 0x1E;
  911. UERST = 0;
  912. UENUM = DISK_RX_ENDPOINT;
  913. UEIENX = (1<<RXOUTE);
  914. return;
  915. }
  916. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  917. usb_wait_in_ready();
  918. UEDATX = usb_configuration;
  919. usb_send_in();
  920. return;
  921. }
  922. if (bRequest == GET_STATUS) {
  923. usb_wait_in_ready();
  924. i = 0;
  925. if (bmRequestType == 0x82) {
  926. UENUM = wIndex;
  927. if (UECONX & (1<<STALLRQ)) i = 1;
  928. UENUM = 0;
  929. }
  930. UEDATX = i;
  931. UEDATX = 0;
  932. usb_send_in();
  933. return;
  934. }
  935. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  936. && bmRequestType == 0x02 && wValue == 0) {
  937. i = wIndex & 0x7F;
  938. if (i >= 1 && i <= MAX_ENDPOINT) {
  939. usb_send_in();
  940. UENUM = i;
  941. if (bRequest == SET_FEATURE) {
  942. UECONX = (1<<STALLRQ)|(1<<EPEN);
  943. } else {
  944. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  945. UERST = (1 << i);
  946. UERST = 0;
  947. if (i == DISK_TX_ENDPOINT) {
  948. UEIENX = (1<<TXINE);
  949. }
  950. }
  951. return;
  952. }
  953. }
  954. if (wIndex == KEYBOARD_INTERFACE) {
  955. if (bmRequestType == 0xA1) {
  956. if (bRequest == HID_GET_REPORT) {
  957. usb_wait_in_ready();
  958. for (i=0; i < 8; i++) {
  959. UEDATX = keyboard_report_data[i];
  960. }
  961. usb_send_in();
  962. return;
  963. }
  964. if (bRequest == HID_GET_IDLE) {
  965. usb_wait_in_ready();
  966. UEDATX = keyboard_idle_config;
  967. usb_send_in();
  968. return;
  969. }
  970. if (bRequest == HID_GET_PROTOCOL) {
  971. usb_wait_in_ready();
  972. UEDATX = keyboard_protocol;
  973. usb_send_in();
  974. return;
  975. }
  976. }
  977. if (bmRequestType == 0x21) {
  978. if (bRequest == HID_SET_REPORT) {
  979. usb_wait_receive_out();
  980. keyboard_leds = UEDATX;
  981. usb_ack_out();
  982. usb_send_in();
  983. return;
  984. }
  985. if (bRequest == HID_SET_IDLE) {
  986. keyboard_idle_config = (wValue >> 8);
  987. keyboard_idle_count = 0;
  988. //usb_wait_in_ready();
  989. usb_send_in();
  990. return;
  991. }
  992. if (bRequest == HID_SET_PROTOCOL) {
  993. keyboard_protocol = wValue;
  994. //usb_wait_in_ready();
  995. usb_send_in();
  996. return;
  997. }
  998. }
  999. }
  1000. if (wIndex == DEBUG_INTERFACE) {
  1001. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  1002. len = wLength;
  1003. do {
  1004. // wait for host ready for IN packet
  1005. do {
  1006. i = UEINTX;
  1007. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  1008. if (i & (1<<RXOUTI)) return; // abort
  1009. // send IN packet
  1010. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  1011. for (i = n; i; i--) {
  1012. UEDATX = 0;
  1013. }
  1014. len -= n;
  1015. usb_send_in();
  1016. } while (len || n == ENDPOINT0_SIZE);
  1017. return;
  1018. }
  1019. if (bRequest == HID_SET_REPORT && bmRequestType == 0x21) {
  1020. if (wValue == 0x0300 && wLength == 0x0004) {
  1021. uint8_t b1, b2, b3, b4;
  1022. usb_wait_receive_out();
  1023. b1 = UEDATX;
  1024. b2 = UEDATX;
  1025. b3 = UEDATX;
  1026. b4 = UEDATX;
  1027. usb_ack_out();
  1028. usb_send_in();
  1029. if (b1 == 0xA9 && b2 == 0x45 && b3 == 0xC2 && b4 == 0x6B)
  1030. _reboot_Teensyduino_();
  1031. if (b1 == 0x8B && b2 == 0xC5 && b3 == 0x1D && b4 == 0x70)
  1032. _restart_Teensyduino_();
  1033. }
  1034. }
  1035. }
  1036. if (bRequest == 0xC9 && bmRequestType == 0x40) {
  1037. usb_send_in();
  1038. usb_wait_in_ready();
  1039. _restart_Teensyduino_();
  1040. }
  1041. if (wIndex == DISK_INTERFACE) {
  1042. if (bRequest == MS_BULK_ONLY_RESET && bmRequestType == 0x21) {
  1043. usb_wait_in_ready();
  1044. ms_state = MS_STATE_IDLE;
  1045. usb_send_in();
  1046. return;
  1047. }
  1048. }
  1049. }
  1050. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  1051. }
  1052. // USB Endpoint Interrupt
  1053. ISR(USB_COM_vect)
  1054. {
  1055. uint8_t epnum_save, r=0, need_rx=0, need_tx=0;
  1056. // first, do endpoint 0
  1057. epnum_save = UENUM;
  1058. endpoint0_isr();
  1059. // disable all USB interrupts
  1060. UDIEN = 0;
  1061. UENUM = 0;
  1062. UEIENX = 0;
  1063. UENUM = DISK_RX_ENDPOINT;
  1064. if (UEIENX & (1<<RXOUTE)) {
  1065. r = ENABLE_MORE_RX;
  1066. if (UEINTX & (1<<RXOUTI)) need_rx=1;
  1067. }
  1068. UEIENX = 0;
  1069. UENUM = DISK_TX_ENDPOINT;
  1070. if (UEIENX & (1<<TXINE)) {
  1071. r |= ENABLE_MORE_TX;
  1072. if (UEINTX & (1<<TXINI)) need_tx=1;
  1073. }
  1074. UEIENX = 0;
  1075. // run the mass storage, with non-USB interrupts enabled
  1076. // so lengthy transfers don't starve other interrupts
  1077. if (need_rx || need_tx) {
  1078. sei();
  1079. r = mass_storage_isr(need_rx, need_tx);
  1080. cli();
  1081. }
  1082. // re-enable USB interrupts
  1083. if (r & ENABLE_MORE_RX) {
  1084. UENUM = DISK_RX_ENDPOINT;
  1085. UEIENX = (1<<RXOUTE);
  1086. }
  1087. if (r & ENABLE_MORE_TX) {
  1088. UENUM = DISK_TX_ENDPOINT;
  1089. UEIENX = (1<<TXINE);
  1090. }
  1091. UENUM = 0;
  1092. UEIENX = (1<<RXSTPE);
  1093. UDIEN = (1<<EORSTE)|(1<<SOFE);
  1094. UENUM = epnum_save;
  1095. }
  1096. // USB Device Interrupt - handle all device-level events
  1097. // the transmit buffer flushing is triggered by the start of frame
  1098. //
  1099. ISR(USB_GEN_vect)
  1100. {
  1101. uint8_t intbits, t, i;
  1102. static uint8_t div4=0;
  1103. intbits = UDINT;
  1104. UDINT = 0;
  1105. if (intbits & (1<<EORSTI)) {
  1106. UENUM = 0;
  1107. UECONX = 1;
  1108. UECFG0X = EP_TYPE_CONTROL;
  1109. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  1110. UEIENX = (1<<RXSTPE);
  1111. usb_configuration = 0;
  1112. UENUM = DISK_RX_ENDPOINT;
  1113. UEIENX = 0;
  1114. UENUM = DISK_TX_ENDPOINT;
  1115. UEIENX = 0;
  1116. ms_state = MS_STATE_IDLE;
  1117. }
  1118. if ((intbits & (1<<SOFI)) && usb_configuration) {
  1119. t = debug_flush_timer;
  1120. if (t) {
  1121. debug_flush_timer = -- t;
  1122. if (!t) {
  1123. UENUM = DEBUG_TX_ENDPOINT;
  1124. while ((UEINTX & (1<<RWAL))) {
  1125. UEDATX = 0;
  1126. }
  1127. UEINTX = 0x3A;
  1128. }
  1129. }
  1130. if (keyboard_idle_config && (++div4 & 3) == 0) {
  1131. UENUM = KEYBOARD_ENDPOINT;
  1132. if (UEINTX & (1<<RWAL)) {
  1133. keyboard_idle_count++;
  1134. if (keyboard_idle_count == keyboard_idle_config) {
  1135. keyboard_idle_count = 0;
  1136. for (i=0; i < 8; i++) {
  1137. UEDATX = keyboard_report_data[i];
  1138. }
  1139. UEINTX = 0x3A;
  1140. }
  1141. }
  1142. }
  1143. }
  1144. if (intbits & (1<<SUSPI)) {
  1145. // USB Suspend (inactivity for 3ms)
  1146. UDIEN = (1<<WAKEUPE);
  1147. usb_configuration = 0;
  1148. usb_suspended = 1;
  1149. #if (F_CPU >= 8000000L)
  1150. // WAKEUPI does not work with USB clock freeze
  1151. // when CPU is running less than 8 MHz.
  1152. // Is this a hardware bug?
  1153. USB_FREEZE(); // shut off USB
  1154. PLLCSR = 0; // shut off PLL
  1155. #endif
  1156. // to properly meet the USB spec, current must
  1157. // reduce to less than 2.5 mA, which means using
  1158. // powerdown mode, but that breaks the Arduino
  1159. // user's paradigm....
  1160. }
  1161. if (usb_suspended && (intbits & (1<<WAKEUPI))) {
  1162. // USB Resume (pretty much any activity)
  1163. #if (F_CPU >= 8000000L)
  1164. PLL_CONFIG();
  1165. while (!(PLLCSR & (1<<PLOCK))) ;
  1166. USB_CONFIG();
  1167. #endif
  1168. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  1169. usb_suspended = 0;
  1170. return;
  1171. }
  1172. }