c304f4d795c2b7b1bcd1bf2d6a997c14e9d5fc76
[jackhill/qmk/firmware.git] / tmk_core / protocol / chibios / main.c
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
18 #include "ch.h"
19 #include "hal.h"
20
21 #include "usb_main.h"
22
23 /* TMK includes */
24 #include "report.h"
25 #include "host.h"
26 #include "host_driver.h"
27 #include "keyboard.h"
28 #include "action.h"
29 #include "action_util.h"
30 #include "mousekey.h"
31 #include "led.h"
32 #include "sendchar.h"
33 #include "debug.h"
34 #include "printf.h"
35 #include "rgblight_reconfig.h"
36
37 #if (defined(RGB_MIDI) || defined(RGBLIGHT_ANIMATIONS)) && defined(RGBLIGHT_ENABLE)
38 # include "rgblight.h"
39 #endif
40 #ifdef SLEEP_LED_ENABLE
41 # include "sleep_led.h"
42 #endif
43 #ifdef SERIAL_LINK_ENABLE
44 # include "serial_link/system/serial_link.h"
45 #endif
46 #ifdef VISUALIZER_ENABLE
47 # include "visualizer/visualizer.h"
48 #endif
49 #ifdef MIDI_ENABLE
50 # include "qmk_midi.h"
51 #endif
52 #ifdef STM32_EEPROM_ENABLE
53 # include "eeprom_stm32.h"
54 #endif
55 #include "suspend.h"
56 #include "wait.h"
57
58 /* -------------------------
59 * TMK host driver defs
60 * -------------------------
61 */
62
63 /* declarations */
64 uint8_t keyboard_leds(void);
65 void send_keyboard(report_keyboard_t *report);
66 void send_mouse(report_mouse_t *report);
67 void send_system(uint16_t data);
68 void send_consumer(uint16_t data);
69
70 /* host struct */
71 host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
72
73 #ifdef VIRTSER_ENABLE
74 void virtser_task(void);
75 #endif
76
77 #ifdef RAW_ENABLE
78 void raw_hid_task(void);
79 #endif
80
81 #ifdef CONSOLE_ENABLE
82 void console_task(void);
83 #endif
84
85 /* TESTING
86 * Amber LED blinker thread, times are in milliseconds.
87 */
88 /* set this variable to non-zero anywhere to blink once */
89 // static THD_WORKING_AREA(waThread1, 128);
90 // static THD_FUNCTION(Thread1, arg) {
91
92 // (void)arg;
93 // chRegSetThreadName("blinker");
94 // while (true) {
95 // systime_t time;
96
97 // time = USB_DRIVER.state == USB_ACTIVE ? 250 : 500;
98 // palClearLine(LINE_CAPS_LOCK);
99 // chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
100 // palSetLine(LINE_CAPS_LOCK);
101 // chSysPolledDelayX(MS2RTC(STM32_HCLK, time));
102 // }
103 // }
104
105 /* Main thread
106 */
107 int main(void) {
108 /* ChibiOS/RT init */
109 halInit();
110 chSysInit();
111
112 #ifdef STM32_EEPROM_ENABLE
113 EEPROM_Init();
114 #endif
115
116 // TESTING
117 // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
118
119 keyboard_setup();
120
121 /* Init USB */
122 init_usb_driver(&USB_DRIVER);
123
124 /* init printf */
125 init_printf(NULL, sendchar_pf);
126
127 #ifdef MIDI_ENABLE
128 setup_midi();
129 #endif
130
131 #ifdef SERIAL_LINK_ENABLE
132 init_serial_link();
133 #endif
134
135 #ifdef VISUALIZER_ENABLE
136 visualizer_init();
137 #endif
138
139 host_driver_t *driver = NULL;
140
141 /* Wait until the USB or serial link is active */
142 while (true) {
143 #if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE)
144 if (USB_DRIVER.state == USB_ACTIVE) {
145 driver = &chibios_driver;
146 break;
147 }
148 #else
149 driver = &chibios_driver;
150 break;
151 #endif
152 #ifdef SERIAL_LINK_ENABLE
153 if (is_serial_link_connected()) {
154 driver = get_serial_link_driver();
155 break;
156 }
157 serial_link_update();
158 #endif
159 wait_ms(50);
160 }
161
162 /* Do need to wait here!
163 * Otherwise the next print might start a transfer on console EP
164 * before the USB is completely ready, which sometimes causes
165 * HardFaults.
166 */
167 wait_ms(50);
168
169 print("USB configured.\n");
170
171 /* init TMK modules */
172 keyboard_init();
173 host_set_driver(driver);
174
175 #ifdef SLEEP_LED_ENABLE
176 sleep_led_init();
177 #endif
178
179 print("Keyboard start.\n");
180
181 /* Main loop */
182 while (true) {
183 #if !defined(NO_USB_STARTUP_CHECK)
184 if (USB_DRIVER.state == USB_SUSPENDED) {
185 print("[s]");
186 # ifdef VISUALIZER_ENABLE
187 visualizer_suspend();
188 # endif
189 while (USB_DRIVER.state == USB_SUSPENDED) {
190 /* Do this in the suspended state */
191 # ifdef SERIAL_LINK_ENABLE
192 serial_link_update();
193 # endif
194 suspend_power_down(); // on AVR this deep sleeps for 15ms
195 /* Remote wakeup */
196 if (suspend_wakeup_condition()) {
197 usbWakeupHost(&USB_DRIVER);
198 }
199 }
200 /* Woken up */
201 // variables has been already cleared by the wakeup hook
202 send_keyboard_report();
203 # ifdef MOUSEKEY_ENABLE
204 mousekey_send();
205 # endif /* MOUSEKEY_ENABLE */
206
207 # ifdef VISUALIZER_ENABLE
208 visualizer_resume();
209 # endif
210 }
211 #endif
212
213 keyboard_task();
214 #ifdef CONSOLE_ENABLE
215 console_task();
216 #endif
217 #ifdef VIRTSER_ENABLE
218 virtser_task();
219 #endif
220 #ifdef RAW_ENABLE
221 raw_hid_task();
222 #endif
223 #if defined(RGBLIGHT_ANIMATIONS) && defined(RGBLIGHT_ENABLE)
224 rgblight_task();
225 #endif
226 }
227 }