summaryrefslogtreecommitdiff
path: root/tmk_core/protocol/chibios/chibios.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/chibios/chibios.c')
-rw-r--r--tmk_core/protocol/chibios/chibios.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c
new file mode 100644
index 0000000000..78a2e3fcbb
--- /dev/null
+++ b/tmk_core/protocol/chibios/chibios.c
@@ -0,0 +1,255 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+#include <ch.h>
+#include <hal.h>
+
+#include "usb_main.h"
+
+/* TMK includes */
+#include "report.h"
+#include "host.h"
+#include "host_driver.h"
+#include "keyboard.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "led.h"
+#include "sendchar.h"
+#include "debug.h"
+#include "print.h"
+
+#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
+// Change this to be TRUE once we've migrated keyboards to the new init system
+// Remember to change docs/platformdev_chibios_earlyinit.md as well.
+# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE
+#endif
+
+#ifdef SLEEP_LED_ENABLE
+# include "sleep_led.h"
+#endif
+#ifdef SERIAL_LINK_ENABLE
+# include "serial_link/system/serial_link.h"
+#endif
+#ifdef VISUALIZER_ENABLE
+# include "visualizer/visualizer.h"
+#endif
+#ifdef MIDI_ENABLE
+# include "qmk_midi.h"
+#endif
+#include "suspend.h"
+#include "wait.h"
+
+/* -------------------------
+ * TMK host driver defs
+ * -------------------------
+ */
+
+/* declarations */
+uint8_t keyboard_leds(void);
+void send_keyboard(report_keyboard_t *report);
+void send_mouse(report_mouse_t *report);
+void send_system(uint16_t data);
+void send_consumer(uint16_t data);
+void send_digitizer(report_digitizer_t *report);
+
+/* host struct */
+host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
+
+#ifdef VIRTSER_ENABLE
+void virtser_task(void);
+#endif
+
+#ifdef RAW_ENABLE
+void raw_hid_task(void);
+#endif
+
+#ifdef CONSOLE_ENABLE
+void console_task(void);
+#endif
+#ifdef MIDI_ENABLE
+void midi_ep_task(void);
+#endif
+
+/* TESTING
+ * Amber LED blinker thread, times are in milliseconds.
+ */
+/* set this variable to non-zero anywhere to blink once */
+// static THD_WORKING_AREA(waThread1, 128);
+// static THD_FUNCTION(Thread1, arg) {
+
+// (void)arg;
+// chRegSetThreadName("blinker");
+// while (true) {
+// systime_t time;
+
+// time = USB_DRIVER.state == USB_ACTIVE ? 250 : 500;
+// palClearLine(LINE_CAPS_LOCK);
+// chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
+// palSetLine(LINE_CAPS_LOCK);
+// chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
+// }
+// }
+
+/* Early initialisation
+ */
+__attribute__((weak)) void early_hardware_init_pre(void) {
+#if EARLY_INIT_PERFORM_BOOTLOADER_JUMP
+ void enter_bootloader_mode_if_requested(void);
+ enter_bootloader_mode_if_requested();
+#endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP
+}
+
+__attribute__((weak)) void early_hardware_init_post(void) {}
+
+__attribute__((weak)) void board_init(void) {}
+
+// This overrides what's normally in ChibiOS board definitions
+void __early_init(void) {
+ early_hardware_init_pre();
+
+ // This is the renamed equivalent of __early_init in the board.c file
+ void __chibios_override___early_init(void);
+ __chibios_override___early_init();
+
+ early_hardware_init_post();
+}
+
+// This overrides what's normally in ChibiOS board definitions
+void boardInit(void) {
+ // This is the renamed equivalent of boardInit in the board.c file
+ void __chibios_override_boardInit(void);
+ __chibios_override_boardInit();
+
+ board_init();
+}
+
+void protocol_setup(void) {
+ // TESTING
+ // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
+
+ keyboard_setup();
+}
+
+void protocol_init(void) {
+ /* Init USB */
+ usb_event_queue_init();
+ init_usb_driver(&USB_DRIVER);
+
+#ifdef MIDI_ENABLE
+ setup_midi();
+#endif
+
+#ifdef SERIAL_LINK_ENABLE
+ init_serial_link();
+#endif
+
+#ifdef VISUALIZER_ENABLE
+ visualizer_init();
+#endif
+
+ host_driver_t *driver = NULL;
+
+ /* Wait until the USB or serial link is active */
+ while (true) {
+#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE)
+ if (USB_DRIVER.state == USB_ACTIVE) {
+ driver = &chibios_driver;
+ break;
+ }
+#else
+ driver = &chibios_driver;
+ break;
+#endif
+#ifdef SERIAL_LINK_ENABLE
+ if (is_serial_link_connected()) {
+ driver = get_serial_link_driver();
+ break;
+ }
+ serial_link_update();
+#endif
+ wait_ms(50);
+ }
+
+ /* Do need to wait here!
+ * Otherwise the next print might start a transfer on console EP
+ * before the USB is completely ready, which sometimes causes
+ * HardFaults.
+ */
+ wait_ms(50);
+
+ print("USB configured.\n");
+
+ /* init TMK modules */
+ keyboard_init();
+ host_set_driver(driver);
+
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+
+ print("Keyboard start.\n");
+}
+
+void protocol_task(void) {
+ usb_event_queue_task();
+
+#if !defined(NO_USB_STARTUP_CHECK)
+ if (USB_DRIVER.state == USB_SUSPENDED) {
+ print("[s]");
+# ifdef VISUALIZER_ENABLE
+ visualizer_suspend();
+# endif
+ while (USB_DRIVER.state == USB_SUSPENDED) {
+ /* Do this in the suspended state */
+# ifdef SERIAL_LINK_ENABLE
+ serial_link_update();
+# endif
+ suspend_power_down(); // on AVR this deep sleeps for 15ms
+ /* Remote wakeup */
+ if (suspend_wakeup_condition()) {
+ usbWakeupHost(&USB_DRIVER);
+ restart_usb_driver(&USB_DRIVER);
+ }
+ }
+ /* Woken up */
+ // variables has been already cleared by the wakeup hook
+ send_keyboard_report();
+# ifdef MOUSEKEY_ENABLE
+ mousekey_send();
+# endif /* MOUSEKEY_ENABLE */
+
+# ifdef VISUALIZER_ENABLE
+ visualizer_resume();
+# endif
+ }
+#endif
+
+ keyboard_task();
+#ifdef CONSOLE_ENABLE
+ console_task();
+#endif
+#ifdef MIDI_ENABLE
+ midi_ep_task();
+#endif
+#ifdef VIRTSER_ENABLE
+ virtser_task();
+#endif
+#ifdef RAW_ENABLE
+ raw_hid_task();
+#endif
+}