2020 February 29 Breaking Changes Update (#8064)
[jackhill/qmk/firmware.git] / quantum / serial_link / system / serial_link.c
1 /*
2 The MIT License (MIT)
3
4 Copyright (c) 2016 Fred Sundvik
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 #include "report.h"
25 #include "host_driver.h"
26 #include "serial_link/system/serial_link.h"
27 #include "hal.h"
28 #include "serial_link/protocol/byte_stuffer.h"
29 #include "serial_link/protocol/transport.h"
30 #include "serial_link/protocol/frame_router.h"
31 #include "matrix.h"
32 #include <stdbool.h>
33 #include "print.h"
34 #include "config.h"
35
36 static event_source_t new_data_event;
37 static bool serial_link_connected;
38 static bool is_master = false;
39
40 static uint8_t keyboard_leds(void);
41 static void send_keyboard(report_keyboard_t* report);
42 static void send_mouse(report_mouse_t* report);
43 static void send_system(uint16_t data);
44 static void send_consumer(uint16_t data);
45
46 host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
47
48 // Define these in your Config.h file
49 #ifndef SERIAL_LINK_BAUD
50 # error "Serial link baud is not set"
51 #endif
52
53 #ifndef SERIAL_LINK_THREAD_PRIORITY
54 # error "Serial link thread priority not set"
55 #endif
56
57 static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD};
58
59 //#define DEBUG_LINK_ERRORS
60
61 static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) {
62 const uint32_t buffer_size = 16;
63 uint8_t buffer[buffer_size];
64 uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size);
65 uint8_t* current = buffer;
66 uint8_t* end = current + bytes_read;
67 while (current < end) {
68 byte_stuffer_recv_byte(link, *current);
69 current++;
70 }
71 return bytes_read;
72 }
73
74 static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
75 #ifdef DEBUG_LINK_ERRORS
76 if (flags & SD_PARITY_ERROR) {
77 print(str);
78 print(" Parity error\n");
79 }
80 if (flags & SD_FRAMING_ERROR) {
81 print(str);
82 print(" Framing error\n");
83 }
84 if (flags & SD_OVERRUN_ERROR) {
85 print(str);
86 uint32_t size = qSpaceI(&(driver->iqueue));
87 xprintf(" Overrun error, queue size %d\n", size);
88 }
89 if (flags & SD_NOISE_ERROR) {
90 print(str);
91 print(" Noise error\n");
92 }
93 if (flags & SD_BREAK_DETECTED) {
94 print(str);
95 print(" Break detected\n");
96 }
97 #else
98 (void)str;
99 (void)flags;
100 (void)driver;
101 #endif
102 }
103
104 bool is_serial_link_master(void) { return is_master; }
105
106 // TODO: Optimize the stack size, this is probably way too big
107 static THD_WORKING_AREA(serialThreadStack, 1024);
108 static THD_FUNCTION(serialThread, arg) {
109 (void)arg;
110 event_listener_t new_data_listener;
111 event_listener_t sd1_listener;
112 event_listener_t sd2_listener;
113 chEvtRegister(&new_data_event, &new_data_listener, 0);
114 eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED;
115 chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events);
116 chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events);
117 bool need_wait = false;
118 while (true) {
119 eventflags_t flags1 = 0;
120 eventflags_t flags2 = 0;
121 if (need_wait) {
122 eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000));
123 if (mask & EVENT_MASK(1)) {
124 flags1 = chEvtGetAndClearFlags(&sd1_listener);
125 print_error("DOWNLINK", flags1, &SD1);
126 }
127 if (mask & EVENT_MASK(2)) {
128 flags2 = chEvtGetAndClearFlags(&sd2_listener);
129 print_error("UPLINK", flags2, &SD2);
130 }
131 }
132
133 // Always stay as master, even if the USB goes into sleep mode
134 is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE;
135 router_set_master(is_master);
136
137 need_wait = true;
138 need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
139 need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
140 update_transport();
141 }
142 }
143
144 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
145 if (link == DOWN_LINK) {
146 sdWrite(&SD1, data, size);
147 } else {
148 sdWrite(&SD2, data, size);
149 }
150 }
151
152 static systime_t last_update = 0;
153
154 typedef struct {
155 matrix_row_t rows[MATRIX_ROWS];
156 } matrix_object_t;
157
158 static matrix_object_t last_matrix = {};
159
160 SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
161 MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
162
163 static remote_object_t* remote_objects[] = {
164 REMOTE_OBJECT(serial_link_connected),
165 REMOTE_OBJECT(keyboard_matrix),
166 };
167
168 void init_serial_link(void) {
169 serial_link_connected = false;
170 init_serial_link_hal();
171 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
172 init_byte_stuffer();
173 sdStart(&SD1, &config);
174 sdStart(&SD2, &config);
175 chEvtObjectInit(&new_data_event);
176 (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL);
177 }
178
179 void matrix_set_remote(matrix_row_t* rows, uint8_t index);
180
181 void serial_link_update(void) {
182 if (read_serial_link_connected()) {
183 serial_link_connected = true;
184 }
185
186 matrix_object_t matrix;
187 bool changed = false;
188 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
189 matrix.rows[i] = matrix_get_row(i);
190 changed |= matrix.rows[i] != last_matrix.rows[i];
191 }
192
193 systime_t current_time = chVTGetSystemTimeX();
194 systime_t delta = current_time - last_update;
195 if (changed || delta > TIME_US2I(5000)) {
196 last_update = current_time;
197 last_matrix = matrix;
198 matrix_object_t* m = begin_write_keyboard_matrix();
199 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
200 m->rows[i] = matrix.rows[i];
201 }
202 end_write_keyboard_matrix();
203 *begin_write_serial_link_connected() = true;
204 end_write_serial_link_connected();
205 }
206
207 matrix_object_t* m = read_keyboard_matrix(0);
208 if (m) {
209 matrix_set_remote(m->rows, 0);
210 }
211 }
212
213 void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
214
215 bool is_serial_link_connected(void) { return serial_link_connected; }
216
217 host_driver_t* get_serial_link_driver(void) { return &serial_driver; }
218
219 // NOTE: The driver does nothing, because the master handles everything
220 uint8_t keyboard_leds(void) { return 0; }
221
222 void send_keyboard(report_keyboard_t* report) { (void)report; }
223
224 void send_mouse(report_mouse_t* report) { (void)report; }
225
226 void send_system(uint16_t data) { (void)data; }
227
228 void send_consumer(uint16_t data) { (void)data; }