Keyboard firmwares for Atmel AVR and Cortex-M
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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