Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. /* USB Serial Example for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/usb_serial.html
  3. * Copyright (c) 2008 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include "usb_common.h"
  24. #include "usb_private.h"
  25. /**************************************************************************
  26. *
  27. * Endpoint Buffer Configuration
  28. *
  29. **************************************************************************/
  30. static const uint8_t PROGMEM endpoint_config_table[] = {
  31. EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER,
  32. EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER,
  33. EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
  34. EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER,
  35. EP_TYPE_INTERRUPT_IN, EP_SIZE(JOYSTICK_SIZE) | JOYSTICK_BUFFER,
  36. EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYMEDIA_SIZE) | KEYMEDIA_BUFFER,
  37. };
  38. /**************************************************************************
  39. *
  40. * Descriptor Data
  41. *
  42. **************************************************************************/
  43. // Descriptors are the data that your computer reads when it auto-detects
  44. // this USB device (called "enumeration" in USB lingo). The most commonly
  45. // changed items are editable at the top of this file. Changing things
  46. // in here should only be done by those who've read chapter 9 of the USB
  47. // spec and relevant portions of any USB class specifications!
  48. static const uint8_t PROGMEM device_descriptor[] = {
  49. 18, // bLength
  50. 1, // bDescriptorType
  51. 0x00, 0x02, // bcdUSB
  52. 0, // bDeviceClass
  53. 0, // bDeviceSubClass
  54. 0, // bDeviceProtocol
  55. ENDPOINT0_SIZE, // bMaxPacketSize0
  56. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  57. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  58. 0x05, 0x01, // bcdDevice
  59. 0, // iManufacturer
  60. 1, // iProduct
  61. 0, // iSerialNumber
  62. 1 // bNumConfigurations
  63. };
  64. // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
  65. static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
  66. 0x05, 0x01, // Usage Page (Generic Desktop),
  67. 0x09, 0x06, // Usage (Keyboard),
  68. 0xA1, 0x01, // Collection (Application),
  69. 0x75, 0x01, // Report Size (1),
  70. 0x95, 0x08, // Report Count (8),
  71. 0x05, 0x07, // Usage Page (Key Codes),
  72. 0x19, 0xE0, // Usage Minimum (224),
  73. 0x29, 0xE7, // Usage Maximum (231),
  74. 0x15, 0x00, // Logical Minimum (0),
  75. 0x25, 0x01, // Logical Maximum (1),
  76. 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
  77. 0x95, 0x01, // Report Count (1),
  78. 0x75, 0x08, // Report Size (8),
  79. 0x81, 0x03, // Input (Constant), ;Reserved byte
  80. 0x95, 0x05, // Report Count (5),
  81. 0x75, 0x01, // Report Size (1),
  82. 0x05, 0x08, // Usage Page (LEDs),
  83. 0x19, 0x01, // Usage Minimum (1),
  84. 0x29, 0x05, // Usage Maximum (5),
  85. 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
  86. 0x95, 0x01, // Report Count (1),
  87. 0x75, 0x03, // Report Size (3),
  88. 0x91, 0x03, // Output (Constant), ;LED report padding
  89. 0x95, 0x06, // Report Count (6),
  90. 0x75, 0x08, // Report Size (8),
  91. 0x15, 0x00, // Logical Minimum (0),
  92. 0x25, 0x7F, // Logical Maximum(104),
  93. 0x05, 0x07, // Usage Page (Key Codes),
  94. 0x19, 0x00, // Usage Minimum (0),
  95. 0x29, 0x7F, // Usage Maximum (104),
  96. 0x81, 0x00, // Input (Data, Array), ;Normal keys
  97. 0xc0 // End Collection
  98. };
  99. static const uint8_t PROGMEM keymedia_hid_report_desc[] = {
  100. 0x05, 0x0C, // Usage Page (Consumer)
  101. 0x09, 0x01, // Usage (Consumer Controls)
  102. 0xA1, 0x01, // Collection (Application)
  103. 0x75, 0x0A, // Report Size (10)
  104. 0x95, 0x04, // Report Count (4)
  105. 0x19, 0x00, // Usage Minimum (0)
  106. 0x2A, 0x9C, 0x02, // Usage Maximum (0x29C)
  107. 0x15, 0x00, // Logical Minimum (0)
  108. 0x26, 0x9C, 0x02, // Logical Maximum (0x29C)
  109. 0x81, 0x00, // Input (Data, Array)
  110. 0x05, 0x01, // Usage Page (Generic Desktop)
  111. 0x75, 0x08, // Report Size (8)
  112. 0x95, 0x03, // Report Count (3)
  113. 0x19, 0x00, // Usage Minimum (0)
  114. 0x29, 0xB7, // Usage Maximum (0xB7)
  115. 0x15, 0x00, // Logical Minimum (0)
  116. 0x26, 0xB7, 0x00, // Logical Maximum (0xB7)
  117. 0x81, 0x00, // Input (Data, Array)
  118. 0xC0 // End Collection
  119. };
  120. // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
  121. static const uint8_t PROGMEM mouse_hid_report_desc[] = {
  122. 0x05, 0x01, // Usage Page (Generic Desktop)
  123. 0x09, 0x02, // Usage (Mouse)
  124. 0xA1, 0x01, // Collection (Application)
  125. 0x05, 0x09, // Usage Page (Button)
  126. 0x19, 0x01, // Usage Minimum (Button #1)
  127. 0x29, 0x08, // Usage Maximum (Button #8)
  128. 0x15, 0x00, // Logical Minimum (0)
  129. 0x25, 0x01, // Logical Maximum (1)
  130. 0x95, 0x08, // Report Count (8)
  131. 0x75, 0x01, // Report Size (1)
  132. 0x81, 0x02, // Input (Data, Variable, Absolute)
  133. 0x05, 0x01, // Usage Page (Generic Desktop)
  134. 0x09, 0x30, // Usage (X)
  135. 0x09, 0x31, // Usage (Y)
  136. 0x09, 0x38, // Usage (Wheel)
  137. 0x15, 0x81, // Logical Minimum (-127)
  138. 0x25, 0x7F, // Logical Maximum (127)
  139. 0x75, 0x08, // Report Size (8),
  140. 0x95, 0x03, // Report Count (3),
  141. 0x81, 0x06, // Input (Data, Variable, Relative)
  142. 0x05, 0x0C, // Usage Page (Consumer)
  143. 0x0A, 0x38, 0x02, // Usage (AC Pan)
  144. 0x15, 0x81, // Logical Minimum (-127)
  145. 0x25, 0x7F, // Logical Maximum (127)
  146. 0x75, 0x08, // Report Size (8),
  147. 0x95, 0x01, // Report Count (1),
  148. 0x81, 0x06, // Input (Data, Variable, Relative)
  149. 0xC0 // End Collection
  150. };
  151. #ifdef JOYSTICK_INTERFACE
  152. static const uint8_t PROGMEM joystick_hid_report_desc[] = {
  153. 0x05, 0x01, // Usage Page (Generic Desktop)
  154. 0x09, 0x04, // Usage (Joystick)
  155. 0xA1, 0x01, // Collection (Application)
  156. 0x15, 0x00, // Logical Minimum (0)
  157. 0x25, 0x01, // Logical Maximum (1)
  158. 0x75, 0x01, // Report Size (1)
  159. 0x95, 0x20, // Report Count (32)
  160. 0x05, 0x09, // Usage Page (Button)
  161. 0x19, 0x01, // Usage Minimum (Button #1)
  162. 0x29, 0x20, // Usage Maximum (Button #32)
  163. 0x81, 0x02, // Input (variable,absolute)
  164. 0x15, 0x00, // Logical Minimum (0)
  165. 0x25, 0x07, // Logical Maximum (7)
  166. 0x35, 0x00, // Physical Minimum (0)
  167. 0x46, 0x3B, 0x01, // Physical Maximum (315)
  168. 0x75, 0x04, // Report Size (4)
  169. 0x95, 0x01, // Report Count (1)
  170. 0x65, 0x14, // Unit (20)
  171. 0x05, 0x01, // Usage Page (Generic Desktop)
  172. 0x09, 0x39, // Usage (Hat switch)
  173. 0x81, 0x42, // Input (variable,absolute,null_state)
  174. 0x05, 0x01, // Usage Page (Generic Desktop)
  175. 0x09, 0x01, // Usage (Pointer)
  176. 0xA1, 0x00, // Collection ()
  177. 0x15, 0x00, // Logical Minimum (0)
  178. 0x26, 0xFF, 0x03, // Logical Maximum (1023)
  179. 0x75, 0x0A, // Report Size (10)
  180. 0x95, 0x04, // Report Count (4)
  181. 0x09, 0x30, // Usage (X)
  182. 0x09, 0x31, // Usage (Y)
  183. 0x09, 0x32, // Usage (Z)
  184. 0x09, 0x35, // Usage (Rz)
  185. 0x81, 0x02, // Input (variable,absolute)
  186. 0xC0, // End Collection
  187. 0x15, 0x00, // Logical Minimum (0)
  188. 0x26, 0xFF, 0x03, // Logical Maximum (1023)
  189. 0x75, 0x0A, // Report Size (10)
  190. 0x95, 0x02, // Report Count (2)
  191. 0x09, 0x36, // Usage (Slider)
  192. 0x09, 0x36, // Usage (Slider)
  193. 0x81, 0x02, // Input (variable,absolute)
  194. 0xC0 // End Collection
  195. };
  196. #endif
  197. static const uint8_t PROGMEM debug_hid_report_desc[] = {
  198. 0x06, 0xC9, 0xFF, // Usage Page 0xFFC9 (vendor defined)
  199. 0x09, 0x04, // Usage 0x04
  200. 0xA1, 0x5C, // Collection 0x5C
  201. 0x75, 0x08, // report size = 8 bits (global)
  202. 0x15, 0x00, // logical minimum = 0 (global)
  203. 0x26, 0xFF, 0x00, // logical maximum = 255 (global)
  204. 0x95, DEBUG_TX_SIZE, // report count (global)
  205. 0x09, 0x75, // usage (local)
  206. 0x81, 0x02, // Input
  207. 0x95, DEBUG_RX_SIZE, // report count (global)
  208. 0x09, 0x76, // usage (local)
  209. 0x91, 0x02, // Output
  210. 0x95, 0x04, // report count (global)
  211. 0x09, 0x76, // usage (local)
  212. 0xB1, 0x02, // Feature
  213. 0xC0 // end collection
  214. };
  215. #define KEYBOARD_HID_DESC_OFFSET ( 9 + 9 )
  216. #define MOUSE_HID_DESC_OFFSET ( 9 + 9+9+7 + 9 )
  217. #define DEBUG_HID_DESC_OFFSET ( 9 + 9+9+7 + 9+9+7 + 9 )
  218. #define JOYSTICK_HID_DESC_OFFSET ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9 )
  219. #define KEYMEDIA_HID_DESC_OFFSET ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7 + 9 )
  220. #define CONFIG1_DESC_SIZE ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7 + 9+9+7 )
  221. static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  222. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  223. 9, // bLength;
  224. 2, // bDescriptorType;
  225. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  226. MSB(CONFIG1_DESC_SIZE),
  227. NUM_INTERFACE, // bNumInterfaces
  228. 1, // bConfigurationValue
  229. 0, // iConfiguration
  230. 0xC0, // bmAttributes
  231. 50, // bMaxPower
  232. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  233. 9, // bLength
  234. 4, // bDescriptorType
  235. KEYBOARD_INTERFACE, // bInterfaceNumber
  236. 0, // bAlternateSetting
  237. 1, // bNumEndpoints
  238. 0x03, // bInterfaceClass (0x03 = HID)
  239. 0x01, // bInterfaceSubClass (0x01 = Boot)
  240. 0x01, // bInterfaceProtocol (0x01 = Keyboard)
  241. 0, // iInterface
  242. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  243. 9, // bLength
  244. 0x21, // bDescriptorType
  245. 0x11, 0x01, // bcdHID
  246. 0, // bCountryCode
  247. 1, // bNumDescriptors
  248. 0x22, // bDescriptorType
  249. sizeof(keyboard_hid_report_desc), // wDescriptorLength
  250. 0,
  251. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  252. 7, // bLength
  253. 5, // bDescriptorType
  254. KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
  255. 0x03, // bmAttributes (0x03=intr)
  256. KEYBOARD_SIZE, 0, // wMaxPacketSize
  257. KEYBOARD_INTERVAL, // bInterval
  258. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  259. 9, // bLength
  260. 4, // bDescriptorType
  261. MOUSE_INTERFACE, // bInterfaceNumber
  262. 0, // bAlternateSetting
  263. 1, // bNumEndpoints
  264. 0x03, // bInterfaceClass (0x03 = HID)
  265. 0x01, // bInterfaceSubClass (0x01 = Boot)
  266. 0x02, // bInterfaceProtocol (0x02 = Mouse)
  267. 0, // iInterface
  268. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  269. 9, // bLength
  270. 0x21, // bDescriptorType
  271. 0x11, 0x01, // bcdHID
  272. 0, // bCountryCode
  273. 1, // bNumDescriptors
  274. 0x22, // bDescriptorType
  275. sizeof(mouse_hid_report_desc), // wDescriptorLength
  276. 0,
  277. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  278. 7, // bLength
  279. 5, // bDescriptorType
  280. MOUSE_ENDPOINT | 0x80, // bEndpointAddress
  281. 0x03, // bmAttributes (0x03=intr)
  282. MOUSE_SIZE, 0, // wMaxPacketSize
  283. MOUSE_INTERVAL, // bInterval
  284. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  285. 9, // bLength
  286. 4, // bDescriptorType
  287. DEBUG_INTERFACE, // bInterfaceNumber
  288. 0, // bAlternateSetting
  289. 2, // bNumEndpoints
  290. 0x03, // bInterfaceClass (0x03 = HID)
  291. 0x00, // bInterfaceSubClass
  292. 0x00, // bInterfaceProtocol
  293. 0, // iInterface
  294. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  295. 9, // bLength
  296. 0x21, // bDescriptorType
  297. 0x11, 0x01, // bcdHID
  298. 0, // bCountryCode
  299. 1, // bNumDescriptors
  300. 0x22, // bDescriptorType
  301. sizeof(debug_hid_report_desc), // wDescriptorLength
  302. 0,
  303. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  304. 7, // bLength
  305. 5, // bDescriptorType
  306. DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
  307. 0x03, // bmAttributes (0x03=intr)
  308. DEBUG_TX_SIZE, 0, // wMaxPacketSize
  309. DEBUG_TX_INTERVAL, // bInterval
  310. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  311. 7, // bLength
  312. 5, // bDescriptorType
  313. DEBUG_RX_ENDPOINT, // bEndpointAddress
  314. 0x03, // bmAttributes (0x03=intr)
  315. DEBUG_RX_SIZE, 0, // wMaxPacketSize
  316. DEBUG_RX_INTERVAL, // bInterval
  317. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  318. 9, // bLength
  319. 4, // bDescriptorType
  320. JOYSTICK_INTERFACE, // bInterfaceNumber
  321. 0, // bAlternateSetting
  322. 1, // bNumEndpoints
  323. 0x03, // bInterfaceClass (0x03 = HID)
  324. 0x00, // bInterfaceSubClass
  325. 0x00, // bInterfaceProtocol
  326. 0, // iInterface
  327. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  328. 9, // bLength
  329. 0x21, // bDescriptorType
  330. 0x11, 0x01, // bcdHID
  331. 0, // bCountryCode
  332. 1, // bNumDescriptors
  333. 0x22, // bDescriptorType
  334. sizeof(joystick_hid_report_desc), // wDescriptorLength
  335. 0,
  336. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  337. 7, // bLength
  338. 5, // bDescriptorType
  339. JOYSTICK_ENDPOINT | 0x80, // bEndpointAddress
  340. 0x03, // bmAttributes (0x03=intr)
  341. 12, 0, // wMaxPacketSize
  342. JOYSTICK_INTERVAL, // bInterval
  343. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  344. 9, // bLength
  345. 4, // bDescriptorType
  346. KEYMEDIA_INTERFACE, // bInterfaceNumber
  347. 0, // bAlternateSetting
  348. 1, // bNumEndpoints
  349. 0x03, // bInterfaceClass (0x03 = HID)
  350. 0x00, // bInterfaceSubClass
  351. 0x00, // bInterfaceProtocol
  352. 0, // iInterface
  353. // HID interface descriptor, HID 1.11 spec, section 6.2.1
  354. 9, // bLength
  355. 0x21, // bDescriptorType
  356. 0x11, 0x01, // bcdHID
  357. 0, // bCountryCode
  358. 1, // bNumDescriptors
  359. 0x22, // bDescriptorType
  360. LSB(sizeof(keymedia_hid_report_desc)), // wDescriptorLength
  361. MSB(sizeof(keymedia_hid_report_desc)),
  362. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  363. 7, // bLength
  364. 5, // bDescriptorType
  365. KEYMEDIA_ENDPOINT | 0x80, // bEndpointAddress
  366. 0x03, // bmAttributes (0x03=intr)
  367. KEYMEDIA_SIZE, 0, // wMaxPacketSize
  368. KEYMEDIA_INTERVAL, // bInterval
  369. };
  370. // If you're desperate for a little extra code memory, these strings
  371. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  372. // in the device desciptor are changed to zeros.
  373. struct usb_string_descriptor_struct {
  374. uint8_t bLength;
  375. uint8_t bDescriptorType;
  376. int16_t wString[];
  377. };
  378. static const struct usb_string_descriptor_struct PROGMEM string0 = {
  379. 4,
  380. 3,
  381. {0x0409}
  382. };
  383. static const struct usb_string_descriptor_struct PROGMEM string1 = {
  384. sizeof(STR_PRODUCT),
  385. 3,
  386. STR_PRODUCT
  387. };
  388. // This table defines which descriptor data is sent for each specific
  389. // request from the host (in wValue and wIndex).
  390. static const struct descriptor_list_struct {
  391. uint16_t wValue;
  392. uint16_t wIndex;
  393. const uint8_t *addr;
  394. uint8_t length;
  395. } PROGMEM descriptor_list[] = {
  396. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  397. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  398. {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
  399. {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
  400. {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
  401. {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
  402. {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
  403. {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
  404. {0x2200, JOYSTICK_INTERFACE, joystick_hid_report_desc, sizeof(joystick_hid_report_desc)},
  405. {0x2100, JOYSTICK_INTERFACE, config1_descriptor+JOYSTICK_HID_DESC_OFFSET, 9},
  406. {0x2200, KEYMEDIA_INTERFACE, keymedia_hid_report_desc, sizeof(keymedia_hid_report_desc)},
  407. {0x2100, KEYMEDIA_INTERFACE, config1_descriptor+KEYMEDIA_HID_DESC_OFFSET, 9},
  408. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  409. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_PRODUCT)},
  410. };
  411. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  412. /**************************************************************************
  413. *
  414. * Variables - these are the only non-stack RAM usage
  415. *
  416. **************************************************************************/
  417. // zero when we are not configured, non-zero when enumerated
  418. volatile uint8_t usb_configuration USBSTATE;
  419. volatile uint8_t usb_suspended USBSTATE;
  420. // the time remaining before we transmit any partially full
  421. // packet, or send a zero length packet.
  422. volatile uint8_t debug_flush_timer USBSTATE;
  423. // byte0: which modifier keys are currently pressed
  424. // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
  425. // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
  426. // byte1: media keys (TODO: document these)
  427. // bytes2-7: which keys are currently pressed, up to 6 keys may be down at once
  428. uint8_t keyboard_report_data[8] USBSTATE;
  429. // protocol setting from the host. We use exactly the same report
  430. // either way, so this variable only stores the setting since we
  431. // are required to be able to report which setting is in use.
  432. static uint8_t keyboard_protocol USBSTATE;
  433. // the idle configuration, how often we send the report to the
  434. // host (ms * 4) even when it hasn't changed
  435. static uint8_t keyboard_idle_config USBSTATE;
  436. // count until idle timeout
  437. uint8_t keyboard_idle_count USBSTATE;
  438. // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
  439. volatile uint8_t keyboard_leds USBSTATE;
  440. // which buttons are currently pressed
  441. uint8_t mouse_buttons USBSTATE;
  442. // protocol setting from the host. We use exactly the same report
  443. // either way, so this variable only stores the setting since we
  444. // are required to be able to report which setting is in use.
  445. static uint8_t mouse_protocol USBSTATE;
  446. // joystick data
  447. uint8_t joystick_report_data[12] USBSTATE;
  448. // keyboard media keys data
  449. uint8_t keymedia_report_data[8] USBSTATE;
  450. uint16_t keymedia_consumer_keys[4] USBSTATE;
  451. uint8_t keymedia_system_keys[3] USBSTATE;
  452. /**************************************************************************
  453. *
  454. * Public Functions - these are the API intended for the user
  455. *
  456. **************************************************************************/
  457. // initialize USB serial
  458. void usb_init(void)
  459. {
  460. uint8_t u;
  461. u = USBCON;
  462. if ((u & (1<<USBE)) && !(u & (1<<FRZCLK))) return;
  463. HW_CONFIG();
  464. USB_FREEZE(); // enable USB
  465. PLL_CONFIG(); // config PLL
  466. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  467. USB_CONFIG(); // start USB clock
  468. UDCON = 0; // enable attach resistor
  469. usb_configuration = 0;
  470. usb_suspended = 0;
  471. debug_flush_timer = 0;
  472. keyboard_report_data[0] = 0;
  473. keyboard_report_data[1] = 0;
  474. keyboard_report_data[2] = 0;
  475. keyboard_report_data[3] = 0;
  476. keyboard_report_data[4] = 0;
  477. keyboard_report_data[5] = 0;
  478. keyboard_report_data[6] = 0;
  479. keyboard_report_data[7] = 0;
  480. keyboard_protocol = 1;
  481. keyboard_idle_config = 125;
  482. keyboard_idle_count = 0;
  483. keyboard_leds = 0;
  484. mouse_buttons = 0;
  485. mouse_protocol = 1;
  486. joystick_report_data[0] = 0;
  487. joystick_report_data[1] = 0;
  488. joystick_report_data[2] = 0;
  489. joystick_report_data[3] = 0;
  490. joystick_report_data[4] = 0x0F;
  491. joystick_report_data[5] = 0x20;
  492. joystick_report_data[6] = 0x80;
  493. joystick_report_data[7] = 0x00;
  494. joystick_report_data[8] = 0x02;
  495. joystick_report_data[9] = 0x08;
  496. joystick_report_data[10] = 0x20;
  497. joystick_report_data[11] = 0x80;
  498. keymedia_report_data[0] = 0;
  499. keymedia_report_data[1] = 0;
  500. keymedia_report_data[2] = 0;
  501. keymedia_report_data[3] = 0;
  502. keymedia_report_data[4] = 0;
  503. keymedia_report_data[5] = 0;
  504. keymedia_report_data[6] = 0;
  505. keymedia_report_data[7] = 0;
  506. keymedia_consumer_keys[0] = 0;
  507. keymedia_consumer_keys[1] = 0;
  508. keymedia_consumer_keys[2] = 0;
  509. keymedia_consumer_keys[3] = 0;
  510. keymedia_system_keys[0] = 0;
  511. keymedia_system_keys[1] = 0;
  512. keymedia_system_keys[2] = 0;
  513. UDINT = 0;
  514. UDIEN = (1<<EORSTE)|(1<<SOFE);
  515. //sei(); // init() in wiring.c does this
  516. }
  517. void usb_shutdown(void)
  518. {
  519. UDIEN = 0; // disable interrupts
  520. UDCON = 1; // disconnect attach resistor
  521. USBCON = 0; // shut off USB periperal
  522. PLLCSR = 0; // shut off PLL
  523. usb_configuration = 0;
  524. usb_suspended = 1;
  525. }
  526. // Public API functions moved to usb_api.cpp
  527. /**************************************************************************
  528. *
  529. * Private Functions - not intended for general user consumption....
  530. *
  531. **************************************************************************/
  532. // USB Device Interrupt - handle all device-level events
  533. // the transmit buffer flushing is triggered by the start of frame
  534. //
  535. ISR(USB_GEN_vect)
  536. {
  537. uint8_t intbits, t, i;
  538. static uint8_t div4=0;
  539. intbits = UDINT;
  540. UDINT = 0;
  541. if (intbits & (1<<EORSTI)) {
  542. UENUM = 0;
  543. UECONX = 1;
  544. UECFG0X = EP_TYPE_CONTROL;
  545. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  546. UEIENX = (1<<RXSTPE);
  547. usb_configuration = 0;
  548. }
  549. if ((intbits & (1<<SOFI)) && usb_configuration) {
  550. t = debug_flush_timer;
  551. if (t) {
  552. debug_flush_timer = -- t;
  553. if (!t) {
  554. UENUM = DEBUG_TX_ENDPOINT;
  555. while ((UEINTX & (1<<RWAL))) {
  556. UEDATX = 0;
  557. }
  558. UEINTX = 0x3A;
  559. }
  560. }
  561. if (keyboard_idle_config && (++div4 & 3) == 0) {
  562. UENUM = KEYBOARD_ENDPOINT;
  563. if (UEINTX & (1<<RWAL)) {
  564. keyboard_idle_count++;
  565. if (keyboard_idle_count == keyboard_idle_config) {
  566. keyboard_idle_count = 0;
  567. //len = keyboard_protocol ? sizeof(keyboard_keys) : 8;
  568. for (i=0; i < 8; i++) {
  569. UEDATX = keyboard_report_data[i];
  570. }
  571. UEINTX = 0x3A;
  572. }
  573. }
  574. }
  575. }
  576. if (intbits & (1<<SUSPI)) {
  577. // USB Suspend (inactivity for 3ms)
  578. UDIEN = (1<<WAKEUPE);
  579. usb_configuration = 0;
  580. usb_suspended = 1;
  581. #if (F_CPU >= 8000000L)
  582. // WAKEUPI does not work with USB clock freeze
  583. // when CPU is running less than 8 MHz.
  584. // Is this a hardware bug?
  585. USB_FREEZE(); // shut off USB
  586. PLLCSR = 0; // shut off PLL
  587. #endif
  588. // to properly meet the USB spec, current must
  589. // reduce to less than 2.5 mA, which means using
  590. // powerdown mode, but that breaks the Arduino
  591. // user's paradigm....
  592. }
  593. if (usb_suspended && (intbits & (1<<WAKEUPI))) {
  594. // USB Resume (pretty much any activity)
  595. #if (F_CPU >= 8000000L)
  596. PLL_CONFIG();
  597. while (!(PLLCSR & (1<<PLOCK))) ;
  598. USB_CONFIG();
  599. #endif
  600. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  601. usb_suspended = 0;
  602. return;
  603. }
  604. }
  605. // Misc functions to wait for ready and send/receive packets
  606. static inline void usb_wait_in_ready(void)
  607. {
  608. while (!(UEINTX & (1<<TXINI))) ;
  609. }
  610. static inline void usb_send_in(void)
  611. {
  612. UEINTX = ~(1<<TXINI);
  613. }
  614. static inline void usb_wait_receive_out(void)
  615. {
  616. while (!(UEINTX & (1<<RXOUTI))) ;
  617. }
  618. static inline void usb_ack_out(void)
  619. {
  620. UEINTX = ~(1<<RXOUTI);
  621. }
  622. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  623. // other endpoints are manipulated by the user-callable
  624. // functions, and the start-of-frame interrupt.
  625. //
  626. ISR(USB_COM_vect)
  627. {
  628. uint8_t intbits;
  629. const uint8_t *list;
  630. const uint8_t *cfg;
  631. uint8_t i, n, len;
  632. uint8_t bmRequestType;
  633. uint8_t bRequest;
  634. uint16_t wValue;
  635. uint16_t wIndex;
  636. uint16_t wLength;
  637. uint16_t desc_val;
  638. const uint8_t *desc_addr;
  639. uint8_t desc_length;
  640. UENUM = 0;
  641. intbits = UEINTX;
  642. if (intbits & (1<<RXSTPI)) {
  643. bmRequestType = UEDATX;
  644. bRequest = UEDATX;
  645. read_word_lsbfirst(wValue, UEDATX);
  646. read_word_lsbfirst(wIndex, UEDATX);
  647. read_word_lsbfirst(wLength, UEDATX);
  648. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  649. if (bRequest == GET_DESCRIPTOR) {
  650. list = (const uint8_t *)descriptor_list;
  651. for (i=0; ; i++) {
  652. if (i >= NUM_DESC_LIST) {
  653. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  654. return;
  655. }
  656. pgm_read_word_postinc(desc_val, list);
  657. if (desc_val != wValue) {
  658. list += sizeof(struct descriptor_list_struct)-2;
  659. continue;
  660. }
  661. pgm_read_word_postinc(desc_val, list);
  662. if (desc_val != wIndex) {
  663. list += sizeof(struct descriptor_list_struct)-4;
  664. continue;
  665. }
  666. pgm_read_word_postinc(desc_addr, list);
  667. desc_length = pgm_read_byte(list);
  668. break;
  669. }
  670. len = (wLength < 256) ? wLength : 255;
  671. if (len > desc_length) len = desc_length;
  672. list = desc_addr;
  673. do {
  674. // wait for host ready for IN packet
  675. do {
  676. i = UEINTX;
  677. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  678. if (i & (1<<RXOUTI)) return; // abort
  679. // send IN packet
  680. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  681. for (i = n; i; i--) {
  682. pgm_read_byte_postinc(UEDATX, list);
  683. }
  684. len -= n;
  685. usb_send_in();
  686. } while (len || n == ENDPOINT0_SIZE);
  687. return;
  688. }
  689. if (bRequest == SET_ADDRESS) {
  690. usb_send_in();
  691. usb_wait_in_ready();
  692. UDADDR = wValue | (1<<ADDEN);
  693. return;
  694. }
  695. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  696. usb_configuration = wValue;
  697. debug_flush_timer = 0;
  698. usb_send_in();
  699. cfg = endpoint_config_table;
  700. for (i=1; i<7; i++) {
  701. UENUM = i;
  702. UECONX = 1;
  703. pgm_read_byte_postinc(UECFG0X, cfg);
  704. pgm_read_byte_postinc(UECFG1X, cfg);
  705. }
  706. UERST = 0x1E;
  707. UERST = 0;
  708. return;
  709. }
  710. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  711. usb_wait_in_ready();
  712. UEDATX = usb_configuration;
  713. usb_send_in();
  714. return;
  715. }
  716. if (bRequest == GET_STATUS) {
  717. usb_wait_in_ready();
  718. i = 0;
  719. if (bmRequestType == 0x82) {
  720. UENUM = wIndex;
  721. if (UECONX & (1<<STALLRQ)) i = 1;
  722. UENUM = 0;
  723. }
  724. UEDATX = i;
  725. UEDATX = 0;
  726. usb_send_in();
  727. return;
  728. }
  729. if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
  730. && bmRequestType == 0x02 && wValue == 0) {
  731. i = wIndex & 0x7F;
  732. if (i >= 1 && i <= NUM_ENDPOINTS) {
  733. usb_send_in();
  734. UENUM = i;
  735. if (bRequest == SET_FEATURE) {
  736. UECONX = (1<<STALLRQ)|(1<<EPEN);
  737. } else {
  738. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  739. UERST = (1 << i);
  740. UERST = 0;
  741. }
  742. return;
  743. }
  744. }
  745. if (wIndex == KEYBOARD_INTERFACE) {
  746. if (bmRequestType == 0xA1) {
  747. if (bRequest == HID_GET_REPORT) {
  748. usb_wait_in_ready();
  749. //len = keyboard_protocol ? sizeof(keyboard_keys) : 8;
  750. for (i=0; i < 8; i++) {
  751. UEDATX = keyboard_report_data[i];
  752. }
  753. usb_send_in();
  754. return;
  755. }
  756. if (bRequest == HID_GET_IDLE) {
  757. usb_wait_in_ready();
  758. UEDATX = keyboard_idle_config;
  759. usb_send_in();
  760. return;
  761. }
  762. if (bRequest == HID_GET_PROTOCOL) {
  763. usb_wait_in_ready();
  764. UEDATX = keyboard_protocol;
  765. usb_send_in();
  766. return;
  767. }
  768. }
  769. if (bmRequestType == 0x21) {
  770. if (bRequest == HID_SET_REPORT) {
  771. usb_wait_receive_out();
  772. keyboard_leds = UEDATX;
  773. usb_ack_out();
  774. usb_send_in();
  775. return;
  776. }
  777. if (bRequest == HID_SET_IDLE) {
  778. keyboard_idle_config = (wValue >> 8);
  779. keyboard_idle_count = 0;
  780. //usb_wait_in_ready();
  781. usb_send_in();
  782. return;
  783. }
  784. if (bRequest == HID_SET_PROTOCOL) {
  785. keyboard_protocol = wValue;
  786. //usb_wait_in_ready();
  787. usb_send_in();
  788. return;
  789. }
  790. }
  791. }
  792. if (wIndex == MOUSE_INTERFACE) {
  793. if (bmRequestType == 0xA1) {
  794. if (bRequest == HID_GET_REPORT) {
  795. usb_wait_in_ready();
  796. UEDATX = mouse_buttons;
  797. UEDATX = 0;
  798. UEDATX = 0;
  799. UEDATX = 0;
  800. UEDATX = 0;
  801. usb_send_in();
  802. return;
  803. }
  804. if (bRequest == HID_GET_PROTOCOL) {
  805. usb_wait_in_ready();
  806. UEDATX = mouse_protocol;
  807. usb_send_in();
  808. return;
  809. }
  810. }
  811. if (bmRequestType == 0x21) {
  812. if (bRequest == HID_SET_PROTOCOL) {
  813. mouse_protocol = wValue;
  814. usb_send_in();
  815. return;
  816. }
  817. }
  818. }
  819. if (wIndex == JOYSTICK_INTERFACE) {
  820. if (bmRequestType == 0xA1) {
  821. if (bRequest == HID_GET_REPORT) {
  822. usb_wait_in_ready();
  823. for (i=0; i<12; i++) {
  824. UEDATX = joystick_report_data[i];
  825. }
  826. usb_send_in();
  827. return;
  828. }
  829. }
  830. }
  831. if (wIndex == KEYMEDIA_INTERFACE) {
  832. if (bmRequestType == 0xA1) {
  833. if (bRequest == HID_GET_REPORT) {
  834. usb_wait_in_ready();
  835. for (i=0; i<8; i++) {
  836. UEDATX = keymedia_report_data[i];
  837. }
  838. usb_send_in();
  839. return;
  840. }
  841. }
  842. }
  843. if (wIndex == DEBUG_INTERFACE) {
  844. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  845. len = wLength;
  846. do {
  847. // wait for host ready for IN packet
  848. do {
  849. i = UEINTX;
  850. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  851. if (i & (1<<RXOUTI)) return; // abort
  852. // send IN packet
  853. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  854. for (i = n; i; i--) {
  855. UEDATX = 0;
  856. }
  857. len -= n;
  858. usb_send_in();
  859. } while (len || n == ENDPOINT0_SIZE);
  860. return;
  861. }
  862. if (bRequest == HID_SET_REPORT && bmRequestType == 0x21) {
  863. if (wValue == 0x0300 && wLength == 0x0004) {
  864. uint8_t b1, b2, b3, b4;
  865. usb_wait_receive_out();
  866. b1 = UEDATX;
  867. b2 = UEDATX;
  868. b3 = UEDATX;
  869. b4 = UEDATX;
  870. usb_ack_out();
  871. usb_send_in();
  872. if (b1 == 0xA9 && b2 == 0x45 && b3 == 0xC2 && b4 == 0x6B)
  873. _reboot_Teensyduino_();
  874. if (b1 == 0x8B && b2 == 0xC5 && b3 == 0x1D && b4 == 0x70)
  875. _restart_Teensyduino_();
  876. }
  877. }
  878. }
  879. if (bRequest == 0xC9 && bmRequestType == 0x40) {
  880. usb_send_in();
  881. usb_wait_in_ready();
  882. _restart_Teensyduino_();
  883. }
  884. }
  885. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  886. }