usb_main.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. /*
  2. * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
  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 "wait.h"
  28. #include "usb_descriptor.h"
  29. #ifdef NKRO_ENABLE
  30. #include "keycode_config.h"
  31. extern keymap_config_t keymap_config;
  32. #endif
  33. /* ---------------------------------------------------------
  34. * Global interface variables and declarations
  35. * ---------------------------------------------------------
  36. */
  37. #ifndef usb_lld_connect_bus
  38. #define usb_lld_connect_bus(usbp)
  39. #endif
  40. #ifndef usb_lld_disconnect_bus
  41. #define usb_lld_disconnect_bus(usbp)
  42. #endif
  43. uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
  44. uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
  45. uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
  46. volatile uint16_t keyboard_idle_count = 0;
  47. static virtual_timer_t keyboard_idle_timer;
  48. static void keyboard_idle_timer_cb(void *arg);
  49. report_keyboard_t keyboard_report_sent = {{0}};
  50. #ifdef MOUSE_ENABLE
  51. report_mouse_t mouse_report_blank = {0};
  52. #endif /* MOUSE_ENABLE */
  53. #ifdef EXTRAKEY_ENABLE
  54. uint8_t extra_report_blank[3] = {0};
  55. #endif /* EXTRAKEY_ENABLE */
  56. /* ---------------------------------------------------------
  57. * Descriptors and USB driver objects
  58. * ---------------------------------------------------------
  59. */
  60. /* HID specific constants */
  61. #define HID_GET_REPORT 0x01
  62. #define HID_GET_IDLE 0x02
  63. #define HID_GET_PROTOCOL 0x03
  64. #define HID_SET_REPORT 0x09
  65. #define HID_SET_IDLE 0x0A
  66. #define HID_SET_PROTOCOL 0x0B
  67. /*
  68. * Handles the GET_DESCRIPTOR callback
  69. *
  70. * Returns the proper descriptor
  71. */
  72. static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
  73. (void)usbp;
  74. static USBDescriptor desc;
  75. uint16_t wValue = ((uint16_t)dtype << 8) | dindex;
  76. desc.ud_string = NULL;
  77. desc.ud_size = get_usb_descriptor(wValue, wIndex, (const void** const)&desc.ud_string);
  78. if (desc.ud_string == NULL)
  79. return NULL;
  80. else
  81. return &desc;
  82. }
  83. /* keyboard endpoint state structure */
  84. static USBInEndpointState kbd_ep_state;
  85. /* keyboard endpoint initialization structure (IN) */
  86. static const USBEndpointConfig kbd_ep_config = {
  87. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  88. NULL, /* SETUP packet notification callback */
  89. kbd_in_cb, /* IN notification callback */
  90. NULL, /* OUT notification callback */
  91. KEYBOARD_EPSIZE, /* IN maximum packet size */
  92. 0, /* OUT maximum packet size */
  93. &kbd_ep_state, /* IN Endpoint state */
  94. NULL, /* OUT endpoint state */
  95. 2, /* IN multiplier */
  96. NULL /* SETUP buffer (not a SETUP endpoint) */
  97. };
  98. #ifdef MOUSE_ENABLE
  99. /* mouse endpoint state structure */
  100. static USBInEndpointState mouse_ep_state;
  101. /* mouse endpoint initialization structure (IN) */
  102. static const USBEndpointConfig mouse_ep_config = {
  103. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  104. NULL, /* SETUP packet notification callback */
  105. mouse_in_cb, /* IN notification callback */
  106. NULL, /* OUT notification callback */
  107. MOUSE_EPSIZE, /* IN maximum packet size */
  108. 0, /* OUT maximum packet size */
  109. &mouse_ep_state, /* IN Endpoint state */
  110. NULL, /* OUT endpoint state */
  111. 2, /* IN multiplier */
  112. NULL /* SETUP buffer (not a SETUP endpoint) */
  113. };
  114. #endif /* MOUSE_ENABLE */
  115. #ifdef EXTRAKEY_ENABLE
  116. /* extrakey endpoint state structure */
  117. static USBInEndpointState extra_ep_state;
  118. /* extrakey endpoint initialization structure (IN) */
  119. static const USBEndpointConfig extra_ep_config = {
  120. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  121. NULL, /* SETUP packet notification callback */
  122. extra_in_cb, /* IN notification callback */
  123. NULL, /* OUT notification callback */
  124. EXTRAKEY_EPSIZE, /* IN maximum packet size */
  125. 0, /* OUT maximum packet size */
  126. &extra_ep_state, /* IN Endpoint state */
  127. NULL, /* OUT endpoint state */
  128. 2, /* IN multiplier */
  129. NULL /* SETUP buffer (not a SETUP endpoint) */
  130. };
  131. #endif /* EXTRAKEY_ENABLE */
  132. #ifdef NKRO_ENABLE
  133. /* nkro endpoint state structure */
  134. static USBInEndpointState nkro_ep_state;
  135. /* nkro endpoint initialization structure (IN) */
  136. static const USBEndpointConfig nkro_ep_config = {
  137. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  138. NULL, /* SETUP packet notification callback */
  139. nkro_in_cb, /* IN notification callback */
  140. NULL, /* OUT notification callback */
  141. NKRO_EPSIZE, /* IN maximum packet size */
  142. 0, /* OUT maximum packet size */
  143. &nkro_ep_state, /* IN Endpoint state */
  144. NULL, /* OUT endpoint state */
  145. 2, /* IN multiplier */
  146. NULL /* SETUP buffer (not a SETUP endpoint) */
  147. };
  148. #endif /* NKRO_ENABLE */
  149. typedef struct {
  150. size_t queue_capacity_in;
  151. size_t queue_capacity_out;
  152. uint8_t* queue_buffer_in;
  153. uint8_t* queue_buffer_out;
  154. USBInEndpointState in_ep_state;
  155. USBOutEndpointState out_ep_state;
  156. USBInEndpointState int_ep_state;
  157. USBEndpointConfig in_ep_config;
  158. USBEndpointConfig out_ep_config;
  159. USBEndpointConfig int_ep_config;
  160. const SerialUSBConfig config;
  161. SerialUSBDriver driver;
  162. } stream_driver_t;
  163. #define STREAM_DRIVER(stream, notification) { \
  164. .queue_capacity_in = stream##_IN_CAPACITY, \
  165. .queue_capacity_out = stream##_OUT_CAPACITY, \
  166. .queue_buffer_in = (uint8_t[BQ_BUFFER_SIZE(stream##_IN_CAPACITY, stream##_EPSIZE)]) {}, \
  167. .queue_buffer_out = (uint8_t[BQ_BUFFER_SIZE(stream##_OUT_CAPACITY,stream##_EPSIZE)]) {}, \
  168. .in_ep_config = { \
  169. .ep_mode = stream##_IN_MODE, \
  170. .setup_cb = NULL, \
  171. .in_cb = sduDataTransmitted, \
  172. .out_cb = NULL, \
  173. .in_maxsize = stream##_EPSIZE, \
  174. .out_maxsize = 0, \
  175. /* The pointer to the states will be filled during initialization */ \
  176. .in_state = NULL, \
  177. .out_state = NULL, \
  178. .ep_buffers = 2, \
  179. .setup_buf = NULL \
  180. }, \
  181. .out_ep_config = { \
  182. .ep_mode = stream##_OUT_MODE, \
  183. .setup_cb = NULL, \
  184. .in_cb = NULL, \
  185. .out_cb = sduDataReceived, \
  186. .in_maxsize = 0, \
  187. .out_maxsize = stream##_EPSIZE, \
  188. /* The pointer to the states will be filled during initialization */ \
  189. .in_state = NULL, \
  190. .out_state = NULL, \
  191. .ep_buffers = 2, \
  192. .setup_buf = NULL, \
  193. }, \
  194. .int_ep_config = { \
  195. .ep_mode = USB_EP_MODE_TYPE_INTR, \
  196. .setup_cb = NULL, \
  197. .in_cb = sduInterruptTransmitted, \
  198. .out_cb = NULL, \
  199. .in_maxsize = CDC_NOTIFICATION_EPSIZE, \
  200. .out_maxsize = 0, \
  201. /* The pointer to the states will be filled during initialization */ \
  202. .in_state = NULL, \
  203. .out_state = NULL, \
  204. .ep_buffers = 2, \
  205. .setup_buf = NULL, \
  206. }, \
  207. .config = { \
  208. .usbp = &USB_DRIVER, \
  209. .bulk_in = stream##_IN_EPNUM, \
  210. .bulk_out = stream##_OUT_EPNUM, \
  211. .int_in = notification \
  212. } \
  213. }
  214. typedef struct {
  215. union {
  216. struct {
  217. #ifdef CONSOLE_ENABLE
  218. stream_driver_t console_driver;
  219. #endif
  220. #ifdef RAW_ENABLE
  221. stream_driver_t raw_driver;
  222. #endif
  223. #ifdef MIDI_ENABLE
  224. stream_driver_t midi_driver;
  225. #endif
  226. #ifdef VIRTSER_ENABLE
  227. stream_driver_t serial_driver;
  228. #endif
  229. };
  230. stream_driver_t array[0];
  231. };
  232. } stream_drivers_t;
  233. static stream_drivers_t drivers = {
  234. #ifdef CONSOLE_ENABLE
  235. #define CONSOLE_IN_CAPACITY 4
  236. #define CONSOLE_OUT_CAPACITY 4
  237. #define CONSOLE_IN_MODE USB_EP_MODE_TYPE_INTR
  238. #define CONSOLE_OUT_MODE USB_EP_MODE_TYPE_INTR
  239. .console_driver = STREAM_DRIVER(CONSOLE, 0),
  240. #endif
  241. #ifdef RAW_ENABLE
  242. #define RAW_IN_CAPACITY 4
  243. #define RAW_OUT_CAPACITY 4
  244. #define RAW_IN_MODE USB_EP_MODE_TYPE_INTR
  245. #define RAW_OUT_MODE USB_EP_MODE_TYPE_INTR
  246. .raw_driver = STREAM_DRIVER(RAW, 0),
  247. #endif
  248. #ifdef MIDI_ENABLE
  249. #define MIDI_STREAM_IN_CAPACITY 4
  250. #define MIDI_STREAM_OUT_CAPACITY 4
  251. #define MIDI_STREAM_IN_MODE USB_EP_MODE_TYPE_BULK
  252. #define MIDI_STREAM_OUT_MODE USB_EP_MODE_TYPE_BULK
  253. .midi_driver = STREAM_DRIVER(MIDI_STREAM, 0),
  254. #endif
  255. #ifdef VIRTSER_ENABLE
  256. #define CDC_IN_CAPACITY 4
  257. #define CDC_OUT_CAPACITY 4
  258. #define CDC_IN_MODE USB_EP_MODE_TYPE_BULK
  259. #define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK
  260. .serial_driver = STREAM_DRIVER(CDC, CDC_NOTIFICATION_EPNUM),
  261. #endif
  262. };
  263. #define NUM_STREAM_DRIVERS (sizeof(drivers) / sizeof(stream_driver_t))
  264. /* ---------------------------------------------------------
  265. * USB driver functions
  266. * ---------------------------------------------------------
  267. */
  268. /* Handles the USB driver global events
  269. * TODO: maybe disable some things when connection is lost? */
  270. static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
  271. switch(event) {
  272. case USB_EVENT_ADDRESS:
  273. return;
  274. case USB_EVENT_CONFIGURED:
  275. osalSysLockFromISR();
  276. /* Enable the endpoints specified into the configuration. */
  277. usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
  278. #ifdef MOUSE_ENABLE
  279. usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
  280. #endif /* MOUSE_ENABLE */
  281. #ifdef EXTRAKEY_ENABLE
  282. usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config);
  283. #endif /* EXTRAKEY_ENABLE */
  284. #ifdef NKRO_ENABLE
  285. usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
  286. #endif /* NKRO_ENABLE */
  287. for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
  288. usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
  289. usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
  290. if (drivers.array[i].config.int_in) {
  291. usbInitEndpointI(usbp, drivers.array[i].config.int_in, &drivers.array[i].int_ep_config);
  292. }
  293. sduConfigureHookI(&drivers.array[i].driver);
  294. }
  295. osalSysUnlockFromISR();
  296. return;
  297. case USB_EVENT_SUSPEND:
  298. #ifdef SLEEP_LED_ENABLE
  299. sleep_led_enable();
  300. #endif /* SLEEP_LED_ENABLE */
  301. /* Falls into.*/
  302. case USB_EVENT_UNCONFIGURED:
  303. /* Falls into.*/
  304. case USB_EVENT_RESET:
  305. for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
  306. chSysLockFromISR();
  307. /* Disconnection event on suspend.*/
  308. sduSuspendHookI(&drivers.array[i].driver);
  309. chSysUnlockFromISR();
  310. }
  311. return;
  312. case USB_EVENT_WAKEUP:
  313. //TODO: from ISR! print("[W]");
  314. for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
  315. chSysLockFromISR();
  316. /* Disconnection event on suspend.*/
  317. sduWakeupHookI(&drivers.array[i].driver);
  318. chSysUnlockFromISR();
  319. }
  320. suspend_wakeup_init();
  321. #ifdef SLEEP_LED_ENABLE
  322. sleep_led_disable();
  323. // NOTE: converters may not accept this
  324. led_set(host_keyboard_leds());
  325. #endif /* SLEEP_LED_ENABLE */
  326. return;
  327. case USB_EVENT_STALLED:
  328. return;
  329. }
  330. }
  331. /* Function used locally in os/hal/src/usb.c for getting descriptors
  332. * need it here for HID descriptor */
  333. static uint16_t get_hword(uint8_t *p) {
  334. uint16_t hw;
  335. hw = (uint16_t)*p++;
  336. hw |= (uint16_t)*p << 8U;
  337. return hw;
  338. }
  339. /*
  340. * Appendix G: HID Request Support Requirements
  341. *
  342. * The following table enumerates the requests that need to be supported by various types of HID class devices.
  343. * Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
  344. * ------------------------------------------------------------------------------------------
  345. * Boot Mouse Required Optional Optional Optional Required Required
  346. * Non-Boot Mouse Required Optional Optional Optional Optional Optional
  347. * Boot Keyboard Required Optional Required Required Required Required
  348. * Non-Boot Keybrd Required Optional Required Required Optional Optional
  349. * Other Device Required Optional Optional Optional Optional Optional
  350. */
  351. /* Callback for SETUP request on the endpoint 0 (control) */
  352. static bool usb_request_hook_cb(USBDriver *usbp) {
  353. const USBDescriptor *dp;
  354. /* usbp->setup fields:
  355. * 0: bmRequestType (bitmask)
  356. * 1: bRequest
  357. * 2,3: (LSB,MSB) wValue
  358. * 4,5: (LSB,MSB) wIndex
  359. * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
  360. /* Handle HID class specific requests */
  361. if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
  362. ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
  363. switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
  364. case USB_RTYPE_DIR_DEV2HOST:
  365. switch(usbp->setup[1]) { /* bRequest */
  366. case HID_GET_REPORT:
  367. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
  368. case KEYBOARD_INTERFACE:
  369. #ifdef NKRO_ENABLE
  370. case NKRO_INTERFACE:
  371. #endif /* NKRO_ENABLE */
  372. usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
  373. return TRUE;
  374. break;
  375. #ifdef MOUSE_ENABLE
  376. case MOUSE_INTERFACE:
  377. usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
  378. return TRUE;
  379. break;
  380. #endif /* MOUSE_ENABLE */
  381. #ifdef EXTRAKEY_ENABLE
  382. case EXTRAKEY_INTERFACE:
  383. if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
  384. switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
  385. case REPORT_ID_SYSTEM:
  386. extra_report_blank[0] = REPORT_ID_SYSTEM;
  387. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  388. return TRUE;
  389. break;
  390. case REPORT_ID_CONSUMER:
  391. extra_report_blank[0] = REPORT_ID_CONSUMER;
  392. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  393. return TRUE;
  394. break;
  395. default:
  396. return FALSE;
  397. }
  398. } else {
  399. return FALSE;
  400. }
  401. break;
  402. #endif /* EXTRAKEY_ENABLE */
  403. default:
  404. usbSetupTransfer(usbp, NULL, 0, NULL);
  405. return TRUE;
  406. break;
  407. }
  408. break;
  409. case HID_GET_PROTOCOL:
  410. if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  411. usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
  412. return TRUE;
  413. }
  414. break;
  415. case HID_GET_IDLE:
  416. usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
  417. return TRUE;
  418. break;
  419. }
  420. break;
  421. case USB_RTYPE_DIR_HOST2DEV:
  422. switch(usbp->setup[1]) { /* bRequest */
  423. case HID_SET_REPORT:
  424. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
  425. case KEYBOARD_INTERFACE:
  426. #ifdef NKRO_ENABLE
  427. case NKRO_INTERFACE:
  428. #endif /* NKRO_ENABLE */
  429. /* keyboard_led_stats = <read byte from next OUT report>
  430. * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
  431. usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
  432. return TRUE;
  433. break;
  434. }
  435. break;
  436. case HID_SET_PROTOCOL:
  437. if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  438. keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
  439. #ifdef NKRO_ENABLE
  440. keymap_config.nkro = !!keyboard_protocol;
  441. if(!keymap_config.nkro && keyboard_idle) {
  442. #else /* NKRO_ENABLE */
  443. if(keyboard_idle) {
  444. #endif /* NKRO_ENABLE */
  445. /* arm the idle timer if boot protocol & idle */
  446. osalSysLockFromISR();
  447. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  448. osalSysUnlockFromISR();
  449. }
  450. }
  451. usbSetupTransfer(usbp, NULL, 0, NULL);
  452. return TRUE;
  453. break;
  454. case HID_SET_IDLE:
  455. keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
  456. /* arm the timer */
  457. #ifdef NKRO_ENABLE
  458. if(!keymap_config.nkro && keyboard_idle) {
  459. #else /* NKRO_ENABLE */
  460. if(keyboard_idle) {
  461. #endif /* NKRO_ENABLE */
  462. osalSysLockFromISR();
  463. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  464. osalSysUnlockFromISR();
  465. }
  466. usbSetupTransfer(usbp, NULL, 0, NULL);
  467. return TRUE;
  468. break;
  469. }
  470. break;
  471. }
  472. }
  473. /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
  474. if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
  475. dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
  476. if(dp == NULL)
  477. return FALSE;
  478. usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
  479. return TRUE;
  480. }
  481. for (int i=0;i<NUM_STREAM_DRIVERS;i++) {
  482. if (drivers.array[i].config.int_in) {
  483. // NOTE: Assumes that we only have one serial driver
  484. return sduRequestsHook(usbp);
  485. }
  486. }
  487. return FALSE;
  488. }
  489. /* Start-of-frame callback */
  490. static void usb_sof_cb(USBDriver *usbp) {
  491. kbd_sof_cb(usbp);
  492. osalSysLockFromISR();
  493. for (int i=0; i<NUM_STREAM_DRIVERS;i++) {
  494. sduSOFHookI(&drivers.array[i].driver);
  495. }
  496. osalSysUnlockFromISR();
  497. }
  498. /* USB driver configuration */
  499. static const USBConfig usbcfg = {
  500. usb_event_cb, /* USB events callback */
  501. usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
  502. usb_request_hook_cb, /* Requests hook callback */
  503. usb_sof_cb /* Start Of Frame callback */
  504. };
  505. /*
  506. * Initialize the USB driver
  507. */
  508. void init_usb_driver(USBDriver *usbp) {
  509. for (int i=0; i<NUM_STREAM_DRIVERS;i++) {
  510. SerialUSBDriver* driver = &drivers.array[i].driver;
  511. drivers.array[i].in_ep_config.in_state = &drivers.array[i].in_ep_state;
  512. drivers.array[i].out_ep_config.out_state = &drivers.array[i].out_ep_state;
  513. drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state;
  514. sduObjectInit(driver);
  515. bqnotify_t notify = driver->ibqueue.notify;
  516. ibqObjectInit(&driver->ibqueue, false, drivers.array[i].queue_buffer_in, drivers.array[i].in_ep_config.in_maxsize, drivers.array[i].queue_capacity_in, notify, driver);
  517. notify = driver->obqueue.notify;
  518. ibqObjectInit(&driver->ibqueue, false, drivers.array[i].queue_buffer_out, drivers.array[i].out_ep_config.out_maxsize, drivers.array[i].queue_capacity_out, notify, driver);
  519. sduStart(driver, &drivers.array[i].config);
  520. }
  521. /*
  522. * Activates the USB driver and then the USB bus pull-up on D+.
  523. * Note, a delay is inserted in order to not have to disconnect the cable
  524. * after a reset.
  525. */
  526. usbDisconnectBus(usbp);
  527. wait_ms(1500);
  528. usbStart(usbp, &usbcfg);
  529. usbConnectBus(usbp);
  530. chVTObjectInit(&keyboard_idle_timer);
  531. }
  532. /* ---------------------------------------------------------
  533. * Keyboard functions
  534. * ---------------------------------------------------------
  535. */
  536. /* keyboard IN callback hander (a kbd report has made it IN) */
  537. void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
  538. /* STUB */
  539. (void)usbp;
  540. (void)ep;
  541. }
  542. #ifdef NKRO_ENABLE
  543. /* nkro IN callback hander (a nkro report has made it IN) */
  544. void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
  545. /* STUB */
  546. (void)usbp;
  547. (void)ep;
  548. }
  549. #endif /* NKRO_ENABLE */
  550. /* start-of-frame handler
  551. * TODO: i guess it would be better to re-implement using timers,
  552. * so that this is not going to have to be checked every 1ms */
  553. void kbd_sof_cb(USBDriver *usbp) {
  554. (void)usbp;
  555. }
  556. /* Idle requests timer code
  557. * callback (called from ISR, unlocked state) */
  558. static void keyboard_idle_timer_cb(void *arg) {
  559. USBDriver *usbp = (USBDriver *)arg;
  560. osalSysLockFromISR();
  561. /* check that the states of things are as they're supposed to */
  562. if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
  563. /* do not rearm the timer, should be enabled on IDLE request */
  564. osalSysUnlockFromISR();
  565. return;
  566. }
  567. #ifdef NKRO_ENABLE
  568. if(!keymap_config.nkro && keyboard_idle) {
  569. #else /* NKRO_ENABLE */
  570. if(keyboard_idle) {
  571. #endif /* NKRO_ENABLE */
  572. /* TODO: are we sure we want the KBD_ENDPOINT? */
  573. if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
  574. usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
  575. }
  576. /* rearm the timer */
  577. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  578. }
  579. /* do not rearm the timer if the condition above fails
  580. * it should be enabled again on either IDLE or SET_PROTOCOL requests */
  581. osalSysUnlockFromISR();
  582. }
  583. /* LED status */
  584. uint8_t keyboard_leds(void) {
  585. return (uint8_t)(keyboard_led_stats & 0xFF);
  586. }
  587. /* prepare and start sending a report IN
  588. * not callable from ISR or locked state */
  589. void send_keyboard(report_keyboard_t *report) {
  590. osalSysLock();
  591. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  592. osalSysUnlock();
  593. return;
  594. }
  595. osalSysUnlock();
  596. #ifdef NKRO_ENABLE
  597. if(keymap_config.nkro) { /* NKRO protocol */
  598. /* need to wait until the previous packet has made it through */
  599. /* can rewrite this using the synchronous API, then would wait
  600. * until *after* the packet has been transmitted. I think
  601. * this is more efficient */
  602. /* busy wait, should be short and not very common */
  603. osalSysLock();
  604. if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) {
  605. /* Need to either suspend, or loop and call unlock/lock during
  606. * every iteration - otherwise the system will remain locked,
  607. * no interrupts served, so USB not going through as well.
  608. * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
  609. osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread);
  610. }
  611. usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t));
  612. osalSysUnlock();
  613. } else
  614. #endif /* NKRO_ENABLE */
  615. { /* boot protocol */
  616. /* need to wait until the previous packet has made it through */
  617. /* busy wait, should be short and not very common */
  618. osalSysLock();
  619. if(usbGetTransmitStatusI(&USB_DRIVER, KEYBOARD_IN_EPNUM)) {
  620. /* Need to either suspend, or loop and call unlock/lock during
  621. * every iteration - otherwise the system will remain locked,
  622. * no interrupts served, so USB not going through as well.
  623. * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
  624. osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
  625. }
  626. usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE);
  627. osalSysUnlock();
  628. }
  629. keyboard_report_sent = *report;
  630. }
  631. /* ---------------------------------------------------------
  632. * Mouse functions
  633. * ---------------------------------------------------------
  634. */
  635. #ifdef MOUSE_ENABLE
  636. /* mouse IN callback hander (a mouse report has made it IN) */
  637. void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
  638. (void)usbp;
  639. (void)ep;
  640. }
  641. void send_mouse(report_mouse_t *report) {
  642. osalSysLock();
  643. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  644. osalSysUnlock();
  645. return;
  646. }
  647. osalSysUnlock();
  648. /* TODO: LUFA manually waits for the endpoint to become ready
  649. * for about 10ms for mouse, kbd, system; 1ms for nkro
  650. * is this really needed?
  651. */
  652. osalSysLock();
  653. usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t));
  654. osalSysUnlock();
  655. }
  656. #else /* MOUSE_ENABLE */
  657. void send_mouse(report_mouse_t *report) {
  658. (void)report;
  659. }
  660. #endif /* MOUSE_ENABLE */
  661. /* ---------------------------------------------------------
  662. * Extrakey functions
  663. * ---------------------------------------------------------
  664. */
  665. #ifdef EXTRAKEY_ENABLE
  666. /* extrakey IN callback hander */
  667. void extra_in_cb(USBDriver *usbp, usbep_t ep) {
  668. /* STUB */
  669. (void)usbp;
  670. (void)ep;
  671. }
  672. static void send_extra_report(uint8_t report_id, uint16_t data) {
  673. osalSysLock();
  674. if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
  675. osalSysUnlock();
  676. return;
  677. }
  678. report_extra_t report = {
  679. .report_id = report_id,
  680. .usage = data
  681. };
  682. usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
  683. osalSysUnlock();
  684. }
  685. void send_system(uint16_t data) {
  686. send_extra_report(REPORT_ID_SYSTEM, data);
  687. }
  688. void send_consumer(uint16_t data) {
  689. send_extra_report(REPORT_ID_CONSUMER, data);
  690. }
  691. #else /* EXTRAKEY_ENABLE */
  692. void send_system(uint16_t data) {
  693. (void)data;
  694. }
  695. void send_consumer(uint16_t data) {
  696. (void)data;
  697. }
  698. #endif /* EXTRAKEY_ENABLE */
  699. /* ---------------------------------------------------------
  700. * Console functions
  701. * ---------------------------------------------------------
  702. */
  703. #ifdef CONSOLE_ENABLE
  704. int8_t sendchar(uint8_t c) {
  705. // The previous implmentation had timeouts, but I think it's better to just slow down
  706. // and make sure that everything is transferred, rather than dropping stuff
  707. return chnWrite(&drivers.console_driver.driver, &c, 1);
  708. }
  709. // Just a dummy function for now, this could be exposed as a weak function
  710. // Or connected to the actual QMK console
  711. static void console_receive( uint8_t *data, uint8_t length ) {
  712. (void)data;
  713. (void)length;
  714. }
  715. void console_task(void) {
  716. uint8_t buffer[CONSOLE_EPSIZE];
  717. size_t size = 0;
  718. do {
  719. size_t size = chnReadTimeout(&drivers.console_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
  720. if (size > 0) {
  721. console_receive(buffer, size);
  722. }
  723. } while(size > 0);
  724. }
  725. #else /* CONSOLE_ENABLE */
  726. int8_t sendchar(uint8_t c) {
  727. (void)c;
  728. return 0;
  729. }
  730. #endif /* CONSOLE_ENABLE */
  731. void sendchar_pf(void *p, char c) {
  732. (void)p;
  733. sendchar((uint8_t)c);
  734. }
  735. #ifdef RAW_ENABLE
  736. void raw_hid_send( uint8_t *data, uint8_t length ) {
  737. // TODO: implement variable size packet
  738. if ( length != RAW_EPSIZE )
  739. {
  740. return;
  741. }
  742. chnWrite(&drivers.raw_driver.driver, data, length);
  743. }
  744. __attribute__ ((weak))
  745. void raw_hid_receive( uint8_t *data, uint8_t length ) {
  746. // Users should #include "raw_hid.h" in their own code
  747. // and implement this function there. Leave this as weak linkage
  748. // so users can opt to not handle data coming in.
  749. }
  750. void raw_hid_task(void) {
  751. uint8_t buffer[RAW_EPSIZE];
  752. size_t size = 0;
  753. do {
  754. size_t size = chnReadTimeout(&drivers.raw_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
  755. if (size > 0) {
  756. raw_hid_receive(buffer, size);
  757. }
  758. } while(size > 0);
  759. }
  760. #endif
  761. #ifdef MIDI_ENABLE
  762. void send_midi_packet(MIDI_EventPacket_t* event) {
  763. chnWrite(&drivers.midi_driver.driver, (uint8_t*)event, sizeof(MIDI_EventPacket_t));
  764. }
  765. bool recv_midi_packet(MIDI_EventPacket_t* const event) {
  766. size_t size = chnReadTimeout(&drivers.midi_driver.driver, (uint8_t*)event, sizeof(MIDI_EventPacket_t), TIME_IMMEDIATE);
  767. return size == sizeof(MIDI_EventPacket_t);
  768. }
  769. #endif
  770. #ifdef VIRTSER_ENABLE
  771. void virtser_send(const uint8_t byte) {
  772. chnWrite(&drivers.serial_driver.driver, &byte, 1);
  773. }
  774. __attribute__ ((weak))
  775. void virtser_recv(uint8_t c)
  776. {
  777. // Ignore by default
  778. }
  779. void virtser_task(void) {
  780. uint8_t numBytesReceived = 0;
  781. uint8_t buffer[16];
  782. do {
  783. numBytesReceived = chnReadTimeout(&drivers.serial_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
  784. for (int i=0;i<numBytesReceived;i++) {
  785. virtser_recv(buffer[i]);
  786. }
  787. } while (numBytesReceived > 0);
  788. }
  789. #endif