Keyboard firmwares for Atmel AVR and Cortex-M
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.

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