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.

usb_main.c 50KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385
  1. /*
  2. * (c) 2015 flabberast <[email protected]>
  3. *
  4. * Based on the following work:
  5. * - Guillaume Duc's raw hid example (MIT License)
  6. * https://github.com/guiduc/usb-hid-chibios-example
  7. * - PJRC Teensy examples (MIT License)
  8. * https://www.pjrc.com/teensy/usb_keyboard.html
  9. * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
  10. * https://github.com/tmk/tmk_keyboard/
  11. * - ChibiOS demo code (Apache 2.0 License)
  12. * http://www.chibios.org
  13. *
  14. * Since some GPL'd code is used, this work is licensed under
  15. * GPL v2 or later.
  16. */
  17. #include "ch.h"
  18. #include "hal.h"
  19. #include "usb_main.h"
  20. #include "host.h"
  21. #include "debug.h"
  22. #include "suspend.h"
  23. #ifdef SLEEP_LED_ENABLE
  24. #include "sleep_led.h"
  25. #include "led.h"
  26. #endif
  27. #include "hook.h"
  28. /* TMK hooks */
  29. __attribute__((weak))
  30. void hook_usb_wakeup(void) {
  31. #ifdef SLEEP_LED_ENABLE
  32. sleep_led_disable();
  33. // NOTE: converters may not accept this
  34. led_set(host_keyboard_leds());
  35. #endif /* SLEEP_LED_ENABLE */
  36. }
  37. __attribute__((weak))
  38. void hook_usb_suspend_entry(void) {
  39. #ifdef SLEEP_LED_ENABLE
  40. sleep_led_enable();
  41. #endif /* SLEEP_LED_ENABLE */
  42. }
  43. /* ---------------------------------------------------------
  44. * Global interface variables and declarations
  45. * ---------------------------------------------------------
  46. */
  47. uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
  48. uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
  49. uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
  50. volatile uint16_t keyboard_idle_count = 0;
  51. static virtual_timer_t keyboard_idle_timer;
  52. static void keyboard_idle_timer_cb(void *arg);
  53. #ifdef NKRO_ENABLE
  54. extern bool keyboard_nkro;
  55. #endif /* NKRO_ENABLE */
  56. report_keyboard_t keyboard_report_sent = {{0}};
  57. #ifdef MOUSE_ENABLE
  58. report_mouse_t mouse_report_blank = {0};
  59. #endif /* MOUSE_ENABLE */
  60. #ifdef EXTRAKEY_ENABLE
  61. uint8_t extra_report_blank[3] = {0};
  62. #endif /* EXTRAKEY_ENABLE */
  63. #ifdef CONSOLE_ENABLE
  64. /* The emission buffers queue */
  65. output_buffers_queue_t console_buf_queue;
  66. static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)];
  67. static virtual_timer_t console_flush_timer;
  68. void console_queue_onotify(io_buffers_queue_t *bqp);
  69. static void console_flush_cb(void *arg);
  70. #endif /* CONSOLE_ENABLE */
  71. /* ---------------------------------------------------------
  72. * Descriptors and USB driver objects
  73. * ---------------------------------------------------------
  74. */
  75. /* HID specific constants */
  76. #define USB_DESCRIPTOR_HID 0x21
  77. #define USB_DESCRIPTOR_HID_REPORT 0x22
  78. #define HID_GET_REPORT 0x01
  79. #define HID_GET_IDLE 0x02
  80. #define HID_GET_PROTOCOL 0x03
  81. #define HID_SET_REPORT 0x09
  82. #define HID_SET_IDLE 0x0A
  83. #define HID_SET_PROTOCOL 0x0B
  84. /* USB Device Descriptor */
  85. static const uint8_t usb_device_descriptor_data[] = {
  86. USB_DESC_DEVICE(0x0200, // bcdUSB (1.1)
  87. 0, // bDeviceClass (defined in later in interface)
  88. 0, // bDeviceSubClass
  89. 0, // bDeviceProtocol
  90. 64, // bMaxPacketSize (64 bytes) (the driver didn't work with 32)
  91. VENDOR_ID, // idVendor
  92. PRODUCT_ID, // idProduct
  93. DEVICE_VER, // bcdDevice
  94. 1, // iManufacturer
  95. 2, // iProduct
  96. 3, // iSerialNumber
  97. 1) // bNumConfigurations
  98. };
  99. /* Device Descriptor wrapper */
  100. static const USBDescriptor usb_device_descriptor = {
  101. sizeof usb_device_descriptor_data,
  102. usb_device_descriptor_data
  103. };
  104. /*
  105. * HID Report Descriptor
  106. *
  107. * See "Device Class Definition for Human Interface Devices (HID)"
  108. * (http://www.usb.org/developers/hidpage/HID1_11.pdf) for the
  109. * detailed descrition of all the fields
  110. */
  111. /* Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 */
  112. static const uint8_t keyboard_hid_report_desc_data[] = {
  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, KBD_REPORT_KEYS, // Report Count (),
  137. 0x75, 0x08, // Report Size (8),
  138. 0x15, 0x00, // Logical Minimum (0),
  139. 0x26, 0xFF, 0x00, // Logical Maximum(255),
  140. 0x05, 0x07, // Usage Page (Key Codes),
  141. 0x19, 0x00, // Usage Minimum (0),
  142. 0x29, 0xFF, // Usage Maximum (255),
  143. 0x81, 0x00, // Input (Data, Array),
  144. 0xc0 // End Collection
  145. };
  146. /* wrapper */
  147. static const USBDescriptor keyboard_hid_report_descriptor = {
  148. sizeof keyboard_hid_report_desc_data,
  149. keyboard_hid_report_desc_data
  150. };
  151. #ifdef NKRO_ENABLE
  152. static const uint8_t nkro_hid_report_desc_data[] = {
  153. 0x05, 0x01, // Usage Page (Generic Desktop),
  154. 0x09, 0x06, // Usage (Keyboard),
  155. 0xA1, 0x01, // Collection (Application),
  156. // bitmap of modifiers
  157. 0x75, 0x01, // Report Size (1),
  158. 0x95, 0x08, // Report Count (8),
  159. 0x05, 0x07, // Usage Page (Key Codes),
  160. 0x19, 0xE0, // Usage Minimum (224),
  161. 0x29, 0xE7, // Usage Maximum (231),
  162. 0x15, 0x00, // Logical Minimum (0),
  163. 0x25, 0x01, // Logical Maximum (1),
  164. 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
  165. // LED output report
  166. 0x95, 0x05, // Report Count (5),
  167. 0x75, 0x01, // Report Size (1),
  168. 0x05, 0x08, // Usage Page (LEDs),
  169. 0x19, 0x01, // Usage Minimum (1),
  170. 0x29, 0x05, // Usage Maximum (5),
  171. 0x91, 0x02, // Output (Data, Variable, Absolute),
  172. 0x95, 0x01, // Report Count (1),
  173. 0x75, 0x03, // Report Size (3),
  174. 0x91, 0x03, // Output (Constant),
  175. // bitmap of keys
  176. 0x95, NKRO_REPORT_KEYS * 8, // Report Count (),
  177. 0x75, 0x01, // Report Size (1),
  178. 0x15, 0x00, // Logical Minimum (0),
  179. 0x25, 0x01, // Logical Maximum(1),
  180. 0x05, 0x07, // Usage Page (Key Codes),
  181. 0x19, 0x00, // Usage Minimum (0),
  182. 0x29, NKRO_REPORT_KEYS * 8 - 1, // Usage Maximum (),
  183. 0x81, 0x02, // Input (Data, Variable, Absolute),
  184. 0xc0 // End Collection
  185. };
  186. /* wrapper */
  187. static const USBDescriptor nkro_hid_report_descriptor = {
  188. sizeof nkro_hid_report_desc_data,
  189. nkro_hid_report_desc_data
  190. };
  191. #endif /* NKRO_ENABLE */
  192. #ifdef MOUSE_ENABLE
  193. /* Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
  194. * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
  195. * http://www.keil.com/forum/15671/
  196. * http://www.microsoft.com/whdc/device/input/wheel.mspx */
  197. static const uint8_t mouse_hid_report_desc_data[] = {
  198. /* mouse */
  199. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  200. 0x09, 0x02, // USAGE (Mouse)
  201. 0xa1, 0x01, // COLLECTION (Application)
  202. //0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
  203. 0x09, 0x01, // USAGE (Pointer)
  204. 0xa1, 0x00, // COLLECTION (Physical)
  205. // ---------------------------- Buttons
  206. 0x05, 0x09, // USAGE_PAGE (Button)
  207. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  208. 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
  209. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  210. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  211. 0x75, 0x01, // REPORT_SIZE (1)
  212. 0x95, 0x05, // REPORT_COUNT (5)
  213. 0x81, 0x02, // INPUT (Data,Var,Abs)
  214. 0x75, 0x03, // REPORT_SIZE (3)
  215. 0x95, 0x01, // REPORT_COUNT (1)
  216. 0x81, 0x03, // INPUT (Cnst,Var,Abs)
  217. // ---------------------------- X,Y position
  218. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  219. 0x09, 0x30, // USAGE (X)
  220. 0x09, 0x31, // USAGE (Y)
  221. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  222. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  223. 0x75, 0x08, // REPORT_SIZE (8)
  224. 0x95, 0x02, // REPORT_COUNT (2)
  225. 0x81, 0x06, // INPUT (Data,Var,Rel)
  226. // ---------------------------- Vertical wheel
  227. 0x09, 0x38, // USAGE (Wheel)
  228. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  229. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  230. 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
  231. 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
  232. 0x75, 0x08, // REPORT_SIZE (8)
  233. 0x95, 0x01, // REPORT_COUNT (1)
  234. 0x81, 0x06, // INPUT (Data,Var,Rel)
  235. // ---------------------------- Horizontal wheel
  236. 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
  237. 0x0a, 0x38, 0x02, // USAGE (AC Pan)
  238. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  239. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  240. 0x75, 0x08, // REPORT_SIZE (8)
  241. 0x95, 0x01, // REPORT_COUNT (1)
  242. 0x81, 0x06, // INPUT (Data,Var,Rel)
  243. 0xc0, // END_COLLECTION
  244. 0xc0, // END_COLLECTION
  245. };
  246. /* wrapper */
  247. static const USBDescriptor mouse_hid_report_descriptor = {
  248. sizeof mouse_hid_report_desc_data,
  249. mouse_hid_report_desc_data
  250. };
  251. #endif /* MOUSE_ENABLE */
  252. #ifdef CONSOLE_ENABLE
  253. static const uint8_t console_hid_report_desc_data[] = {
  254. 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
  255. 0x09, 0x74, // Usage 0x74
  256. 0xA1, 0x53, // Collection 0x53
  257. 0x75, 0x08, // report size = 8 bits
  258. 0x15, 0x00, // logical minimum = 0
  259. 0x26, 0xFF, 0x00, // logical maximum = 255
  260. 0x95, CONSOLE_EPSIZE, // report count
  261. 0x09, 0x75, // usage
  262. 0x81, 0x02, // Input (array)
  263. 0xC0 // end collection
  264. };
  265. /* wrapper */
  266. static const USBDescriptor console_hid_report_descriptor = {
  267. sizeof console_hid_report_desc_data,
  268. console_hid_report_desc_data
  269. };
  270. #endif /* CONSOLE_ENABLE */
  271. #ifdef EXTRAKEY_ENABLE
  272. /* audio controls & system controls
  273. * http://www.microsoft.com/whdc/archive/w2kbd.mspx */
  274. static const uint8_t extra_hid_report_desc_data[] = {
  275. /* system control */
  276. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  277. 0x09, 0x80, // USAGE (System Control)
  278. 0xa1, 0x01, // COLLECTION (Application)
  279. 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
  280. 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
  281. 0x26, 0xb7, 0x00, // LOGICAL_MAXIMUM (0xb7)
  282. 0x19, 0x01, // USAGE_MINIMUM (0x1)
  283. 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
  284. 0x75, 0x10, // REPORT_SIZE (16)
  285. 0x95, 0x01, // REPORT_COUNT (1)
  286. 0x81, 0x00, // INPUT (Data,Array,Abs)
  287. 0xc0, // END_COLLECTION
  288. /* consumer */
  289. 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
  290. 0x09, 0x01, // USAGE (Consumer Control)
  291. 0xa1, 0x01, // COLLECTION (Application)
  292. 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
  293. 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
  294. 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
  295. 0x19, 0x01, // USAGE_MINIMUM (0x1)
  296. 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
  297. 0x75, 0x10, // REPORT_SIZE (16)
  298. 0x95, 0x01, // REPORT_COUNT (1)
  299. 0x81, 0x00, // INPUT (Data,Array,Abs)
  300. 0xc0, // END_COLLECTION
  301. };
  302. /* wrapper */
  303. static const USBDescriptor extra_hid_report_descriptor = {
  304. sizeof extra_hid_report_desc_data,
  305. extra_hid_report_desc_data
  306. };
  307. #endif /* EXTRAKEY_ENABLE */
  308. /*
  309. * Configuration Descriptor tree for a HID device
  310. *
  311. * The HID Specifications version 1.11 require the following order:
  312. * - Configuration Descriptor
  313. * - Interface Descriptor
  314. * - HID Descriptor
  315. * - Endpoints Descriptors
  316. */
  317. #define KBD_HID_DESC_NUM 0
  318. #define KBD_HID_DESC_OFFSET (9 + (9 + 9 + 7) * KBD_HID_DESC_NUM + 9)
  319. #ifdef MOUSE_ENABLE
  320. # define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1)
  321. # define MOUSE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * MOUSE_HID_DESC_NUM + 9)
  322. #else /* MOUSE_ENABLE */
  323. # define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0)
  324. #endif /* MOUSE_ENABLE */
  325. #ifdef CONSOLE_ENABLE
  326. #define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1)
  327. #define CONSOLE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * CONSOLE_HID_DESC_NUM + 9)
  328. #else /* CONSOLE_ENABLE */
  329. # define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0)
  330. #endif /* CONSOLE_ENABLE */
  331. #ifdef EXTRAKEY_ENABLE
  332. # define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 1)
  333. # define EXTRA_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
  334. #else /* EXTRAKEY_ENABLE */
  335. # define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 0)
  336. #endif /* EXTRAKEY_ENABLE */
  337. #ifdef NKRO_ENABLE
  338. # define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1)
  339. # define NKRO_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
  340. #else /* NKRO_ENABLE */
  341. # define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0)
  342. #endif /* NKRO_ENABLE */
  343. #define NUM_INTERFACES (NKRO_HID_DESC_NUM + 1)
  344. #define CONFIG1_DESC_SIZE (9 + (9 + 9 + 7) * NUM_INTERFACES)
  345. static const uint8_t hid_configuration_descriptor_data[] = {
  346. /* Configuration Descriptor (9 bytes) USB spec 9.6.3, page 264-266, Table 9-10 */
  347. USB_DESC_CONFIGURATION(CONFIG1_DESC_SIZE, // wTotalLength
  348. NUM_INTERFACES, // bNumInterfaces
  349. 1, // bConfigurationValue
  350. 0, // iConfiguration
  351. 0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP)
  352. 50), // bMaxPower (50mA)
  353. /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
  354. USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber
  355. 0, // bAlternateSetting
  356. 1, // bNumEndpoints
  357. 0x03, // bInterfaceClass: HID
  358. 0x01, // bInterfaceSubClass: Boot
  359. 0x01, // bInterfaceProtocol: Keyboard
  360. 0), // iInterface
  361. /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
  362. USB_DESC_BYTE(9), // bLength
  363. USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
  364. USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
  365. USB_DESC_BYTE(0), // bCountryCode
  366. USB_DESC_BYTE(1), // bNumDescriptors
  367. USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
  368. USB_DESC_WORD(sizeof(keyboard_hid_report_desc_data)), // wDescriptorLength
  369. /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
  370. USB_DESC_ENDPOINT(KBD_ENDPOINT | 0x80, // bEndpointAddress
  371. 0x03, // bmAttributes (Interrupt)
  372. KBD_EPSIZE,// wMaxPacketSize
  373. 10), // bInterval
  374. #ifdef MOUSE_ENABLE
  375. /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
  376. USB_DESC_INTERFACE(MOUSE_INTERFACE, // bInterfaceNumber
  377. 0, // bAlternateSetting
  378. 1, // bNumEndpoints
  379. 0x03, // bInterfaceClass (0x03 = HID)
  380. // ThinkPad T23 BIOS doesn't work with boot mouse.
  381. 0x00, // bInterfaceSubClass (0x01 = Boot)
  382. 0x00, // bInterfaceProtocol (0x02 = Mouse)
  383. /*
  384. 0x01, // bInterfaceSubClass (0x01 = Boot)
  385. 0x02, // bInterfaceProtocol (0x02 = Mouse)
  386. */
  387. 0), // iInterface
  388. /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
  389. USB_DESC_BYTE(9), // bLength
  390. USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
  391. USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
  392. USB_DESC_BYTE(0), // bCountryCode
  393. USB_DESC_BYTE(1), // bNumDescriptors
  394. USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
  395. USB_DESC_WORD(sizeof(mouse_hid_report_desc_data)), // wDescriptorLength
  396. /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
  397. USB_DESC_ENDPOINT(MOUSE_ENDPOINT | 0x80, // bEndpointAddress
  398. 0x03, // bmAttributes (Interrupt)
  399. MOUSE_EPSIZE, // wMaxPacketSize
  400. 1), // bInterval
  401. #endif /* MOUSE_ENABLE */
  402. #ifdef CONSOLE_ENABLE
  403. /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
  404. USB_DESC_INTERFACE(CONSOLE_INTERFACE, // bInterfaceNumber
  405. 0, // bAlternateSetting
  406. 1, // bNumEndpoints
  407. 0x03, // bInterfaceClass: HID
  408. 0x00, // bInterfaceSubClass: None
  409. 0x00, // bInterfaceProtocol: None
  410. 0), // iInterface
  411. /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
  412. USB_DESC_BYTE(9), // bLength
  413. USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
  414. USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
  415. USB_DESC_BYTE(0), // bCountryCode
  416. USB_DESC_BYTE(1), // bNumDescriptors
  417. USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
  418. USB_DESC_WORD(sizeof(console_hid_report_desc_data)), // wDescriptorLength
  419. /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
  420. USB_DESC_ENDPOINT(CONSOLE_ENDPOINT | 0x80, // bEndpointAddress
  421. 0x03, // bmAttributes (Interrupt)
  422. CONSOLE_EPSIZE, // wMaxPacketSize
  423. 1), // bInterval
  424. #endif /* CONSOLE_ENABLE */
  425. #ifdef EXTRAKEY_ENABLE
  426. /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
  427. USB_DESC_INTERFACE(EXTRA_INTERFACE, // bInterfaceNumber
  428. 0, // bAlternateSetting
  429. 1, // bNumEndpoints
  430. 0x03, // bInterfaceClass: HID
  431. 0x00, // bInterfaceSubClass: None
  432. 0x00, // bInterfaceProtocol: None
  433. 0), // iInterface
  434. /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
  435. USB_DESC_BYTE(9), // bLength
  436. USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
  437. USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
  438. USB_DESC_BYTE(0), // bCountryCode
  439. USB_DESC_BYTE(1), // bNumDescriptors
  440. USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
  441. USB_DESC_WORD(sizeof(extra_hid_report_desc_data)), // wDescriptorLength
  442. /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
  443. USB_DESC_ENDPOINT(EXTRA_ENDPOINT | 0x80, // bEndpointAddress
  444. 0x03, // bmAttributes (Interrupt)
  445. EXTRA_EPSIZE, // wMaxPacketSize
  446. 10), // bInterval
  447. #endif /* EXTRAKEY_ENABLE */
  448. #ifdef NKRO_ENABLE
  449. /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
  450. USB_DESC_INTERFACE(NKRO_INTERFACE, // bInterfaceNumber
  451. 0, // bAlternateSetting
  452. 1, // bNumEndpoints
  453. 0x03, // bInterfaceClass: HID
  454. 0x00, // bInterfaceSubClass: None
  455. 0x00, // bInterfaceProtocol: None
  456. 0), // iInterface
  457. /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
  458. USB_DESC_BYTE(9), // bLength
  459. USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
  460. USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
  461. USB_DESC_BYTE(0), // bCountryCode
  462. USB_DESC_BYTE(1), // bNumDescriptors
  463. USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
  464. USB_DESC_WORD(sizeof(nkro_hid_report_desc_data)), // wDescriptorLength
  465. /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
  466. USB_DESC_ENDPOINT(NKRO_ENDPOINT | 0x80, // bEndpointAddress
  467. 0x03, // bmAttributes (Interrupt)
  468. NKRO_EPSIZE, // wMaxPacketSize
  469. 1), // bInterval
  470. #endif /* NKRO_ENABLE */
  471. };
  472. /* Configuration Descriptor wrapper */
  473. static const USBDescriptor hid_configuration_descriptor = {
  474. sizeof hid_configuration_descriptor_data,
  475. hid_configuration_descriptor_data
  476. };
  477. /* wrappers */
  478. #define HID_DESCRIPTOR_SIZE 9
  479. static const USBDescriptor keyboard_hid_descriptor = {
  480. HID_DESCRIPTOR_SIZE,
  481. &hid_configuration_descriptor_data[KBD_HID_DESC_OFFSET]
  482. };
  483. #ifdef MOUSE_ENABLE
  484. static const USBDescriptor mouse_hid_descriptor = {
  485. HID_DESCRIPTOR_SIZE,
  486. &hid_configuration_descriptor_data[MOUSE_HID_DESC_OFFSET]
  487. };
  488. #endif /* MOUSE_ENABLE */
  489. #ifdef CONSOLE_ENABLE
  490. static const USBDescriptor console_hid_descriptor = {
  491. HID_DESCRIPTOR_SIZE,
  492. &hid_configuration_descriptor_data[CONSOLE_HID_DESC_OFFSET]
  493. };
  494. #endif /* CONSOLE_ENABLE */
  495. #ifdef EXTRAKEY_ENABLE
  496. static const USBDescriptor extra_hid_descriptor = {
  497. HID_DESCRIPTOR_SIZE,
  498. &hid_configuration_descriptor_data[EXTRA_HID_DESC_OFFSET]
  499. };
  500. #endif /* EXTRAKEY_ENABLE */
  501. #ifdef NKRO_ENABLE
  502. static const USBDescriptor nkro_hid_descriptor = {
  503. HID_DESCRIPTOR_SIZE,
  504. &hid_configuration_descriptor_data[NKRO_HID_DESC_OFFSET]
  505. };
  506. #endif /* NKRO_ENABLE */
  507. /* U.S. English language identifier */
  508. static const uint8_t usb_string_langid[] = {
  509. USB_DESC_BYTE(4), // bLength
  510. USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
  511. USB_DESC_WORD(0x0409) // wLANGID (U.S. English)
  512. };
  513. /* ugly ugly hack */
  514. #define PP_NARG(...) \
  515. PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
  516. #define PP_NARG_(...) \
  517. PP_ARG_N(__VA_ARGS__)
  518. #define PP_ARG_N( \
  519. _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
  520. _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
  521. _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
  522. _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
  523. _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
  524. _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
  525. _61,_62,_63,N,...) N
  526. #define PP_RSEQ_N() \
  527. 63,62,61,60, \
  528. 59,58,57,56,55,54,53,52,51,50, \
  529. 49,48,47,46,45,44,43,42,41,40, \
  530. 39,38,37,36,35,34,33,32,31,30, \
  531. 29,28,27,26,25,24,23,22,21,20, \
  532. 19,18,17,16,15,14,13,12,11,10, \
  533. 9,8,7,6,5,4,3,2,1,0
  534. /* Vendor string = manufacturer */
  535. static const uint8_t usb_string_vendor[] = {
  536. USB_DESC_BYTE(PP_NARG(USBSTR_MANUFACTURER)+2), // bLength
  537. USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
  538. USBSTR_MANUFACTURER
  539. };
  540. /* Device Description string = product */
  541. static const uint8_t usb_string_description[] = {
  542. USB_DESC_BYTE(PP_NARG(USBSTR_PRODUCT)+2), // bLength
  543. USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
  544. USBSTR_PRODUCT
  545. };
  546. /* Serial Number string (will be filled by the function init_usb_serial_string) */
  547. static uint8_t usb_string_serial[] = {
  548. USB_DESC_BYTE(22), // bLength
  549. USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
  550. '0', 0, 'x', 0, 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'B', 0, 'E', 0, 'E', 0, 'F', 0
  551. };
  552. /* Strings wrappers array */
  553. static const USBDescriptor usb_strings[] = {
  554. { sizeof usb_string_langid, usb_string_langid }
  555. ,
  556. { sizeof usb_string_vendor, usb_string_vendor }
  557. ,
  558. { sizeof usb_string_description, usb_string_description }
  559. ,
  560. { sizeof usb_string_serial, usb_string_serial }
  561. };
  562. /*
  563. * Handles the GET_DESCRIPTOR callback
  564. *
  565. * Returns the proper descriptor
  566. */
  567. static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) {
  568. (void)usbp;
  569. (void)lang;
  570. switch(dtype) {
  571. /* Generic descriptors */
  572. case USB_DESCRIPTOR_DEVICE: /* Device Descriptor */
  573. return &usb_device_descriptor;
  574. case USB_DESCRIPTOR_CONFIGURATION: /* Configuration Descriptor */
  575. return &hid_configuration_descriptor;
  576. case USB_DESCRIPTOR_STRING: /* Strings */
  577. if(dindex < 4)
  578. return &usb_strings[dindex];
  579. break;
  580. /* HID specific descriptors */
  581. case USB_DESCRIPTOR_HID: /* HID Descriptors */
  582. switch(lang) { /* yea, poor label, it's actually wIndex from the setup packet */
  583. case KBD_INTERFACE:
  584. return &keyboard_hid_descriptor;
  585. #ifdef MOUSE_ENABLE
  586. case MOUSE_INTERFACE:
  587. return &mouse_hid_descriptor;
  588. #endif /* MOUSE_ENABLE */
  589. #ifdef CONSOLE_ENABLE
  590. case CONSOLE_INTERFACE:
  591. return &console_hid_descriptor;
  592. #endif /* CONSOLE_ENABLE */
  593. #ifdef EXTRAKEY_ENABLE
  594. case EXTRA_INTERFACE:
  595. return &extra_hid_descriptor;
  596. #endif /* EXTRAKEY_ENABLE */
  597. #ifdef NKRO_ENABLE
  598. case NKRO_INTERFACE:
  599. return &nkro_hid_descriptor;
  600. #endif /* NKRO_ENABLE */
  601. }
  602. case USB_DESCRIPTOR_HID_REPORT: /* HID Report Descriptor */
  603. switch(lang) {
  604. case KBD_INTERFACE:
  605. return &keyboard_hid_report_descriptor;
  606. #ifdef MOUSE_ENABLE
  607. case MOUSE_INTERFACE:
  608. return &mouse_hid_report_descriptor;
  609. #endif /* MOUSE_ENABLE */
  610. #ifdef CONSOLE_ENABLE
  611. case CONSOLE_INTERFACE:
  612. return &console_hid_report_descriptor;
  613. #endif /* CONSOLE_ENABLE */
  614. #ifdef EXTRAKEY_ENABLE
  615. case EXTRA_INTERFACE:
  616. return &extra_hid_report_descriptor;
  617. #endif /* EXTRAKEY_ENABLE */
  618. #ifdef NKRO_ENABLE
  619. case NKRO_INTERFACE:
  620. return &nkro_hid_report_descriptor;
  621. #endif /* NKRO_ENABLE */
  622. }
  623. }
  624. return NULL;
  625. }
  626. /* keyboard endpoint state structure */
  627. static USBInEndpointState kbd_ep_state;
  628. /* keyboard endpoint initialization structure (IN) */
  629. static const USBEndpointConfig kbd_ep_config = {
  630. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  631. NULL, /* SETUP packet notification callback */
  632. kbd_in_cb, /* IN notification callback */
  633. NULL, /* OUT notification callback */
  634. KBD_EPSIZE, /* IN maximum packet size */
  635. 0, /* OUT maximum packet size */
  636. &kbd_ep_state, /* IN Endpoint state */
  637. NULL, /* OUT endpoint state */
  638. 2, /* IN multiplier */
  639. NULL /* SETUP buffer (not a SETUP endpoint) */
  640. };
  641. #ifdef MOUSE_ENABLE
  642. /* mouse endpoint state structure */
  643. static USBInEndpointState mouse_ep_state;
  644. /* mouse endpoint initialization structure (IN) */
  645. static const USBEndpointConfig mouse_ep_config = {
  646. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  647. NULL, /* SETUP packet notification callback */
  648. mouse_in_cb, /* IN notification callback */
  649. NULL, /* OUT notification callback */
  650. MOUSE_EPSIZE, /* IN maximum packet size */
  651. 0, /* OUT maximum packet size */
  652. &mouse_ep_state, /* IN Endpoint state */
  653. NULL, /* OUT endpoint state */
  654. 2, /* IN multiplier */
  655. NULL /* SETUP buffer (not a SETUP endpoint) */
  656. };
  657. #endif /* MOUSE_ENABLE */
  658. #ifdef CONSOLE_ENABLE
  659. /* console endpoint state structure */
  660. static USBInEndpointState console_ep_state;
  661. /* console endpoint initialization structure (IN) */
  662. static const USBEndpointConfig console_ep_config = {
  663. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  664. NULL, /* SETUP packet notification callback */
  665. console_in_cb, /* IN notification callback */
  666. NULL, /* OUT notification callback */
  667. CONSOLE_EPSIZE, /* IN maximum packet size */
  668. 0, /* OUT maximum packet size */
  669. &console_ep_state, /* IN Endpoint state */
  670. NULL, /* OUT endpoint state */
  671. 2, /* IN multiplier */
  672. NULL /* SETUP buffer (not a SETUP endpoint) */
  673. };
  674. #endif /* CONSOLE_ENABLE */
  675. #ifdef EXTRAKEY_ENABLE
  676. /* extrakey endpoint state structure */
  677. static USBInEndpointState extra_ep_state;
  678. /* extrakey endpoint initialization structure (IN) */
  679. static const USBEndpointConfig extra_ep_config = {
  680. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  681. NULL, /* SETUP packet notification callback */
  682. extra_in_cb, /* IN notification callback */
  683. NULL, /* OUT notification callback */
  684. EXTRA_EPSIZE, /* IN maximum packet size */
  685. 0, /* OUT maximum packet size */
  686. &extra_ep_state, /* IN Endpoint state */
  687. NULL, /* OUT endpoint state */
  688. 2, /* IN multiplier */
  689. NULL /* SETUP buffer (not a SETUP endpoint) */
  690. };
  691. #endif /* EXTRAKEY_ENABLE */
  692. #ifdef NKRO_ENABLE
  693. /* nkro endpoint state structure */
  694. static USBInEndpointState nkro_ep_state;
  695. /* nkro endpoint initialization structure (IN) */
  696. static const USBEndpointConfig nkro_ep_config = {
  697. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  698. NULL, /* SETUP packet notification callback */
  699. nkro_in_cb, /* IN notification callback */
  700. NULL, /* OUT notification callback */
  701. NKRO_EPSIZE, /* IN maximum packet size */
  702. 0, /* OUT maximum packet size */
  703. &nkro_ep_state, /* IN Endpoint state */
  704. NULL, /* OUT endpoint state */
  705. 2, /* IN multiplier */
  706. NULL /* SETUP buffer (not a SETUP endpoint) */
  707. };
  708. #endif /* NKRO_ENABLE */
  709. /* ---------------------------------------------------------
  710. * USB driver functions
  711. * ---------------------------------------------------------
  712. */
  713. /* Handles the USB driver global events
  714. * TODO: maybe disable some things when connection is lost? */
  715. static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
  716. switch(event) {
  717. case USB_EVENT_RESET:
  718. //TODO: from ISR! print("[R]");
  719. return;
  720. case USB_EVENT_ADDRESS:
  721. return;
  722. case USB_EVENT_CONFIGURED:
  723. osalSysLockFromISR();
  724. /* Enable the endpoints specified into the configuration. */
  725. usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config);
  726. #ifdef MOUSE_ENABLE
  727. usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config);
  728. #endif /* MOUSE_ENABLE */
  729. #ifdef CONSOLE_ENABLE
  730. usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
  731. /* don't need to start the flush timer, it starts from console_in_cb automatically */
  732. #endif /* CONSOLE_ENABLE */
  733. #ifdef EXTRAKEY_ENABLE
  734. usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config);
  735. #endif /* EXTRAKEY_ENABLE */
  736. #ifdef NKRO_ENABLE
  737. usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config);
  738. #endif /* NKRO_ENABLE */
  739. osalSysUnlockFromISR();
  740. return;
  741. case USB_EVENT_SUSPEND:
  742. //TODO: from ISR! print("[S]");
  743. hook_usb_suspend_entry();
  744. return;
  745. case USB_EVENT_WAKEUP:
  746. //TODO: from ISR! print("[W]");
  747. suspend_wakeup_init();
  748. hook_usb_wakeup();
  749. return;
  750. case USB_EVENT_STALLED:
  751. return;
  752. }
  753. }
  754. /* Function used locally in os/hal/src/usb.c for getting descriptors
  755. * need it here for HID descriptor */
  756. static uint16_t get_hword(uint8_t *p) {
  757. uint16_t hw;
  758. hw = (uint16_t)*p++;
  759. hw |= (uint16_t)*p << 8U;
  760. return hw;
  761. }
  762. /*
  763. * Appendix G: HID Request Support Requirements
  764. *
  765. * The following table enumerates the requests that need to be supported by various types of HID class devices.
  766. * Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
  767. * ------------------------------------------------------------------------------------------
  768. * Boot Mouse Required Optional Optional Optional Required Required
  769. * Non-Boot Mouse Required Optional Optional Optional Optional Optional
  770. * Boot Keyboard Required Optional Required Required Required Required
  771. * Non-Boot Keybrd Required Optional Required Required Optional Optional
  772. * Other Device Required Optional Optional Optional Optional Optional
  773. */
  774. /* Callback for SETUP request on the endpoint 0 (control) */
  775. static bool usb_request_hook_cb(USBDriver *usbp) {
  776. const USBDescriptor *dp;
  777. /* usbp->setup fields:
  778. * 0: bmRequestType (bitmask)
  779. * 1: bRequest
  780. * 2,3: (LSB,MSB) wValue
  781. * 4,5: (LSB,MSB) wIndex
  782. * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
  783. /* Handle HID class specific requests */
  784. if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
  785. ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
  786. switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
  787. case USB_RTYPE_DIR_DEV2HOST:
  788. switch(usbp->setup[1]) { /* bRequest */
  789. case HID_GET_REPORT:
  790. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
  791. case KBD_INTERFACE:
  792. #ifdef NKRO_ENABLE
  793. case NKRO_INTERFACE:
  794. #endif /* NKRO_ENABLE */
  795. usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
  796. return TRUE;
  797. break;
  798. #ifdef MOUSE_ENABLE
  799. case MOUSE_INTERFACE:
  800. usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
  801. return TRUE;
  802. break;
  803. #endif /* MOUSE_ENABLE */
  804. #ifdef CONSOLE_ENABLE
  805. case CONSOLE_INTERFACE:
  806. usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
  807. return TRUE;
  808. break;
  809. #endif /* CONSOLE_ENABLE */
  810. #ifdef EXTRAKEY_ENABLE
  811. case EXTRA_INTERFACE:
  812. if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
  813. switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
  814. case REPORT_ID_SYSTEM:
  815. extra_report_blank[0] = REPORT_ID_SYSTEM;
  816. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  817. return TRUE;
  818. break;
  819. case REPORT_ID_CONSUMER:
  820. extra_report_blank[0] = REPORT_ID_CONSUMER;
  821. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  822. return TRUE;
  823. break;
  824. default:
  825. return FALSE;
  826. }
  827. } else {
  828. return FALSE;
  829. }
  830. break;
  831. #endif /* EXTRAKEY_ENABLE */
  832. default:
  833. usbSetupTransfer(usbp, NULL, 0, NULL);
  834. return TRUE;
  835. break;
  836. }
  837. break;
  838. case HID_GET_PROTOCOL:
  839. if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  840. usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
  841. return TRUE;
  842. }
  843. break;
  844. case HID_GET_IDLE:
  845. usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
  846. return TRUE;
  847. break;
  848. }
  849. break;
  850. case USB_RTYPE_DIR_HOST2DEV:
  851. switch(usbp->setup[1]) { /* bRequest */
  852. case HID_SET_REPORT:
  853. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
  854. case KBD_INTERFACE:
  855. #ifdef NKRO_ENABLE
  856. case NKRO_INTERFACE:
  857. #endif /* NKRO_ENABLE */
  858. /* keyboard_led_stats = <read byte from next OUT report>
  859. * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
  860. usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
  861. return TRUE;
  862. break;
  863. }
  864. break;
  865. case HID_SET_PROTOCOL:
  866. if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  867. keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
  868. #ifdef NKRO_ENABLE
  869. keyboard_nkro = !!keyboard_protocol;
  870. if(!keyboard_nkro && keyboard_idle) {
  871. #else /* NKRO_ENABLE */
  872. if(keyboard_idle) {
  873. #endif /* NKRO_ENABLE */
  874. /* arm the idle timer if boot protocol & idle */
  875. osalSysLockFromISR();
  876. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  877. osalSysUnlockFromISR();
  878. }
  879. }
  880. usbSetupTransfer(usbp, NULL, 0, NULL);
  881. return TRUE;
  882. break;
  883. case HID_SET_IDLE:
  884. keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
  885. /* arm the timer */
  886. #ifdef NKRO_ENABLE
  887. if(!keyboard_nkro && keyboard_idle) {
  888. #else /* NKRO_ENABLE */
  889. if(keyboard_idle) {
  890. #endif /* NKRO_ENABLE */
  891. osalSysLockFromISR();
  892. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  893. osalSysUnlockFromISR();
  894. }
  895. usbSetupTransfer(usbp, NULL, 0, NULL);
  896. return TRUE;
  897. break;
  898. }
  899. break;
  900. }
  901. }
  902. /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
  903. if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
  904. dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
  905. if(dp == NULL)
  906. return FALSE;
  907. usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
  908. return TRUE;
  909. }
  910. return FALSE;
  911. }
  912. /* Start-of-frame callback */
  913. static void usb_sof_cb(USBDriver *usbp) {
  914. kbd_sof_cb(usbp);
  915. }
  916. /* USB driver configuration */
  917. static const USBConfig usbcfg = {
  918. usb_event_cb, /* USB events callback */
  919. usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
  920. usb_request_hook_cb, /* Requests hook callback */
  921. usb_sof_cb /* Start Of Frame callback */
  922. };
  923. /*
  924. * Initialize the USB driver
  925. */
  926. void init_usb_driver(USBDriver *usbp) {
  927. /*
  928. * Activates the USB driver and then the USB bus pull-up on D+.
  929. * Note, a delay is inserted in order to not have to disconnect the cable
  930. * after a reset.
  931. */
  932. usbDisconnectBus(usbp);
  933. chThdSleepMilliseconds(1500);
  934. usbStart(usbp, &usbcfg);
  935. usbConnectBus(usbp);
  936. chVTObjectInit(&keyboard_idle_timer);
  937. #ifdef CONSOLE_ENABLE
  938. obqObjectInit(&console_buf_queue, true, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
  939. chVTObjectInit(&console_flush_timer);
  940. #endif
  941. }
  942. /*
  943. * Send remote wakeup packet
  944. * Note: should not be called from ISR
  945. */
  946. void send_remote_wakeup(USBDriver *usbp) {
  947. (void)usbp;
  948. #if defined(K20x) || defined(KL2x)
  949. #if KINETIS_USB_USE_USB0
  950. USB0->CTL |= USBx_CTL_RESUME;
  951. chThdSleepMilliseconds(15);
  952. USB0->CTL &= ~USBx_CTL_RESUME;
  953. #endif /* KINETIS_USB_USE_USB0 */
  954. #elif defined(STM32F0XX) || defined(STM32F1XX) /* K20x || KL2x */
  955. STM32_USB->CNTR |= CNTR_RESUME;
  956. chThdSleepMilliseconds(15);
  957. STM32_USB->CNTR &= ~CNTR_RESUME;
  958. #else /* STM32F0XX || STM32F1XX */
  959. #warning Sending remote wakeup packet not implemented for your platform.
  960. #endif /* K20x || KL2x */
  961. }
  962. /* ---------------------------------------------------------
  963. * Keyboard functions
  964. * ---------------------------------------------------------
  965. */
  966. /* keyboard IN callback hander (a kbd report has made it IN) */
  967. void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
  968. /* STUB */
  969. (void)usbp;
  970. (void)ep;
  971. }
  972. #ifdef NKRO_ENABLE
  973. /* nkro IN callback hander (a nkro report has made it IN) */
  974. void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
  975. /* STUB */
  976. (void)usbp;
  977. (void)ep;
  978. }
  979. #endif /* NKRO_ENABLE */
  980. /* start-of-frame handler
  981. * TODO: i guess it would be better to re-implement using timers,
  982. * so that this is not going to have to be checked every 1ms */
  983. void kbd_sof_cb(USBDriver *usbp) {
  984. (void)usbp;
  985. }
  986. /* Idle requests timer code
  987. * callback (called from ISR, unlocked state) */
  988. static void keyboard_idle_timer_cb(void *arg) {
  989. USBDriver *usbp = (USBDriver *)arg;
  990. osalSysLockFromISR();
  991. /* check that the states of things are as they're supposed to */
  992. if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
  993. /* do not rearm the timer, should be enabled on IDLE request */
  994. osalSysUnlockFromISR();
  995. return;
  996. }
  997. #ifdef NKRO_ENABLE
  998. if(!keyboard_nkro && keyboard_idle) {
  999. #else /* NKRO_ENABLE */
  1000. if(keyboard_idle) {
  1001. #endif /* NKRO_ENABLE */
  1002. /* TODO: are we sure we want the KBD_ENDPOINT? */
  1003. if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) {
  1004. usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE);
  1005. }
  1006. /* rearm the timer */
  1007. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  1008. }
  1009. /* do not rearm the timer if the condition above fails
  1010. * it should be enabled again on either IDLE or SET_PROTOCOL requests */
  1011. osalSysUnlockFromISR();
  1012. }
  1013. /* LED status */
  1014. uint8_t keyboard_leds(void) {
  1015. return (uint8_t)(keyboard_led_stats & 0xFF);
  1016. }
  1017. /* prepare and start sending a report IN
  1018. * not callable from ISR or locked state */
  1019. void send_keyboard(report_keyboard_t *report) {
  1020. osalSysLock();
  1021. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  1022. osalSysUnlock();
  1023. return;
  1024. }
  1025. osalSysUnlock();
  1026. #ifdef NKRO_ENABLE
  1027. if(keyboard_nkro) { /* NKRO protocol */
  1028. /* need to wait until the previous packet has made it through */
  1029. /* can rewrite this using the synchronous API, then would wait
  1030. * until *after* the packet has been transmitted. I think
  1031. * this is more efficient */
  1032. /* busy wait, should be short and not very common */
  1033. osalSysLock();
  1034. if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) {
  1035. /* Need to either suspend, or loop and call unlock/lock during
  1036. * every iteration - otherwise the system will remain locked,
  1037. * no interrupts served, so USB not going through as well.
  1038. * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
  1039. osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread);
  1040. }
  1041. usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
  1042. osalSysUnlock();
  1043. } else
  1044. #endif /* NKRO_ENABLE */
  1045. { /* boot protocol */
  1046. /* need to wait until the previous packet has made it through */
  1047. /* busy wait, should be short and not very common */
  1048. osalSysLock();
  1049. if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) {
  1050. /* Need to either suspend, or loop and call unlock/lock during
  1051. * every iteration - otherwise the system will remain locked,
  1052. * no interrupts served, so USB not going through as well.
  1053. * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
  1054. osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread);
  1055. }
  1056. usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
  1057. osalSysUnlock();
  1058. }
  1059. keyboard_report_sent = *report;
  1060. }
  1061. /* ---------------------------------------------------------
  1062. * Mouse functions
  1063. * ---------------------------------------------------------
  1064. */
  1065. #ifdef MOUSE_ENABLE
  1066. /* mouse IN callback hander (a mouse report has made it IN) */
  1067. void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
  1068. (void)usbp;
  1069. (void)ep;
  1070. }
  1071. void send_mouse(report_mouse_t *report) {
  1072. osalSysLock();
  1073. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  1074. osalSysUnlock();
  1075. return;
  1076. }
  1077. osalSysUnlock();
  1078. /* TODO: LUFA manually waits for the endpoint to become ready
  1079. * for about 10ms for mouse, kbd, system; 1ms for nkro
  1080. * is this really needed?
  1081. */
  1082. osalSysLock();
  1083. usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
  1084. osalSysUnlock();
  1085. }
  1086. #else /* MOUSE_ENABLE */
  1087. void send_mouse(report_mouse_t *report) {
  1088. (void)report;
  1089. }
  1090. #endif /* MOUSE_ENABLE */
  1091. /* ---------------------------------------------------------
  1092. * Extrakey functions
  1093. * ---------------------------------------------------------
  1094. */
  1095. #ifdef EXTRAKEY_ENABLE
  1096. /* extrakey IN callback hander */
  1097. void extra_in_cb(USBDriver *usbp, usbep_t ep) {
  1098. /* STUB */
  1099. (void)usbp;
  1100. (void)ep;
  1101. }
  1102. static void send_extra_report(uint8_t report_id, uint16_t data) {
  1103. osalSysLock();
  1104. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  1105. osalSysUnlock();
  1106. return;
  1107. }
  1108. report_extra_t report = {
  1109. .report_id = report_id,
  1110. .usage = data
  1111. };
  1112. usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
  1113. osalSysUnlock();
  1114. }
  1115. void send_system(uint16_t data) {
  1116. send_extra_report(REPORT_ID_SYSTEM, data);
  1117. }
  1118. void send_consumer(uint16_t data) {
  1119. send_extra_report(REPORT_ID_CONSUMER, data);
  1120. }
  1121. #else /* EXTRAKEY_ENABLE */
  1122. void send_system(uint16_t data) {
  1123. (void)data;
  1124. }
  1125. void send_consumer(uint16_t data) {
  1126. (void)data;
  1127. }
  1128. #endif /* EXTRAKEY_ENABLE */
  1129. /* ---------------------------------------------------------
  1130. * Console functions
  1131. * ---------------------------------------------------------
  1132. */
  1133. #ifdef CONSOLE_ENABLE
  1134. /* console IN callback hander */
  1135. void console_in_cb(USBDriver *usbp, usbep_t ep) {
  1136. (void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */
  1137. uint8_t *buf;
  1138. size_t n;
  1139. osalSysLockFromISR();
  1140. /* rearm the timer */
  1141. chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
  1142. /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
  1143. if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
  1144. obqReleaseEmptyBufferI(&console_buf_queue);
  1145. }
  1146. /* Checking if there is a buffer ready for transmission.*/
  1147. buf = obqGetFullBufferI(&console_buf_queue, &n);
  1148. if (buf != NULL) {
  1149. /* The endpoint cannot be busy, we are in the context of the callback,
  1150. so it is safe to transmit without a check.*/
  1151. /* Should have n == CONSOLE_EPSIZE; check it? */
  1152. usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
  1153. } else {
  1154. /* Nothing to transmit.*/
  1155. }
  1156. osalSysUnlockFromISR();
  1157. }
  1158. /* Callback when data is inserted into the output queue
  1159. * Called from a locked state */
  1160. void console_queue_onotify(io_buffers_queue_t *bqp) {
  1161. size_t n;
  1162. USBDriver *usbp = bqGetLinkX(bqp);
  1163. if(usbGetDriverStateI(usbp) != USB_ACTIVE)
  1164. return;
  1165. /* Checking if there is already a transaction ongoing on the endpoint.*/
  1166. if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
  1167. /* Trying to get a full buffer.*/
  1168. uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
  1169. if (buf != NULL) {
  1170. /* Buffer found, starting a new transaction.*/
  1171. /* Should have n == CONSOLE_EPSIZE; check this? */
  1172. usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
  1173. }
  1174. }
  1175. }
  1176. /* Flush timer code
  1177. * callback (called from ISR, unlocked state) */
  1178. static void console_flush_cb(void *arg) {
  1179. USBDriver *usbp = (USBDriver *)arg;
  1180. osalSysLockFromISR();
  1181. /* check that the states of things are as they're supposed to */
  1182. if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
  1183. /* rearm the timer */
  1184. chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
  1185. osalSysUnlockFromISR();
  1186. return;
  1187. }
  1188. /* If there is already a transaction ongoing then another one cannot be
  1189. started.*/
  1190. if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
  1191. /* rearm the timer */
  1192. chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
  1193. osalSysUnlockFromISR();
  1194. return;
  1195. }
  1196. /* Checking if there only a buffer partially filled, if so then it is
  1197. enforced in the queue and transmitted.*/
  1198. if(obqTryFlushI(&console_buf_queue)) {
  1199. size_t n,i;
  1200. uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
  1201. osalDbgAssert(buf != NULL, "queue is empty");
  1202. /* zero the rest of the buffer (buf should point to allocated space) */
  1203. for(i=n; i<CONSOLE_EPSIZE; i++)
  1204. buf[i]=0;
  1205. usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
  1206. }
  1207. /* rearm the timer */
  1208. chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
  1209. osalSysUnlockFromISR();
  1210. }
  1211. int8_t sendchar(uint8_t c) {
  1212. osalSysLock();
  1213. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  1214. osalSysUnlock();
  1215. return 0;
  1216. }
  1217. osalSysUnlock();
  1218. /* Timeout after 100us if the queue is full.
  1219. * Increase this timeout if too much stuff is getting
  1220. * dropped (i.e. the buffer is getting full too fast
  1221. * for USB/HIDRAW to dequeue). Another possibility
  1222. * for fixing this kind of thing is to increase
  1223. * CONSOLE_QUEUE_CAPACITY. */
  1224. return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
  1225. }
  1226. #else /* CONSOLE_ENABLE */
  1227. int8_t sendchar(uint8_t c) {
  1228. (void)c;
  1229. return 0;
  1230. }
  1231. #endif /* CONSOLE_ENABLE */
  1232. void sendchar_pf(void *p, char c) {
  1233. (void)p;
  1234. sendchar((uint8_t)c);
  1235. }