Teensy 4.1 core updated for C++20
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  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, cmd_len, status;
  447. static uint8_t scsi_sense, scsi_asense;
  448. static uint16_t sector_count;
  449. static uint8_t sector_chunk;
  450. static uint8_t previous_media_state, do_media_status;
  451. uint8_t cmd;
  452. if (need_rx) {
  453. UENUM = DISK_RX_ENDPOINT;
  454. if (!media_lock_isr()) {
  455. print("Media is locked, ISR exit\n");
  456. // if the user program is busy with the media
  457. // then disable our interrupt and hope the user
  458. // program enables it again when finished.
  459. //UEIENX = 0;
  460. return 0;
  461. }
  462. //print("rx ");
  463. n = UEBCLX;
  464. state = ms_state;
  465. if (state == MS_STATE_IDLE) {
  466. print("CBW ");
  467. //phex(n);
  468. if (n != 31) goto error_stall;
  469. if (UEDATX != 0x55) goto error_stall;
  470. if (UEDATX != 0x53) goto error_stall;
  471. if (UEDATX != 0x42) goto error_stall;
  472. if (UEDATX != 0x43) goto error_stall;
  473. read_dword_lsbfirst(tag, UEDATX);
  474. read_dword_lsbfirst(xfer_len, UEDATX);
  475. dir = UEDATX & 0x80;
  476. UEDATX; // LUN
  477. cmd_len = UEDATX;
  478. //print(", len=");
  479. //phex(cmd_len);
  480. status = 0;
  481. cmd = UEDATX;
  482. print(", cmd=");
  483. phex(cmd);
  484. //print(", dir=");
  485. //phex(dir);
  486. //print(", xfer=");
  487. //phex32(xfer_len);
  488. print("\n");
  489. do_media_status = 0;
  490. if (cmd == SCSI_CMD_REQUEST_SENSE) { // 0x03
  491. print("REQUEST_SENSE ");
  492. phex(scsi_sense);
  493. phex(scsi_asense);
  494. print("\n");
  495. if (media_state & MEDIA_STATE_CLAIMED)
  496. media_state |= MEDIA_STATE_CLAIMED_SENSE;
  497. UEINTX = 0x6B;
  498. UENUM = DISK_TX_ENDPOINT;
  499. UEDATX = 0x70;
  500. UEDATX = 0;
  501. UEDATX = scsi_sense;
  502. UEDATX = 0;
  503. UEDATX = 0;
  504. UEDATX = 0;
  505. UEDATX = 0;
  506. UEDATX = 10;
  507. UEDATX = 0;
  508. UEDATX = 0;
  509. UEDATX = 0;
  510. UEDATX = 0;
  511. UEDATX = scsi_asense;
  512. xfer_len -= 13;
  513. goto send_finishup;
  514. }
  515. scsi_sense = SCSI_SENSE_OK;
  516. scsi_asense = SCSI_ASENSE_NONE;
  517. if (cmd == SCSI_CMD_INQUIRY) { // 0x12
  518. // http://en.wikipedia.org/wiki/SCSI_Inquiry_Command
  519. uint16_t len;
  520. UEDATX; // ignore request bits
  521. UEDATX;
  522. read_word_msbfirst(len, UEDATX);
  523. print("INQUIRY\n");
  524. UEINTX = 0x6B;
  525. if (len > sizeof(scsi_inquiry_response))
  526. len = sizeof(scsi_inquiry_response);
  527. p = scsi_inquiry_response;
  528. UENUM = DISK_TX_ENDPOINT;
  529. for (n=len; n > 0; n--) {
  530. pgm_read_byte_postinc(UEDATX, p);
  531. }
  532. xfer_len -= len;
  533. goto send_finishup;
  534. }
  535. previous_media_state = media_state;
  536. do_media_status = 1;
  537. // all commands below this point need media access
  538. if (cmd == SCSI_CMD_TEST_UNIT_READY) { // 0x00
  539. print("TEST READY, ms=");
  540. phex(media_state);
  541. print("\n");
  542. media_poll();
  543. UEINTX = 0x3A;
  544. goto send_status;
  545. }
  546. // all commands below this point need the media
  547. // to be present
  548. if (!(previous_media_state & MEDIA_PRESENT_MASK)) {
  549. print("stall_in\n");
  550. UEINTX = 0x6B;
  551. UENUM = DISK_TX_ENDPOINT;
  552. //UEIENX = 0;
  553. UECONX = (1<<STALLRQ) | (1<<EPEN);
  554. ms_state = MS_STATE_SEND_STATUS;
  555. return ENABLE_MORE_RX;
  556. }
  557. if (cmd == SCSI_CMD_MODE_SENSE_6 // 0x1A
  558. || cmd == SCSI_CMD_MODE_SENSE_10) { // 0x5A
  559. // 1A 00 1C 00 C0 00 - from disk.sys
  560. // 1A 00 3F 00 C0 00 - from classpnp.sys
  561. // 1A 00 3F 00 C0 00 - from linux kernel
  562. print("MODE SENSE 6 or 10\n");
  563. // check allocation length...
  564. UEINTX = 0x6B;
  565. UENUM = DISK_TX_ENDPOINT;
  566. UEDATX = 0x03;
  567. UEDATX = 0x00;
  568. UEDATX = media_rdonly ? 0x80 : 0x00; // WP bit
  569. UEDATX = 0x00;
  570. xfer_len -= 4;
  571. goto send_finishup;
  572. } else if (cmd == SCSI_CMD_READ_CAPACITY) { // 0x25
  573. uint32_t capacity;
  574. print("CAPACITY\n");
  575. UEINTX = 0x6B;
  576. media_poll();
  577. capacity = media_size();
  578. UENUM = DISK_TX_ENDPOINT;
  579. write_dword_msbfirst(capacity - 1, UEDATX);
  580. UEDATX = 0x00;
  581. UEDATX = 0x00;
  582. UEDATX = 0x02;
  583. UEDATX = 0x00;
  584. xfer_len -= 8;
  585. goto send_finishup;
  586. } else if (cmd == SCSI_CMD_READ_FORMAT_CAPACITIES) { // 0x23
  587. uint32_t capacity;
  588. print("READ_FORMAT_CAPACITIES\n");
  589. UEINTX = 0x6B;
  590. media_poll();
  591. capacity = media_size();
  592. UENUM = DISK_TX_ENDPOINT;
  593. UEDATX = 0x00;
  594. UEDATX = 0x00;
  595. UEDATX = 0x00;
  596. UEDATX = 0x08;
  597. write_dword_msbfirst(capacity, UEDATX);
  598. UEDATX = 2 + status; // 2 = formatted, 3 = no media present
  599. UEDATX = 0x00;
  600. UEDATX = 0x02; // 512 byte blocks
  601. UEDATX = 0x00;
  602. xfer_len -= 12;
  603. goto send_finishup;
  604. } else if (cmd == SCSI_CMD_READ_10) { // 0x28
  605. // http://en.wikipedia.org/wiki/SCSI_Read_Commands#Read_.2810.29
  606. UEDATX;
  607. read_dword_msbfirst(lba, UEDATX);
  608. UEDATX;
  609. read_word_msbfirst(sector_count, UEDATX);
  610. print("READ_10: lba=");
  611. phex32(lba);
  612. print(", count=");
  613. phex16(sector_count);
  614. print("\n");
  615. UEINTX = 0x6B;
  616. if (!(media_state & MEDIA_PRESENT_MASK)) {
  617. UENUM = DISK_TX_ENDPOINT;
  618. goto send_finishup;
  619. }
  620. media_send_begin(lba);
  621. sector_chunk = 0;
  622. ms_state = MS_STATE_SEND_DATA;
  623. goto send_data;
  624. } else if (cmd == SCSI_CMD_WRITE_10) { // 0x2A
  625. UEDATX;
  626. read_dword_msbfirst(lba, UEDATX);
  627. UEDATX;
  628. read_word_msbfirst(sector_count, UEDATX);
  629. print("WRITE_10: lba=");
  630. phex32(lba);
  631. print(", count=");
  632. phex16(sector_count);
  633. print("\n");
  634. UEINTX = 0x6B;
  635. // TODO: how to handle write when media not ready
  636. //if (!(media_state & MEDIA_PRESENT_MASK)) goto send_finishup;
  637. sector_chunk = 0;
  638. media_receive_begin(lba);
  639. ms_state = MS_STATE_RECEIVE_DATA;
  640. n = UEBCLX;
  641. if (n > 0) goto receive_data;
  642. return ENABLE_MORE_RX;
  643. } else {
  644. print("Unimplemented, cmd=");
  645. phex(cmd);
  646. print("\n");
  647. UEINTX = 0x6B;
  648. scsi_sense = SCSI_SENSE_ILLEGAL_REQUEST;
  649. scsi_asense = SCSI_ASENSE_INVALID_COMMAND;
  650. status = 1;
  651. goto send_finishup;
  652. //TODO: what is the proper way to handle this error??
  653. //UENUM = DISK_TX_ENDPOINT;
  654. //UECONX = (1<<STALLRQ) | (1<<EPEN);
  655. //state = MS_STATE_SEND_STATUS;
  656. //UEIENX = (1<<TXINE);
  657. //return ENABLE_MORE_RX;
  658. }
  659. } else if (state == MS_STATE_RECEIVE_DATA) {
  660. receive_data:
  661. //print("receive, count=");
  662. //phex16(sector_count);
  663. //print (", lba=");
  664. //phex32(lba);
  665. //print(", chunk=");
  666. //phex(sector_chunk);
  667. //print("\n");
  668. if (sector_count > 0) {
  669. media_receive_chunk(lba, sector_chunk);
  670. xfer_len -= 64;
  671. if (++sector_chunk >= 8) {
  672. sector_chunk = 0;
  673. lba++;
  674. //if (--sector_count == 0) ms_state = MS_STATE_SEND_STATUS;
  675. if (--sector_count == 0) {
  676. media_receive_end();
  677. goto send_status;
  678. }
  679. }
  680. // if another interrupt already ending, do it now
  681. //if (UEINTX & (1<<RXOUTI)) goto receive_data;
  682. } else {
  683. UEINTX = 0x6B;
  684. }
  685. return ENABLE_MORE_RX;
  686. } else {
  687. //print("unexpected receive: n=");
  688. //phex(n);
  689. //print("\n");
  690. UEINTX = 0x6B;
  691. return ENABLE_MORE_RX;
  692. }
  693. }
  694. if (need_tx) {
  695. UENUM = DISK_TX_ENDPOINT;
  696. //print("tx ");
  697. state = ms_state;
  698. if (state == MS_STATE_SEND_STATUS) goto send_status_force;
  699. if (state == MS_STATE_SEND_ZEROPAD) goto send_finishup;
  700. if (state == MS_STATE_SEND_DATA) goto send_data;
  701. print("unhandled tx interrupt ");
  702. phex(state);
  703. print("\n");
  704. return 0;
  705. }
  706. return ENABLE_MORE_RX; // should never be called with both need_rx = 0 and need_tx = 0
  707. send_data:
  708. //print("send, count=");
  709. //phex16(sector_count);
  710. //print (", lba=");
  711. //phex32(lba);
  712. //print(", chunk=");
  713. //phex(sector_chunk);
  714. //print("\n");
  715. UENUM = DISK_TX_ENDPOINT;
  716. if (sector_count > 0 && (UEINTX & (1<<RWAL))) {
  717. media_send_chunk(lba, sector_chunk);
  718. xfer_len -= 64;
  719. if (++sector_chunk >= 8) {
  720. sector_chunk = 0;
  721. lba++;
  722. if (--sector_count == 0) {
  723. media_send_end();
  724. ms_state = MS_STATE_SEND_STATUS;
  725. }
  726. }
  727. // if more buffers ready, don't wait for another interrupt
  728. if (UEINTX & (1<<RWAL)) goto send_data;
  729. }
  730. //UEIENX = (1<<TXINE);
  731. return ENABLE_MORE_TX;
  732. send_finishup:
  733. while (xfer_len > 0 && (UEINTX & (1<<RWAL))) {
  734. UEDATX = 0;
  735. xfer_len--;
  736. }
  737. UEINTX = 0x3A;
  738. if (xfer_len) {
  739. print("short reply\n");
  740. ms_state = MS_STATE_SEND_ZEROPAD;
  741. //UEIENX = (1<<TXINE);
  742. return ENABLE_MORE_TX;
  743. }
  744. send_status:
  745. UENUM = DISK_TX_ENDPOINT;
  746. if (!(UEINTX & (1<<RWAL))) {
  747. print("wait tx\n");
  748. ms_state = MS_STATE_SEND_STATUS;
  749. //UEIENX = (1<<TXINE);
  750. return ENABLE_MORE_TX;
  751. }
  752. send_status_force:
  753. if (do_media_status) {
  754. uint8_t current_media_state = media_state;
  755. if (current_media_state & MEDIA_STATE_CLAIMED)
  756. media_state = current_media_state | MEDIA_STATE_CLAIMED_STATUS;
  757. if (status == 0) {
  758. if (!(current_media_state & MEDIA_PRESENT_MASK)) {
  759. scsi_sense = SCSI_SENSE_NOT_READY;
  760. scsi_asense = SCSI_ASENSE_MEDIUM_NOT_PRESENT;
  761. status = 1;
  762. } else {
  763. if (!(previous_media_state & MEDIA_PRESENT_MASK)) {
  764. scsi_sense = SCSI_SENSE_UNIT_ATTENTION;
  765. scsi_asense = SCSI_ASENSE_NOT_READY_TO_READY;
  766. status = 1;
  767. }
  768. }
  769. }
  770. do_media_status = 0;
  771. }
  772. print("status ");
  773. phex(status);
  774. if (status) {
  775. phex(scsi_sense);
  776. phex(scsi_asense);
  777. }
  778. print("\n");
  779. UEDATX = 0x55;
  780. UEDATX = 0x53;
  781. UEDATX = 0x42;
  782. UEDATX = 0x53;
  783. write_dword_lsbfirst(tag, UEDATX);
  784. write_dword_lsbfirst(xfer_len, UEDATX);
  785. UEDATX = status;
  786. UEINTX = 0x3A;
  787. //UEIENX = 0;
  788. ms_state = MS_STATE_IDLE;
  789. media_unlock_isr();
  790. return ENABLE_MORE_RX;
  791. error_stall:
  792. print("\nStall\n");
  793. ms_state = MS_STATE_STALLED;
  794. UENUM = DISK_RX_ENDPOINT;
  795. //UEIENX = 0;
  796. UECONX = (1<<STALLRQ) | (1<<EPEN);
  797. UENUM = DISK_TX_ENDPOINT;
  798. //UEIENX = 0;
  799. UECONX = (1<<STALLRQ) | (1<<EPEN);
  800. media_unlock_isr();
  801. return ENABLE_MORE_RX | ENABLE_MORE_TX;
  802. }
  803. // Misc functions to wait for ready and send/receive packets
  804. static inline void usb_wait_in_ready(void)
  805. {
  806. while (!(UEINTX & (1<<TXINI))) ;
  807. }
  808. static inline void usb_send_in(void)
  809. {
  810. UEINTX = ~(1<<TXINI);
  811. }
  812. static inline void usb_wait_receive_out(void)
  813. {
  814. while (!(UEINTX & (1<<RXOUTI))) ;
  815. }
  816. static inline void usb_ack_out(void)
  817. {
  818. UEINTX = ~(1<<RXOUTI);
  819. }
  820. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  821. // other endpoints are manipulated by the user-callable
  822. // functions, and the start-of-frame interrupt.
  823. //
  824. static inline void endpoint0_isr(void) __attribute__((always_inline));
  825. static inline void endpoint0_isr(void)
  826. {
  827. uint8_t intbits;
  828. const uint8_t *list;
  829. const uint8_t *cfg;
  830. uint8_t i, n, len, en;
  831. uint8_t bmRequestType;
  832. uint8_t bRequest;
  833. uint16_t wValue;
  834. uint16_t wIndex;
  835. uint16_t wLength;
  836. uint16_t desc_val;
  837. const uint8_t *desc_addr;
  838. uint8_t desc_length;
  839. UENUM = 0;
  840. intbits = UEINTX;
  841. if (intbits & (1<<RXSTPI)) {
  842. bmRequestType = UEDATX;
  843. bRequest = UEDATX;
  844. read_word_lsbfirst(wValue, UEDATX);
  845. read_word_lsbfirst(wIndex, UEDATX);
  846. read_word_lsbfirst(wLength, UEDATX);
  847. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  848. if (bRequest == GET_DESCRIPTOR) {
  849. list = (const uint8_t *)descriptor_list;
  850. for (i=0; ; i++) {
  851. if (i >= NUM_DESC_LIST) {
  852. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  853. return;
  854. }
  855. pgm_read_word_postinc(desc_val, list);
  856. if (desc_val != wValue) {
  857. list += sizeof(struct descriptor_list_struct)-2;
  858. continue;
  859. }
  860. pgm_read_word_postinc(desc_val, list);
  861. if (desc_val != wIndex) {
  862. list += sizeof(struct descriptor_list_struct)-4;
  863. continue;
  864. }
  865. pgm_read_word_postinc(desc_addr, list);
  866. desc_length = pgm_read_byte(list);
  867. break;
  868. }
  869. len = (wLength < 256) ? wLength : 255;
  870. if (len > desc_length) len = desc_length;
  871. list = desc_addr;
  872. do {
  873. // wait for host ready for IN packet
  874. do {
  875. i = UEINTX;
  876. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  877. if (i & (1<<RXOUTI)) return; // abort
  878. // send IN packet
  879. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  880. for (i = n; i; i--) {
  881. pgm_read_byte_postinc(UEDATX, list);
  882. }
  883. len -= n;
  884. usb_send_in();
  885. } while (len || n == ENDPOINT0_SIZE);
  886. return;
  887. }
  888. if (bRequest == SET_ADDRESS) {
  889. usb_send_in();
  890. usb_wait_in_ready();
  891. UDADDR = wValue | (1<<ADDEN);
  892. return;
  893. }
  894. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  895. usb_configuration = wValue;
  896. debug_flush_timer = 0;
  897. usb_send_in();
  898. cfg = endpoint_config_table;
  899. for (i=1; i<NUM_ENDPOINTS; i++) {
  900. UENUM = i;
  901. pgm_read_byte_postinc(en, cfg);
  902. UECONX = en;
  903. if (en) {
  904. pgm_read_byte_postinc(UECFG0X, cfg);
  905. pgm_read_byte_postinc(UECFG1X, cfg);
  906. }
  907. }
  908. UERST = 0x1E;
  909. UERST = 0;
  910. UENUM = DISK_RX_ENDPOINT;
  911. UEIENX = (1<<RXOUTE);
  912. return;
  913. }
  914. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  915. usb_wait_in_ready();
  916. UEDATX = usb_configuration;
  917. usb_send_in();
  918. return;
  919. }
  920. if (bRequest == GET_STATUS) {
  921. usb_wait_in_ready();
  922. i = 0;
  923. if (bmRequestType == 0x82) {
  924. UENUM = wIndex;
  925. if (UECONX & (1<<STALLRQ)) i = 1;
  926. UENUM = 0;
  927. }
  928. UEDATX = i;
  929. UEDATX = 0;
  930. usb_send_in();
  931. return;
  932. }
  933. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  934. && bmRequestType == 0x02 && wValue == 0) {
  935. i = wIndex & 0x7F;
  936. if (i >= 1 && i <= MAX_ENDPOINT) {
  937. usb_send_in();
  938. UENUM = i;
  939. if (bRequest == SET_FEATURE) {
  940. UECONX = (1<<STALLRQ)|(1<<EPEN);
  941. } else {
  942. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  943. UERST = (1 << i);
  944. UERST = 0;
  945. if (i == DISK_TX_ENDPOINT) {
  946. UEIENX = (1<<TXINE);
  947. }
  948. }
  949. return;
  950. }
  951. }
  952. if (wIndex == KEYBOARD_INTERFACE) {
  953. if (bmRequestType == 0xA1) {
  954. if (bRequest == HID_GET_REPORT) {
  955. usb_wait_in_ready();
  956. for (i=0; i < 8; i++) {
  957. UEDATX = keyboard_report_data[i];
  958. }
  959. usb_send_in();
  960. return;
  961. }
  962. if (bRequest == HID_GET_IDLE) {
  963. usb_wait_in_ready();
  964. UEDATX = keyboard_idle_config;
  965. usb_send_in();
  966. return;
  967. }
  968. if (bRequest == HID_GET_PROTOCOL) {
  969. usb_wait_in_ready();
  970. UEDATX = keyboard_protocol;
  971. usb_send_in();
  972. return;
  973. }
  974. }
  975. if (bmRequestType == 0x21) {
  976. if (bRequest == HID_SET_REPORT) {
  977. usb_wait_receive_out();
  978. keyboard_leds = UEDATX;
  979. usb_ack_out();
  980. usb_send_in();
  981. return;
  982. }
  983. if (bRequest == HID_SET_IDLE) {
  984. keyboard_idle_config = (wValue >> 8);
  985. keyboard_idle_count = 0;
  986. //usb_wait_in_ready();
  987. usb_send_in();
  988. return;
  989. }
  990. if (bRequest == HID_SET_PROTOCOL) {
  991. keyboard_protocol = wValue;
  992. //usb_wait_in_ready();
  993. usb_send_in();
  994. return;
  995. }
  996. }
  997. }
  998. if (wIndex == DEBUG_INTERFACE) {
  999. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  1000. len = wLength;
  1001. do {
  1002. // wait for host ready for IN packet
  1003. do {
  1004. i = UEINTX;
  1005. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  1006. if (i & (1<<RXOUTI)) return; // abort
  1007. // send IN packet
  1008. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  1009. for (i = n; i; i--) {
  1010. UEDATX = 0;
  1011. }
  1012. len -= n;
  1013. usb_send_in();
  1014. } while (len || n == ENDPOINT0_SIZE);
  1015. return;
  1016. }
  1017. if (bRequest == HID_SET_REPORT && bmRequestType == 0x21) {
  1018. if (wValue == 0x0300 && wLength == 0x0004) {
  1019. uint8_t b1, b2, b3, b4;
  1020. usb_wait_receive_out();
  1021. b1 = UEDATX;
  1022. b2 = UEDATX;
  1023. b3 = UEDATX;
  1024. b4 = UEDATX;
  1025. usb_ack_out();
  1026. usb_send_in();
  1027. if (b1 == 0xA9 && b2 == 0x45 && b3 == 0xC2 && b4 == 0x6B)
  1028. _reboot_Teensyduino_();
  1029. if (b1 == 0x8B && b2 == 0xC5 && b3 == 0x1D && b4 == 0x70)
  1030. _restart_Teensyduino_();
  1031. }
  1032. }
  1033. }
  1034. if (bRequest == 0xC9 && bmRequestType == 0x40) {
  1035. usb_send_in();
  1036. usb_wait_in_ready();
  1037. _restart_Teensyduino_();
  1038. }
  1039. if (wIndex == DISK_INTERFACE) {
  1040. if (bRequest == MS_BULK_ONLY_RESET && bmRequestType == 0x21) {
  1041. usb_wait_in_ready();
  1042. ms_state = MS_STATE_IDLE;
  1043. usb_send_in();
  1044. return;
  1045. }
  1046. }
  1047. }
  1048. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  1049. }
  1050. // USB Endpoint Interrupt
  1051. ISR(USB_COM_vect)
  1052. {
  1053. uint8_t epnum_save, r=0, need_rx=0, need_tx=0;
  1054. // first, do endpoint 0
  1055. epnum_save = UENUM;
  1056. endpoint0_isr();
  1057. // disable all USB interrupts
  1058. UDIEN = 0;
  1059. UENUM = 0;
  1060. UEIENX = 0;
  1061. UENUM = DISK_RX_ENDPOINT;
  1062. if (UEIENX & (1<<RXOUTE)) {
  1063. r = ENABLE_MORE_RX;
  1064. if (UEINTX & (1<<RXOUTI)) need_rx=1;
  1065. }
  1066. UEIENX = 0;
  1067. UENUM = DISK_TX_ENDPOINT;
  1068. if (UEIENX & (1<<TXINE)) {
  1069. r |= ENABLE_MORE_TX;
  1070. if (UEINTX & (1<<TXINI)) need_tx=1;
  1071. }
  1072. UEIENX = 0;
  1073. // run the mass storage, with non-USB interrupts enabled
  1074. // so lengthy transfers don't starve other interrupts
  1075. if (need_rx || need_tx) {
  1076. sei();
  1077. r = mass_storage_isr(need_rx, need_tx);
  1078. cli();
  1079. }
  1080. // re-enable USB interrupts
  1081. if (r & ENABLE_MORE_RX) {
  1082. UENUM = DISK_RX_ENDPOINT;
  1083. UEIENX = (1<<RXOUTE);
  1084. }
  1085. if (r & ENABLE_MORE_TX) {
  1086. UENUM = DISK_TX_ENDPOINT;
  1087. UEIENX = (1<<TXINE);
  1088. }
  1089. UENUM = 0;
  1090. UEIENX = (1<<RXSTPE);
  1091. UDIEN = (1<<EORSTE)|(1<<SOFE);
  1092. UENUM = epnum_save;
  1093. }
  1094. // USB Device Interrupt - handle all device-level events
  1095. // the transmit buffer flushing is triggered by the start of frame
  1096. //
  1097. ISR(USB_GEN_vect)
  1098. {
  1099. uint8_t intbits, t, i;
  1100. static uint8_t div4=0;
  1101. intbits = UDINT;
  1102. UDINT = 0;
  1103. if (intbits & (1<<EORSTI)) {
  1104. UENUM = 0;
  1105. UECONX = 1;
  1106. UECFG0X = EP_TYPE_CONTROL;
  1107. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  1108. UEIENX = (1<<RXSTPE);
  1109. usb_configuration = 0;
  1110. UENUM = DISK_RX_ENDPOINT;
  1111. UEIENX = 0;
  1112. UENUM = DISK_TX_ENDPOINT;
  1113. UEIENX = 0;
  1114. ms_state = MS_STATE_IDLE;
  1115. }
  1116. if ((intbits & (1<<SOFI)) && usb_configuration) {
  1117. t = debug_flush_timer;
  1118. if (t) {
  1119. debug_flush_timer = -- t;
  1120. if (!t) {
  1121. UENUM = DEBUG_TX_ENDPOINT;
  1122. while ((UEINTX & (1<<RWAL))) {
  1123. UEDATX = 0;
  1124. }
  1125. UEINTX = 0x3A;
  1126. }
  1127. }
  1128. if (keyboard_idle_config && (++div4 & 3) == 0) {
  1129. UENUM = KEYBOARD_ENDPOINT;
  1130. if (UEINTX & (1<<RWAL)) {
  1131. keyboard_idle_count++;
  1132. if (keyboard_idle_count == keyboard_idle_config) {
  1133. keyboard_idle_count = 0;
  1134. for (i=0; i < 8; i++) {
  1135. UEDATX = keyboard_report_data[i];
  1136. }
  1137. UEINTX = 0x3A;
  1138. }
  1139. }
  1140. }
  1141. }
  1142. if (intbits & (1<<SUSPI)) {
  1143. // USB Suspend (inactivity for 3ms)
  1144. UDIEN = (1<<WAKEUPE);
  1145. usb_configuration = 0;
  1146. usb_suspended = 1;
  1147. #if (F_CPU >= 8000000L)
  1148. // WAKEUPI does not work with USB clock freeze
  1149. // when CPU is running less than 8 MHz.
  1150. // Is this a hardware bug?
  1151. USB_FREEZE(); // shut off USB
  1152. PLLCSR = 0; // shut off PLL
  1153. #endif
  1154. // to properly meet the USB spec, current must
  1155. // reduce to less than 2.5 mA, which means using
  1156. // powerdown mode, but that breaks the Arduino
  1157. // user's paradigm....
  1158. }
  1159. if (usb_suspended && (intbits & (1<<WAKEUPI))) {
  1160. // USB Resume (pretty much any activity)
  1161. #if (F_CPU >= 8000000L)
  1162. PLL_CONFIG();
  1163. while (!(PLLCSR & (1<<PLOCK))) ;
  1164. USB_CONFIG();
  1165. #endif
  1166. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  1167. usb_suspended = 0;
  1168. return;
  1169. }
  1170. }