4 Copyright (c) 2016 Fred Sundvik
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:
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
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
25 #include "host_driver.h"
26 #include "serial_link/system/serial_link.h"
28 #include "serial_link/protocol/byte_stuffer.h"
29 #include "serial_link/protocol/transport.h"
30 #include "serial_link/protocol/frame_router.h"
36 static event_source_t new_data_event;
37 static bool serial_link_connected;
38 static bool is_master = false;
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);
46 host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
48 // Define these in your Config.h file
49 #ifndef SERIAL_LINK_BAUD
50 # error "Serial link baud is not set"
53 #ifndef SERIAL_LINK_THREAD_PRIORITY
54 # error "Serial link thread priority not set"
57 static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD};
59 //#define DEBUG_LINK_ERRORS
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);
74 static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
75 #ifdef DEBUG_LINK_ERRORS
76 if (flags & SD_PARITY_ERROR) {
78 print(" Parity error\n");
80 if (flags & SD_FRAMING_ERROR) {
82 print(" Framing error\n");
84 if (flags & SD_OVERRUN_ERROR) {
86 uint32_t size = qSpaceI(&(driver->iqueue));
87 xprintf(" Overrun error, queue size %d\n", size);
89 if (flags & SD_NOISE_ERROR) {
91 print(" Noise error\n");
93 if (flags & SD_BREAK_DETECTED) {
95 print(" Break detected\n");
104 bool is_serial_link_master(void) { return is_master; }
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) {
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;
119 eventflags_t flags1 = 0;
120 eventflags_t flags2 = 0;
122 eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000));
123 if (mask & EVENT_MASK(1)) {
124 flags1 = chEvtGetAndClearFlags(&sd1_listener);
125 print_error("DOWNLINK", flags1, &SD1);
127 if (mask & EVENT_MASK(2)) {
128 flags2 = chEvtGetAndClearFlags(&sd2_listener);
129 print_error("UPLINK", flags2, &SD2);
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);
138 need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
139 need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
144 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
145 if (link == DOWN_LINK) {
146 sdWrite(&SD1, data, size);
148 sdWrite(&SD2, data, size);
152 static systime_t last_update = 0;
155 matrix_row_t rows[MATRIX_ROWS];
158 static matrix_object_t last_matrix = {};
160 SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
161 MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
163 static remote_object_t* remote_objects[] = {
164 REMOTE_OBJECT(serial_link_connected),
165 REMOTE_OBJECT(keyboard_matrix),
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*));
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);
179 void matrix_set_remote(matrix_row_t* rows, uint8_t index);
181 void serial_link_update(void) {
182 if (read_serial_link_connected()) {
183 serial_link_connected = true;
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];
193 systime_t current_time = chVTGetSystemTimeX();
194 systime_t delta = current_time - last_update;
195 if (changed || delta > US2ST(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];
202 end_write_keyboard_matrix();
203 *begin_write_serial_link_connected() = true;
204 end_write_serial_link_connected();
207 matrix_object_t* m = read_keyboard_matrix(0);
209 matrix_set_remote(m->rows, 0);
213 void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
215 bool is_serial_link_connected(void) { return serial_link_connected; }
217 host_driver_t* get_serial_link_driver(void) { return &serial_driver; }
219 // NOTE: The driver does nothing, because the master handles everything
220 uint8_t keyboard_leds(void) { return 0; }
222 void send_keyboard(report_keyboard_t* report) { (void)report; }
224 void send_mouse(report_mouse_t* report) { (void)report; }
226 void send_system(uint16_t data) { (void)data; }
228 void send_consumer(uint16_t data) { (void)data; }