usb_main.c 27 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. #include "usb_driver.h"
  30. #ifdef NKRO_ENABLE
  31. #include "keycode_config.h"
  32. extern keymap_config_t keymap_config;
  33. #endif
  34. /* ---------------------------------------------------------
  35. * Global interface variables and declarations
  36. * ---------------------------------------------------------
  37. */
  38. #ifndef usb_lld_connect_bus
  39. #define usb_lld_connect_bus(usbp)
  40. #endif
  41. #ifndef usb_lld_disconnect_bus
  42. #define usb_lld_disconnect_bus(usbp)
  43. #endif
  44. uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
  45. uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
  46. uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
  47. volatile uint16_t keyboard_idle_count = 0;
  48. static virtual_timer_t keyboard_idle_timer;
  49. static void keyboard_idle_timer_cb(void *arg);
  50. report_keyboard_t keyboard_report_sent = {{0}};
  51. #ifdef MOUSE_ENABLE
  52. report_mouse_t mouse_report_blank = {0};
  53. #endif /* MOUSE_ENABLE */
  54. #ifdef EXTRAKEY_ENABLE
  55. uint8_t extra_report_blank[3] = {0};
  56. #endif /* EXTRAKEY_ENABLE */
  57. /* ---------------------------------------------------------
  58. * Descriptors and USB driver objects
  59. * ---------------------------------------------------------
  60. */
  61. /* HID specific constants */
  62. #define HID_GET_REPORT 0x01
  63. #define HID_GET_IDLE 0x02
  64. #define HID_GET_PROTOCOL 0x03
  65. #define HID_SET_REPORT 0x09
  66. #define HID_SET_IDLE 0x0A
  67. #define HID_SET_PROTOCOL 0x0B
  68. /*
  69. * Handles the GET_DESCRIPTOR callback
  70. *
  71. * Returns the proper descriptor
  72. */
  73. static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
  74. (void)usbp;
  75. static USBDescriptor desc;
  76. uint16_t wValue = ((uint16_t)dtype << 8) | dindex;
  77. desc.ud_string = NULL;
  78. desc.ud_size = get_usb_descriptor(wValue, wIndex, (const void** const)&desc.ud_string);
  79. if (desc.ud_string == NULL)
  80. return NULL;
  81. else
  82. return &desc;
  83. }
  84. /* keyboard endpoint state structure */
  85. static USBInEndpointState kbd_ep_state;
  86. /* keyboard endpoint initialization structure (IN) */
  87. static const USBEndpointConfig kbd_ep_config = {
  88. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  89. NULL, /* SETUP packet notification callback */
  90. kbd_in_cb, /* IN notification callback */
  91. NULL, /* OUT notification callback */
  92. KEYBOARD_EPSIZE, /* IN maximum packet size */
  93. 0, /* OUT maximum packet size */
  94. &kbd_ep_state, /* IN Endpoint state */
  95. NULL, /* OUT endpoint state */
  96. 2, /* IN multiplier */
  97. NULL /* SETUP buffer (not a SETUP endpoint) */
  98. };
  99. #ifdef MOUSE_ENABLE
  100. /* mouse endpoint state structure */
  101. static USBInEndpointState mouse_ep_state;
  102. /* mouse endpoint initialization structure (IN) */
  103. static const USBEndpointConfig mouse_ep_config = {
  104. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  105. NULL, /* SETUP packet notification callback */
  106. mouse_in_cb, /* IN notification callback */
  107. NULL, /* OUT notification callback */
  108. MOUSE_EPSIZE, /* IN maximum packet size */
  109. 0, /* OUT maximum packet size */
  110. &mouse_ep_state, /* IN Endpoint state */
  111. NULL, /* OUT endpoint state */
  112. 2, /* IN multiplier */
  113. NULL /* SETUP buffer (not a SETUP endpoint) */
  114. };
  115. #endif /* MOUSE_ENABLE */
  116. #ifdef EXTRAKEY_ENABLE
  117. /* extrakey endpoint state structure */
  118. static USBInEndpointState extra_ep_state;
  119. /* extrakey endpoint initialization structure (IN) */
  120. static const USBEndpointConfig extra_ep_config = {
  121. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  122. NULL, /* SETUP packet notification callback */
  123. extra_in_cb, /* IN notification callback */
  124. NULL, /* OUT notification callback */
  125. EXTRAKEY_EPSIZE, /* IN maximum packet size */
  126. 0, /* OUT maximum packet size */
  127. &extra_ep_state, /* IN Endpoint state */
  128. NULL, /* OUT endpoint state */
  129. 2, /* IN multiplier */
  130. NULL /* SETUP buffer (not a SETUP endpoint) */
  131. };
  132. #endif /* EXTRAKEY_ENABLE */
  133. #ifdef NKRO_ENABLE
  134. /* nkro endpoint state structure */
  135. static USBInEndpointState nkro_ep_state;
  136. /* nkro endpoint initialization structure (IN) */
  137. static const USBEndpointConfig nkro_ep_config = {
  138. USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
  139. NULL, /* SETUP packet notification callback */
  140. nkro_in_cb, /* IN notification callback */
  141. NULL, /* OUT notification callback */
  142. NKRO_EPSIZE, /* IN maximum packet size */
  143. 0, /* OUT maximum packet size */
  144. &nkro_ep_state, /* IN Endpoint state */
  145. NULL, /* OUT endpoint state */
  146. 2, /* IN multiplier */
  147. NULL /* SETUP buffer (not a SETUP endpoint) */
  148. };
  149. #endif /* NKRO_ENABLE */
  150. typedef struct {
  151. size_t queue_capacity_in;
  152. size_t queue_capacity_out;
  153. USBInEndpointState in_ep_state;
  154. USBOutEndpointState out_ep_state;
  155. USBInEndpointState int_ep_state;
  156. USBEndpointConfig in_ep_config;
  157. USBEndpointConfig out_ep_config;
  158. USBEndpointConfig int_ep_config;
  159. const QMKUSBConfig config;
  160. QMKUSBDriver driver;
  161. } usb_driver_config_t;
  162. #define QMK_USB_DRIVER_CONFIG(stream, notification, fixedsize) { \
  163. .queue_capacity_in = stream##_IN_CAPACITY, \
  164. .queue_capacity_out = stream##_OUT_CAPACITY, \
  165. .in_ep_config = { \
  166. .ep_mode = stream##_IN_MODE, \
  167. .setup_cb = NULL, \
  168. .in_cb = qmkusbDataTransmitted, \
  169. .out_cb = NULL, \
  170. .in_maxsize = stream##_EPSIZE, \
  171. .out_maxsize = 0, \
  172. /* The pointer to the states will be filled during initialization */ \
  173. .in_state = NULL, \
  174. .out_state = NULL, \
  175. .ep_buffers = 2, \
  176. .setup_buf = NULL \
  177. }, \
  178. .out_ep_config = { \
  179. .ep_mode = stream##_OUT_MODE, \
  180. .setup_cb = NULL, \
  181. .in_cb = NULL, \
  182. .out_cb = qmkusbDataReceived, \
  183. .in_maxsize = 0, \
  184. .out_maxsize = stream##_EPSIZE, \
  185. /* The pointer to the states will be filled during initialization */ \
  186. .in_state = NULL, \
  187. .out_state = NULL, \
  188. .ep_buffers = 2, \
  189. .setup_buf = NULL, \
  190. }, \
  191. .int_ep_config = { \
  192. .ep_mode = USB_EP_MODE_TYPE_INTR, \
  193. .setup_cb = NULL, \
  194. .in_cb = qmkusbInterruptTransmitted, \
  195. .out_cb = NULL, \
  196. .in_maxsize = CDC_NOTIFICATION_EPSIZE, \
  197. .out_maxsize = 0, \
  198. /* The pointer to the states will be filled during initialization */ \
  199. .in_state = NULL, \
  200. .out_state = NULL, \
  201. .ep_buffers = 2, \
  202. .setup_buf = NULL, \
  203. }, \
  204. .config = { \
  205. .usbp = &USB_DRIVER, \
  206. .bulk_in = stream##_IN_EPNUM, \
  207. .bulk_out = stream##_OUT_EPNUM, \
  208. .int_in = notification, \
  209. .in_buffers = stream##_IN_CAPACITY, \
  210. .out_buffers = stream##_OUT_CAPACITY, \
  211. .in_size = stream##_EPSIZE, \
  212. .out_size = stream##_EPSIZE, \
  213. .fixed_size = fixedsize, \
  214. .ib = (uint8_t[BQ_BUFFER_SIZE(stream##_IN_CAPACITY, stream##_EPSIZE)]) {}, \
  215. .ob = (uint8_t[BQ_BUFFER_SIZE(stream##_OUT_CAPACITY,stream##_EPSIZE)]) {}, \
  216. } \
  217. }
  218. typedef struct {
  219. union {
  220. struct {
  221. #ifdef CONSOLE_ENABLE
  222. usb_driver_config_t console_driver;
  223. #endif
  224. #ifdef RAW_ENABLE
  225. usb_driver_config_t raw_driver;
  226. #endif
  227. #ifdef MIDI_ENABLE
  228. usb_driver_config_t midi_driver;
  229. #endif
  230. #ifdef VIRTSER_ENABLE
  231. usb_driver_config_t serial_driver;
  232. #endif
  233. };
  234. usb_driver_config_t array[0];
  235. };
  236. } usb_driver_configs_t;
  237. static usb_driver_configs_t drivers = {
  238. #ifdef CONSOLE_ENABLE
  239. #define CONSOLE_IN_CAPACITY 4
  240. #define CONSOLE_OUT_CAPACITY 4
  241. #define CONSOLE_IN_MODE USB_EP_MODE_TYPE_INTR
  242. #define CONSOLE_OUT_MODE USB_EP_MODE_TYPE_INTR
  243. .console_driver = QMK_USB_DRIVER_CONFIG(CONSOLE, 0, true),
  244. #endif
  245. #ifdef RAW_ENABLE
  246. #define RAW_IN_CAPACITY 4
  247. #define RAW_OUT_CAPACITY 4
  248. #define RAW_IN_MODE USB_EP_MODE_TYPE_INTR
  249. #define RAW_OUT_MODE USB_EP_MODE_TYPE_INTR
  250. .raw_driver = QMK_USB_DRIVER_CONFIG(RAW, 0, false),
  251. #endif
  252. #ifdef MIDI_ENABLE
  253. #define MIDI_STREAM_IN_CAPACITY 4
  254. #define MIDI_STREAM_OUT_CAPACITY 4
  255. #define MIDI_STREAM_IN_MODE USB_EP_MODE_TYPE_BULK
  256. #define MIDI_STREAM_OUT_MODE USB_EP_MODE_TYPE_BULK
  257. .midi_driver = QMK_USB_DRIVER_CONFIG(MIDI_STREAM, 0, false),
  258. #endif
  259. #ifdef VIRTSER_ENABLE
  260. #define CDC_IN_CAPACITY 4
  261. #define CDC_OUT_CAPACITY 4
  262. #define CDC_IN_MODE USB_EP_MODE_TYPE_BULK
  263. #define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK
  264. .serial_driver = QMK_USB_DRIVER_CONFIG(CDC, CDC_NOTIFICATION_EPNUM, false),
  265. #endif
  266. };
  267. #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
  268. /* ---------------------------------------------------------
  269. * USB driver functions
  270. * ---------------------------------------------------------
  271. */
  272. /* Handles the USB driver global events
  273. * TODO: maybe disable some things when connection is lost? */
  274. static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
  275. switch(event) {
  276. case USB_EVENT_ADDRESS:
  277. return;
  278. case USB_EVENT_CONFIGURED:
  279. osalSysLockFromISR();
  280. /* Enable the endpoints specified into the configuration. */
  281. usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
  282. #ifdef MOUSE_ENABLE
  283. usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
  284. #endif /* MOUSE_ENABLE */
  285. #ifdef EXTRAKEY_ENABLE
  286. usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config);
  287. #endif /* EXTRAKEY_ENABLE */
  288. #ifdef NKRO_ENABLE
  289. usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
  290. #endif /* NKRO_ENABLE */
  291. for (int i=0;i<NUM_USB_DRIVERS;i++) {
  292. usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
  293. usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
  294. if (drivers.array[i].config.int_in) {
  295. usbInitEndpointI(usbp, drivers.array[i].config.int_in, &drivers.array[i].int_ep_config);
  296. }
  297. qmkusbConfigureHookI(&drivers.array[i].driver);
  298. }
  299. osalSysUnlockFromISR();
  300. return;
  301. case USB_EVENT_SUSPEND:
  302. #ifdef SLEEP_LED_ENABLE
  303. sleep_led_enable();
  304. #endif /* SLEEP_LED_ENABLE */
  305. /* Falls into.*/
  306. case USB_EVENT_UNCONFIGURED:
  307. /* Falls into.*/
  308. case USB_EVENT_RESET:
  309. for (int i=0;i<NUM_USB_DRIVERS;i++) {
  310. chSysLockFromISR();
  311. /* Disconnection event on suspend.*/
  312. qmkusbSuspendHookI(&drivers.array[i].driver);
  313. chSysUnlockFromISR();
  314. }
  315. return;
  316. case USB_EVENT_WAKEUP:
  317. //TODO: from ISR! print("[W]");
  318. for (int i=0;i<NUM_USB_DRIVERS;i++) {
  319. chSysLockFromISR();
  320. /* Disconnection event on suspend.*/
  321. qmkusbWakeupHookI(&drivers.array[i].driver);
  322. chSysUnlockFromISR();
  323. }
  324. suspend_wakeup_init();
  325. #ifdef SLEEP_LED_ENABLE
  326. sleep_led_disable();
  327. // NOTE: converters may not accept this
  328. led_set(host_keyboard_leds());
  329. #endif /* SLEEP_LED_ENABLE */
  330. return;
  331. case USB_EVENT_STALLED:
  332. return;
  333. }
  334. }
  335. /* Function used locally in os/hal/src/usb.c for getting descriptors
  336. * need it here for HID descriptor */
  337. static uint16_t get_hword(uint8_t *p) {
  338. uint16_t hw;
  339. hw = (uint16_t)*p++;
  340. hw |= (uint16_t)*p << 8U;
  341. return hw;
  342. }
  343. /*
  344. * Appendix G: HID Request Support Requirements
  345. *
  346. * The following table enumerates the requests that need to be supported by various types of HID class devices.
  347. * Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
  348. * ------------------------------------------------------------------------------------------
  349. * Boot Mouse Required Optional Optional Optional Required Required
  350. * Non-Boot Mouse Required Optional Optional Optional Optional Optional
  351. * Boot Keyboard Required Optional Required Required Required Required
  352. * Non-Boot Keybrd Required Optional Required Required Optional Optional
  353. * Other Device Required Optional Optional Optional Optional Optional
  354. */
  355. /* Callback for SETUP request on the endpoint 0 (control) */
  356. static bool usb_request_hook_cb(USBDriver *usbp) {
  357. const USBDescriptor *dp;
  358. /* usbp->setup fields:
  359. * 0: bmRequestType (bitmask)
  360. * 1: bRequest
  361. * 2,3: (LSB,MSB) wValue
  362. * 4,5: (LSB,MSB) wIndex
  363. * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
  364. /* Handle HID class specific requests */
  365. if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
  366. ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
  367. switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
  368. case USB_RTYPE_DIR_DEV2HOST:
  369. switch(usbp->setup[1]) { /* bRequest */
  370. case HID_GET_REPORT:
  371. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
  372. case KEYBOARD_INTERFACE:
  373. #ifdef NKRO_ENABLE
  374. case NKRO_INTERFACE:
  375. #endif /* NKRO_ENABLE */
  376. usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
  377. return TRUE;
  378. break;
  379. #ifdef MOUSE_ENABLE
  380. case MOUSE_INTERFACE:
  381. usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
  382. return TRUE;
  383. break;
  384. #endif /* MOUSE_ENABLE */
  385. #ifdef EXTRAKEY_ENABLE
  386. case EXTRAKEY_INTERFACE:
  387. if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
  388. switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
  389. case REPORT_ID_SYSTEM:
  390. extra_report_blank[0] = REPORT_ID_SYSTEM;
  391. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  392. return TRUE;
  393. break;
  394. case REPORT_ID_CONSUMER:
  395. extra_report_blank[0] = REPORT_ID_CONSUMER;
  396. usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
  397. return TRUE;
  398. break;
  399. default:
  400. return FALSE;
  401. }
  402. } else {
  403. return FALSE;
  404. }
  405. break;
  406. #endif /* EXTRAKEY_ENABLE */
  407. default:
  408. usbSetupTransfer(usbp, NULL, 0, NULL);
  409. return TRUE;
  410. break;
  411. }
  412. break;
  413. case HID_GET_PROTOCOL:
  414. if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  415. usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
  416. return TRUE;
  417. }
  418. break;
  419. case HID_GET_IDLE:
  420. usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
  421. return TRUE;
  422. break;
  423. }
  424. break;
  425. case USB_RTYPE_DIR_HOST2DEV:
  426. switch(usbp->setup[1]) { /* bRequest */
  427. case HID_SET_REPORT:
  428. switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
  429. case KEYBOARD_INTERFACE:
  430. #ifdef NKRO_ENABLE
  431. case NKRO_INTERFACE:
  432. #endif /* NKRO_ENABLE */
  433. /* keyboard_led_stats = <read byte from next OUT report>
  434. * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
  435. usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
  436. return TRUE;
  437. break;
  438. }
  439. break;
  440. case HID_SET_PROTOCOL:
  441. if((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
  442. keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
  443. #ifdef NKRO_ENABLE
  444. keymap_config.nkro = !!keyboard_protocol;
  445. if(!keymap_config.nkro && keyboard_idle) {
  446. #else /* NKRO_ENABLE */
  447. if(keyboard_idle) {
  448. #endif /* NKRO_ENABLE */
  449. /* arm the idle timer if boot protocol & idle */
  450. osalSysLockFromISR();
  451. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  452. osalSysUnlockFromISR();
  453. }
  454. }
  455. usbSetupTransfer(usbp, NULL, 0, NULL);
  456. return TRUE;
  457. break;
  458. case HID_SET_IDLE:
  459. keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
  460. /* arm the timer */
  461. #ifdef NKRO_ENABLE
  462. if(!keymap_config.nkro && keyboard_idle) {
  463. #else /* NKRO_ENABLE */
  464. if(keyboard_idle) {
  465. #endif /* NKRO_ENABLE */
  466. osalSysLockFromISR();
  467. chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  468. osalSysUnlockFromISR();
  469. }
  470. usbSetupTransfer(usbp, NULL, 0, NULL);
  471. return TRUE;
  472. break;
  473. }
  474. break;
  475. }
  476. }
  477. /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
  478. if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
  479. dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
  480. if(dp == NULL)
  481. return FALSE;
  482. usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
  483. return TRUE;
  484. }
  485. for (int i=0;i<NUM_USB_DRIVERS;i++) {
  486. if (drivers.array[i].config.int_in) {
  487. // NOTE: Assumes that we only have one serial driver
  488. return qmkusbRequestsHook(usbp);
  489. }
  490. }
  491. return FALSE;
  492. }
  493. /* Start-of-frame callback */
  494. static void usb_sof_cb(USBDriver *usbp) {
  495. kbd_sof_cb(usbp);
  496. osalSysLockFromISR();
  497. for (int i=0; i<NUM_USB_DRIVERS;i++) {
  498. qmkusbSOFHookI(&drivers.array[i].driver);
  499. }
  500. osalSysUnlockFromISR();
  501. }
  502. /* USB driver configuration */
  503. static const USBConfig usbcfg = {
  504. usb_event_cb, /* USB events callback */
  505. usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
  506. usb_request_hook_cb, /* Requests hook callback */
  507. usb_sof_cb /* Start Of Frame callback */
  508. };
  509. /*
  510. * Initialize the USB driver
  511. */
  512. void init_usb_driver(USBDriver *usbp) {
  513. for (int i=0; i<NUM_USB_DRIVERS;i++) {
  514. QMKUSBDriver* driver = &drivers.array[i].driver;
  515. drivers.array[i].in_ep_config.in_state = &drivers.array[i].in_ep_state;
  516. drivers.array[i].out_ep_config.out_state = &drivers.array[i].out_ep_state;
  517. drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state;
  518. qmkusbObjectInit(driver, &drivers.array[i].config);
  519. qmkusbStart(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