Keyboard firmwares for Atmel AVR and Cortex-M
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
13 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/usb_keyboard.html
  3. * Copyright (c) 2009 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include <stdint.h>
  24. #include <stdbool.h>
  25. #include <avr/io.h>
  26. #include <avr/pgmspace.h>
  27. #include <avr/interrupt.h>
  28. #include "usb.h"
  29. #include "usb_keyboard.h"
  30. #include "usb_mouse.h"
  31. #include "usb_debug.h"
  32. #include "usb_extra.h"
  33. #include "print.h"
  34. #include "util.h"
  35. /**************************************************************************
  36. *
  37. * Configurable Options
  38. *
  39. **************************************************************************/
  40. // You can change these to give your code its own name.
  41. #ifndef MANUFACTURER
  42. # define STR_MANUFACTURER L"t.m.k."
  43. #else
  44. # define STR_MANUFACTURER LSTR(MANUFACTURER)
  45. #endif
  46. #ifndef PRODUCT
  47. # define STR_PRODUCT L"t.m.k. keyboard"
  48. #else
  49. # define STR_PRODUCT LSTR(PRODUCT)
  50. #endif
  51. // Mac OS-X and Linux automatically load the correct drivers. On
  52. // Windows, even though the driver is supplied by Microsoft, an
  53. // INF file is needed to load the driver. These numbers need to
  54. // match the INF file.
  55. #ifndef VENDOR_ID
  56. # define VENDOR_ID 0xFEED
  57. #endif
  58. #ifndef PRODUCT_ID
  59. # define PRODUCT_ID 0xBABE
  60. #endif
  61. // USB devices are supposed to implment a halt feature, which is
  62. // rarely (if ever) used. If you comment this line out, the halt
  63. // code will be removed, saving 102 bytes of space (gcc 4.3.0).
  64. // This is not strictly USB compliant, but works with all major
  65. // operating systems.
  66. #define SUPPORT_ENDPOINT_HALT
  67. /**************************************************************************
  68. *
  69. * Endpoint Buffer Configuration
  70. *
  71. **************************************************************************/
  72. #define ENDPOINT0_SIZE 32
  73. bool remote_wakeup = false;
  74. bool suspend = false;
  75. // 0:control endpoint is enabled automatically by controller.
  76. static const uint8_t PROGMEM endpoint_config_table[] = {
  77. // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
  78. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 1
  79. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2
  80. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
  81. 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
  82. 0, // 5
  83. 0, // 6
  84. };
  85. /**************************************************************************
  86. *
  87. * Descriptor Data
  88. *
  89. **************************************************************************/
  90. // Descriptors are the data that your computer reads when it auto-detects
  91. // this USB device (called "enumeration" in USB lingo). The most commonly
  92. // changed items are editable at the top of this file. Changing things
  93. // in here should only be done by those who've read chapter 9 of the USB
  94. // spec and relevant portions of any USB class specifications!
  95. static uint8_t PROGMEM device_descriptor[] = {
  96. 18, // bLength
  97. 1, // bDescriptorType
  98. 0x00, 0x02, // bcdUSB
  99. 0, // bDeviceClass
  100. 0, // bDeviceSubClass
  101. 0, // bDeviceProtocol
  102. ENDPOINT0_SIZE, // bMaxPacketSize0
  103. LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
  104. LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
  105. 0x00, 0x01, // bcdDevice
  106. 1, // iManufacturer
  107. 2, // iProduct
  108. 0, // iSerialNumber
  109. 1 // bNumConfigurations
  110. };
  111. // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
  112. static uint8_t PROGMEM keyboard_hid_report_desc[] = {
  113. 0x05, 0x01, // Usage Page (Generic Desktop),
  114. 0x09, 0x06, // Usage (Keyboard),
  115. 0xA1, 0x01, // Collection (Application),
  116. 0x75, 0x01, // Report Size (1),
  117. 0x95, 0x08, // Report Count (8),
  118. 0x05, 0x07, // Usage Page (Key Codes),
  119. 0x19, 0xE0, // Usage Minimum (224),
  120. 0x29, 0xE7, // Usage Maximum (231),
  121. 0x15, 0x00, // Logical Minimum (0),
  122. 0x25, 0x01, // Logical Maximum (1),
  123. 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
  124. 0x95, 0x01, // Report Count (1),
  125. 0x75, 0x08, // Report Size (8),
  126. 0x81, 0x03, // Input (Constant), ;Reserved byte
  127. 0x95, 0x05, // Report Count (5),
  128. 0x75, 0x01, // Report Size (1),
  129. 0x05, 0x08, // Usage Page (LEDs),
  130. 0x19, 0x01, // Usage Minimum (1),
  131. 0x29, 0x05, // Usage Maximum (5),
  132. 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
  133. 0x95, 0x01, // Report Count (1),
  134. 0x75, 0x03, // Report Size (3),
  135. 0x91, 0x03, // Output (Constant), ;LED report padding
  136. 0x95, 0x06, // Report Count (6),
  137. 0x75, 0x08, // Report Size (8),
  138. 0x15, 0x00, // Logical Minimum (0),
  139. 0x25, 0x68, // Logical Maximum(104),
  140. 0x05, 0x07, // Usage Page (Key Codes),
  141. 0x19, 0x00, // Usage Minimum (0),
  142. 0x29, 0x68, // Usage Maximum (104),
  143. 0x81, 0x00, // Input (Data, Array),
  144. 0xc0 // End Collection
  145. };
  146. // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
  147. // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
  148. // http://www.keil.com/forum/15671/
  149. // http://www.microsoft.com/whdc/device/input/wheel.mspx
  150. static uint8_t PROGMEM mouse_hid_report_desc[] = {
  151. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  152. 0x09, 0x02, // USAGE (Mouse)
  153. 0xa1, 0x01, // COLLECTION (Application)
  154. 0x09, 0x02, // USAGE (Mouse)
  155. 0xa1, 0x02, // COLLECTION (Logical)
  156. 0x09, 0x01, // USAGE (Pointer)
  157. 0xa1, 0x00, // COLLECTION (Physical)
  158. // ------------------------------ Buttons
  159. 0x05, 0x09, // USAGE_PAGE (Button)
  160. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  161. 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
  162. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  163. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  164. 0x75, 0x01, // REPORT_SIZE (1)
  165. 0x95, 0x05, // REPORT_COUNT (5)
  166. 0x81, 0x02, // INPUT (Data,Var,Abs)
  167. // ------------------------------ Padding
  168. 0x75, 0x03, // REPORT_SIZE (3)
  169. 0x95, 0x01, // REPORT_COUNT (1)
  170. 0x81, 0x03, // INPUT (Cnst,Var,Abs)
  171. // ------------------------------ X,Y position
  172. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  173. 0x09, 0x30, // USAGE (X)
  174. 0x09, 0x31, // USAGE (Y)
  175. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  176. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  177. 0x75, 0x08, // REPORT_SIZE (8)
  178. 0x95, 0x02, // REPORT_COUNT (2)
  179. 0x81, 0x06, // INPUT (Data,Var,Rel)
  180. 0xa1, 0x02, // COLLECTION (Logical)
  181. // ------------------------------ Vertical wheel res multiplier
  182. 0x09, 0x48, // USAGE (Resolution Multiplier)
  183. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  184. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  185. 0x35, 0x01, // PHYSICAL_MINIMUM (1)
  186. 0x45, 0x04, // PHYSICAL_MAXIMUM (4)
  187. 0x75, 0x02, // REPORT_SIZE (2)
  188. 0x95, 0x01, // REPORT_COUNT (1)
  189. 0xa4, // PUSH
  190. 0xb1, 0x02, // FEATURE (Data,Var,Abs)
  191. // ------------------------------ Vertical wheel
  192. 0x09, 0x38, // USAGE (Wheel)
  193. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  194. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  195. 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
  196. 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
  197. 0x75, 0x08, // REPORT_SIZE (8)
  198. 0x81, 0x06, // INPUT (Data,Var,Rel)
  199. 0xc0, // END_COLLECTION
  200. 0xa1, 0x02, // COLLECTION (Logical)
  201. // ------------------------------ Horizontal wheel res multiplier
  202. 0x09, 0x48, // USAGE (Resolution Multiplier)
  203. 0xb4, // POP
  204. 0xb1, 0x02, // FEATURE (Data,Var,Abs)
  205. // ------------------------------ Padding for Feature report
  206. 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
  207. 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
  208. 0x75, 0x04, // REPORT_SIZE (4)
  209. 0xb1, 0x03, // FEATURE (Cnst,Var,Abs)
  210. // ------------------------------ Horizontal wheel
  211. 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
  212. 0x0a, 0x38, 0x02, // USAGE (AC Pan)
  213. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  214. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  215. 0x75, 0x08, // REPORT_SIZE (8)
  216. 0x81, 0x06, // INPUT (Data,Var,Rel)
  217. 0xc0, // END_COLLECTION
  218. 0xc0, // END_COLLECTION
  219. 0xc0, // END_COLLECTION
  220. 0xc0 // END_COLLECTION
  221. };
  222. static uint8_t PROGMEM debug_hid_report_desc[] = {
  223. 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
  224. 0x09, 0x74, // Usage 0x74
  225. 0xA1, 0x53, // Collection 0x53
  226. 0x75, 0x08, // report size = 8 bits
  227. 0x15, 0x00, // logical minimum = 0
  228. 0x26, 0xFF, 0x00, // logical maximum = 255
  229. 0x95, DEBUG_TX_SIZE, // report count
  230. 0x09, 0x75, // usage
  231. 0x81, 0x02, // Input (array)
  232. 0xC0 // end collection
  233. };
  234. // audio controls & system controls
  235. // http://www.microsoft.com/whdc/archive/w2kbd.mspx
  236. static uint8_t PROGMEM extra_hid_report_desc[] = {
  237. 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
  238. 0x09, 0x01, // USAGE (Consumer Control)
  239. 0xa1, 0x01, // COLLECTION (Application)
  240. 0x85, 0x01, // REPORT_ID (1)
  241. 0x09, 0xe9, // USAGE (Volume Up)
  242. 0x09, 0xea, // USAGE (Volume Down)
  243. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  244. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  245. 0x75, 0x01, // REPORT_SIZE (1)
  246. 0x95, 0x02, // REPORT_COUNT (2)
  247. 0x81, 0x02, // INPUT (Data,Var,Abs)
  248. 0x09, 0xe2, // USAGE (Mute)
  249. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  250. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  251. 0x75, 0x01, // REPORT_SIZE (1)
  252. 0x95, 0x01, // REPORT_COUNT (1)
  253. 0x81, 0x06, // INPUT (Data,Var,Rel)
  254. 0x95, 0x05, // REPORT_COUNT (5)
  255. 0x81, 0x07, // INPUT (Cnst,Var,Abs)
  256. 0xc0, // END_COLLECTION
  257. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  258. 0x09, 0x80, // USAGE (System Control)
  259. 0xa1, 0x01, // COLLECTION (Application)
  260. 0x85, 0x02, // REPORT_ID (2)
  261. 0x19, 0x81, // USAGE_MINIMUM (System Power Down)
  262. 0x29, 0x83, // USAGE_MAXIMUM (System Wake Up)
  263. 0x95, 0x03, // REPORT_COUNT (3)
  264. 0x81, 0x06, // INPUT (Data,Var,Rel)
  265. 0x95, 0x05, // REPORT_COUNT (5)
  266. 0x81, 0x07, // INPUT (Cnst,Var,Rel)
  267. 0xc0 // END_COLLECTION
  268. };
  269. #define CONFIG1_DESC_SIZE (9+(9+9+7)*4)
  270. #define KEYBOARD_HID_DESC_OFFSET (9+(9+9+7)*0+9)
  271. #define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9)
  272. #define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9)
  273. #define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9)
  274. static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
  275. // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
  276. 9, // bLength;
  277. 2, // bDescriptorType;
  278. LSB(CONFIG1_DESC_SIZE), // wTotalLength
  279. MSB(CONFIG1_DESC_SIZE),
  280. 4, // bNumInterfaces
  281. 1, // bConfigurationValue
  282. 0, // iConfiguration
  283. 0xA0, // bmAttributes
  284. 50, // bMaxPower
  285. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  286. 9, // bLength
  287. 4, // bDescriptorType
  288. KEYBOARD_INTERFACE, // bInterfaceNumber
  289. 0, // bAlternateSetting
  290. 1, // bNumEndpoints
  291. 0x03, // bInterfaceClass (0x03 = HID)
  292. 0x01, // bInterfaceSubClass (0x01 = Boot)
  293. 0x01, // bInterfaceProtocol (0x01 = Keyboard)
  294. 0, // iInterface
  295. // HID descriptor, HID 1.11 spec, section 6.2.1
  296. 9, // bLength
  297. 0x21, // bDescriptorType
  298. 0x11, 0x01, // bcdHID
  299. 0, // bCountryCode
  300. 1, // bNumDescriptors
  301. 0x22, // bDescriptorType
  302. sizeof(keyboard_hid_report_desc), // wDescriptorLength
  303. 0,
  304. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  305. 7, // bLength
  306. 5, // bDescriptorType
  307. KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
  308. 0x03, // bmAttributes (0x03=intr)
  309. KEYBOARD_SIZE, 0, // wMaxPacketSize
  310. 1, // bInterval
  311. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  312. 9, // bLength
  313. 4, // bDescriptorType
  314. MOUSE_INTERFACE, // bInterfaceNumber
  315. 0, // bAlternateSetting
  316. 1, // bNumEndpoints
  317. 0x03, // bInterfaceClass (0x03 = HID)
  318. 0x01, // bInterfaceSubClass (0x01 = Boot)
  319. 0x02, // bInterfaceProtocol (0x02 = Mouse)
  320. 0, // iInterface
  321. // HID descriptor, HID 1.11 spec, section 6.2.1
  322. 9, // bLength
  323. 0x21, // bDescriptorType
  324. 0x11, 0x01, // bcdHID
  325. 0, // bCountryCode
  326. 1, // bNumDescriptors
  327. 0x22, // bDescriptorType
  328. sizeof(mouse_hid_report_desc), // wDescriptorLength
  329. 0,
  330. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  331. 7, // bLength
  332. 5, // bDescriptorType
  333. MOUSE_ENDPOINT | 0x80, // bEndpointAddress
  334. 0x03, // bmAttributes (0x03=intr)
  335. MOUSE_SIZE, 0, // wMaxPacketSize
  336. 1, // bInterval
  337. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  338. 9, // bLength
  339. 4, // bDescriptorType
  340. DEBUG_INTERFACE, // bInterfaceNumber
  341. 0, // bAlternateSetting
  342. 1, // bNumEndpoints
  343. 0x03, // bInterfaceClass (0x03 = HID)
  344. 0x00, // bInterfaceSubClass
  345. 0x00, // bInterfaceProtocol
  346. 0, // iInterface
  347. // HID descriptor, HID 1.11 spec, section 6.2.1
  348. 9, // bLength
  349. 0x21, // bDescriptorType
  350. 0x11, 0x01, // bcdHID
  351. 0, // bCountryCode
  352. 1, // bNumDescriptors
  353. 0x22, // bDescriptorType
  354. sizeof(debug_hid_report_desc), // wDescriptorLength
  355. 0,
  356. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  357. 7, // bLength
  358. 5, // bDescriptorType
  359. DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
  360. 0x03, // bmAttributes (0x03=intr)
  361. DEBUG_TX_SIZE, 0, // wMaxPacketSize
  362. 1, // bInterval
  363. // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
  364. 9, // bLength
  365. 4, // bDescriptorType
  366. EXTRA_INTERFACE, // bInterfaceNumber
  367. 0, // bAlternateSetting
  368. 1, // bNumEndpoints
  369. 0x03, // bInterfaceClass (0x03 = HID)
  370. 0x00, // bInterfaceSubClass
  371. 0x00, // bInterfaceProtocol
  372. 0, // iInterface
  373. // HID descriptor, HID 1.11 spec, section 6.2.1
  374. 9, // bLength
  375. 0x21, // bDescriptorType
  376. 0x11, 0x01, // bcdHID
  377. 0, // bCountryCode
  378. 1, // bNumDescriptors
  379. 0x22, // bDescriptorType
  380. sizeof(extra_hid_report_desc), // wDescriptorLength
  381. 0,
  382. // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
  383. 7, // bLength
  384. 5, // bDescriptorType
  385. EXTRA_ENDPOINT | 0x80, // bEndpointAddress
  386. 0x03, // bmAttributes (0x03=intr)
  387. EXTRA_SIZE, 0, // wMaxPacketSize
  388. 10, // bInterval
  389. };
  390. // If you're desperate for a little extra code memory, these strings
  391. // can be completely removed if iManufacturer, iProduct, iSerialNumber
  392. // in the device desciptor are changed to zeros.
  393. struct usb_string_descriptor_struct {
  394. uint8_t bLength;
  395. uint8_t bDescriptorType;
  396. int16_t wString[];
  397. };
  398. static struct usb_string_descriptor_struct PROGMEM string0 = {
  399. 4,
  400. 3,
  401. {0x0409}
  402. };
  403. static struct usb_string_descriptor_struct PROGMEM string1 = {
  404. sizeof(STR_MANUFACTURER),
  405. 3,
  406. STR_MANUFACTURER
  407. };
  408. static struct usb_string_descriptor_struct PROGMEM string2 = {
  409. sizeof(STR_PRODUCT),
  410. 3,
  411. STR_PRODUCT
  412. };
  413. // This table defines which descriptor data is sent for each specific
  414. // request from the host (in wValue and wIndex).
  415. static struct descriptor_list_struct {
  416. uint16_t wValue; // descriptor type
  417. uint16_t wIndex;
  418. const uint8_t *addr;
  419. uint8_t length;
  420. } PROGMEM descriptor_list[] = {
  421. // DEVICE descriptor
  422. {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
  423. // CONFIGURATION descriptor
  424. {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
  425. // HID REPORT
  426. {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
  427. {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
  428. // HID REPORT
  429. {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
  430. {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
  431. // HID REPORT
  432. {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
  433. {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
  434. // HID REPORT
  435. {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
  436. {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
  437. // STRING descriptor
  438. {0x0300, 0x0000, (const uint8_t *)&string0, 4},
  439. {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
  440. {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
  441. };
  442. #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
  443. /**************************************************************************
  444. *
  445. * Variables - these are the only non-stack RAM usage
  446. *
  447. **************************************************************************/
  448. // zero when we are not configured, non-zero when enumerated
  449. static volatile uint8_t usb_configuration=0;
  450. /**************************************************************************
  451. *
  452. * Public Functions - these are the API intended for the user
  453. *
  454. **************************************************************************/
  455. // initialize USB
  456. void usb_init(void)
  457. {
  458. HW_CONFIG();
  459. USB_FREEZE(); // enable USB
  460. PLL_CONFIG(); // config PLL
  461. while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
  462. USB_CONFIG(); // start USB clock
  463. UDCON = 0; // enable attach resistor
  464. usb_configuration = 0;
  465. UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE);
  466. sei();
  467. }
  468. // return 0 if the USB is not configured, or the configuration
  469. // number selected by the HOST
  470. uint8_t usb_configured(void)
  471. {
  472. return usb_configuration && !suspend;
  473. }
  474. void usb_remote_wakeup(void)
  475. {
  476. UDCON |= (1<<RMWKUP);
  477. }
  478. /**************************************************************************
  479. *
  480. * Private Functions - not intended for general user consumption....
  481. *
  482. **************************************************************************/
  483. // USB Device Interrupt - handle all device-level events
  484. // the transmit buffer flushing is triggered by the start of frame
  485. //
  486. ISR(USB_GEN_vect)
  487. {
  488. uint8_t intbits, t, i;
  489. static uint8_t div4=0;
  490. intbits = UDINT;
  491. UDINT = 0;
  492. if (intbits & (1<<SUSPI)) {
  493. suspend = true;
  494. } else {
  495. suspend = false;
  496. }
  497. if (intbits & (1<<EORSTI)) {
  498. UENUM = 0;
  499. UECONX = 1;
  500. UECFG0X = EP_TYPE_CONTROL;
  501. UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
  502. UEIENX = (1<<RXSTPE);
  503. usb_configuration = 0;
  504. }
  505. if ((intbits & (1<<SOFI)) && usb_configuration) {
  506. t = debug_flush_timer;
  507. if (t) {
  508. debug_flush_timer = -- t;
  509. if (!t) {
  510. UENUM = DEBUG_TX_ENDPOINT;
  511. while ((UEINTX & (1<<RWAL))) {
  512. UEDATX = 0;
  513. }
  514. UEINTX = 0x3A;
  515. }
  516. }
  517. if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
  518. UENUM = KEYBOARD_ENDPOINT;
  519. if (UEINTX & (1<<RWAL)) {
  520. usb_keyboard_idle_count++;
  521. if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
  522. usb_keyboard_idle_count = 0;
  523. UEDATX = usb_keyboard_mods;
  524. UEDATX = 0;
  525. for (i=0; i<6; i++) {
  526. UEDATX = usb_keyboard_keys[i];
  527. }
  528. UEINTX = 0x3A;
  529. }
  530. }
  531. }
  532. }
  533. }
  534. // Misc functions to wait for ready and send/receive packets
  535. static inline void usb_wait_in_ready(void)
  536. {
  537. while (!(UEINTX & (1<<TXINI))) ;
  538. }
  539. static inline void usb_send_in(void)
  540. {
  541. UEINTX = ~(1<<TXINI);
  542. }
  543. static inline void usb_wait_receive_out(void)
  544. {
  545. while (!(UEINTX & (1<<RXOUTI))) ;
  546. }
  547. static inline void usb_ack_out(void)
  548. {
  549. UEINTX = ~(1<<RXOUTI);
  550. }
  551. // USB Endpoint Interrupt - endpoint 0 is handled here. The
  552. // other endpoints are manipulated by the user-callable
  553. // functions, and the start-of-frame interrupt.
  554. //
  555. ISR(USB_COM_vect)
  556. {
  557. uint8_t intbits;
  558. const uint8_t *list;
  559. const uint8_t *cfg;
  560. uint8_t i, n, len, en;
  561. uint8_t bmRequestType;
  562. uint8_t bRequest;
  563. uint16_t wValue;
  564. uint16_t wIndex;
  565. uint16_t wLength;
  566. uint16_t desc_val;
  567. const uint8_t *desc_addr;
  568. uint8_t desc_length;
  569. UENUM = 0;
  570. intbits = UEINTX;
  571. if (intbits & (1<<RXSTPI)) {
  572. bmRequestType = UEDATX;
  573. bRequest = UEDATX;
  574. wValue = UEDATX;
  575. wValue |= (UEDATX << 8);
  576. wIndex = UEDATX;
  577. wIndex |= (UEDATX << 8);
  578. wLength = UEDATX;
  579. wLength |= (UEDATX << 8);
  580. UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
  581. if (bRequest == GET_DESCRIPTOR) {
  582. list = (const uint8_t *)descriptor_list;
  583. for (i=0; ; i++) {
  584. if (i >= NUM_DESC_LIST) {
  585. UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
  586. return;
  587. }
  588. desc_val = pgm_read_word(list);
  589. if (desc_val != wValue) {
  590. list += sizeof(struct descriptor_list_struct);
  591. continue;
  592. }
  593. list += 2;
  594. desc_val = pgm_read_word(list);
  595. if (desc_val != wIndex) {
  596. list += sizeof(struct descriptor_list_struct)-2;
  597. continue;
  598. }
  599. list += 2;
  600. desc_addr = (const uint8_t *)pgm_read_word(list);
  601. list += 2;
  602. desc_length = pgm_read_byte(list);
  603. break;
  604. }
  605. len = (wLength < 256) ? wLength : 255;
  606. if (len > desc_length) len = desc_length;
  607. do {
  608. // wait for host ready for IN packet
  609. do {
  610. i = UEINTX;
  611. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  612. if (i & (1<<RXOUTI)) return; // abort
  613. // send IN packet
  614. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  615. for (i = n; i; i--) {
  616. UEDATX = pgm_read_byte(desc_addr++);
  617. }
  618. len -= n;
  619. usb_send_in();
  620. } while (len || n == ENDPOINT0_SIZE);
  621. return;
  622. }
  623. if (bRequest == SET_ADDRESS) {
  624. usb_send_in();
  625. usb_wait_in_ready();
  626. UDADDR = wValue | (1<<ADDEN);
  627. return;
  628. }
  629. if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
  630. usb_configuration = wValue;
  631. usb_send_in();
  632. cfg = endpoint_config_table;
  633. for (i=1; i<=6; i++) {
  634. UENUM = i;
  635. en = pgm_read_byte(cfg++);
  636. UECONX = en;
  637. if (en) {
  638. UECFG0X = pgm_read_byte(cfg++);
  639. UECFG1X = pgm_read_byte(cfg++);
  640. }
  641. }
  642. UERST = 0x7E;
  643. UERST = 0;
  644. return;
  645. }
  646. if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
  647. usb_wait_in_ready();
  648. UEDATX = usb_configuration;
  649. usb_send_in();
  650. return;
  651. }
  652. if (bRequest == GET_STATUS) {
  653. usb_wait_in_ready();
  654. i = 0;
  655. #ifdef SUPPORT_ENDPOINT_HALT
  656. if (bmRequestType == 0x82) {
  657. UENUM = wIndex;
  658. if (UECONX & (1<<STALLRQ)) i = 1;
  659. UENUM = 0;
  660. }
  661. #endif
  662. UEDATX = i;
  663. UEDATX = 0;
  664. usb_send_in();
  665. return;
  666. }
  667. if (bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) {
  668. #ifdef SUPPORT_ENDPOINT_HALT
  669. if (bmRequestType == 0x02 && wValue == ENDPOINT_HALT) {
  670. i = wIndex & 0x7F;
  671. if (i >= 1 && i <= MAX_ENDPOINT) {
  672. usb_send_in();
  673. UENUM = i;
  674. if (bRequest == SET_FEATURE) {
  675. UECONX = (1<<STALLRQ)|(1<<EPEN);
  676. } else {
  677. UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
  678. UERST = (1 << i);
  679. UERST = 0;
  680. }
  681. return;
  682. }
  683. }
  684. #endif
  685. if (bmRequestType == 0x00 && wValue == DEVICE_REMOTE_WAKEUP) {
  686. if (bRequest == SET_FEATURE) {
  687. remote_wakeup = true;
  688. } else {
  689. remote_wakeup = false;
  690. }
  691. usb_send_in();
  692. return;
  693. }
  694. }
  695. if (wIndex == KEYBOARD_INTERFACE) {
  696. if (bmRequestType == 0xA1) {
  697. if (bRequest == HID_GET_REPORT) {
  698. usb_wait_in_ready();
  699. UEDATX = usb_keyboard_mods;
  700. UEDATX = 0;
  701. for (i=0; i<6; i++) {
  702. UEDATX = usb_keyboard_keys[i];
  703. }
  704. usb_send_in();
  705. return;
  706. }
  707. if (bRequest == HID_GET_IDLE) {
  708. usb_wait_in_ready();
  709. UEDATX = usb_keyboard_idle_config;
  710. usb_send_in();
  711. return;
  712. }
  713. if (bRequest == HID_GET_PROTOCOL) {
  714. usb_wait_in_ready();
  715. UEDATX = usb_keyboard_protocol;
  716. usb_send_in();
  717. return;
  718. }
  719. }
  720. if (bmRequestType == 0x21) {
  721. if (bRequest == HID_SET_REPORT) {
  722. usb_wait_receive_out();
  723. usb_keyboard_leds = UEDATX;
  724. usb_ack_out();
  725. usb_send_in();
  726. return;
  727. }
  728. if (bRequest == HID_SET_IDLE) {
  729. usb_keyboard_idle_config = (wValue >> 8);
  730. usb_keyboard_idle_count = 0;
  731. //usb_wait_in_ready();
  732. usb_send_in();
  733. return;
  734. }
  735. if (bRequest == HID_SET_PROTOCOL) {
  736. usb_keyboard_protocol = wValue;
  737. //usb_wait_in_ready();
  738. usb_send_in();
  739. return;
  740. }
  741. }
  742. }
  743. if (wIndex == MOUSE_INTERFACE) {
  744. if (bmRequestType == 0xA1) {
  745. if (bRequest == HID_GET_REPORT) {
  746. if (wValue == HID_REPORT_INPUT) {
  747. usb_wait_in_ready();
  748. UEDATX = mouse_buttons;
  749. UEDATX = 0;
  750. UEDATX = 0;
  751. UEDATX = 0;
  752. usb_send_in();
  753. return;
  754. }
  755. if (wValue == HID_REPORT_FEATURE) {
  756. usb_wait_in_ready();
  757. UEDATX = 0x05;
  758. usb_send_in();
  759. return;
  760. }
  761. }
  762. if (bRequest == HID_GET_PROTOCOL) {
  763. usb_wait_in_ready();
  764. UEDATX = mouse_protocol;
  765. usb_send_in();
  766. return;
  767. }
  768. }
  769. if (bmRequestType == 0x21) {
  770. if (bRequest == HID_SET_PROTOCOL) {
  771. mouse_protocol = wValue;
  772. usb_send_in();
  773. return;
  774. }
  775. }
  776. }
  777. if (wIndex == DEBUG_INTERFACE) {
  778. if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
  779. len = wLength;
  780. do {
  781. // wait for host ready for IN packet
  782. do {
  783. i = UEINTX;
  784. } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
  785. if (i & (1<<RXOUTI)) return; // abort
  786. // send IN packet
  787. n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
  788. for (i = n; i; i--) {
  789. UEDATX = 0;
  790. }
  791. len -= n;
  792. usb_send_in();
  793. } while (len || n == ENDPOINT0_SIZE);
  794. return;
  795. }
  796. }
  797. }
  798. UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
  799. }