aboutsummaryrefslogtreecommitdiff
path: root/users/drashna/split/transport_sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'users/drashna/split/transport_sync.c')
-rw-r--r--users/drashna/split/transport_sync.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/users/drashna/split/transport_sync.c b/users/drashna/split/transport_sync.c
new file mode 100644
index 000000000..cee3f04c8
--- /dev/null
+++ b/users/drashna/split/transport_sync.c
@@ -0,0 +1,174 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "transport_sync.h"
18#include "transactions.h"
19#include <string.h>
20
21#ifdef CUSTOM_UNICODE_ENABLE
22#include "process_unicode_common.h"
23extern unicode_config_t unicode_config;
24#endif
25#ifdef AUDIO_ENABLE
26# include "audio.h"
27extern audio_config_t audio_config;
28extern bool delayed_tasks_run;
29#endif
30#if defined(POINTING_DEVICE_ENABLE) && defined(KEYBOARD_handwired_tractyl_manuform)
31extern bool tap_toggling;
32#endif
33#ifdef SWAP_HANDS_ENABLE
34extern bool swap_hands;
35#endif
36extern userspace_config_t userspace_config;
37extern bool host_driver_disabled;
38
39uint16_t transport_keymap_config = 0;
40uint32_t transport_userspace_config = 0, transport_user_state = 0;
41
42user_runtime_config_t user_state;
43
44void user_state_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
45 if (initiator2target_buffer_size == sizeof(transport_user_state)) {
46 memcpy(&transport_user_state, initiator2target_buffer, initiator2target_buffer_size);
47 }
48}
49void user_keymap_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
50 if (initiator2target_buffer_size == sizeof(transport_keymap_config)) {
51 memcpy(&transport_keymap_config, initiator2target_buffer, initiator2target_buffer_size);
52 }
53}
54void user_config_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
55 if (initiator2target_buffer_size == sizeof(transport_userspace_config)) {
56 memcpy(&transport_userspace_config, initiator2target_buffer, initiator2target_buffer_size);
57 }
58}
59
60void keyboard_post_init_transport_sync(void) {
61 // Register keyboard state sync split transaction
62 transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_state_sync);
63 transaction_register_rpc(RPC_ID_USER_KEYMAP_SYNC, user_keymap_sync);
64 transaction_register_rpc(RPC_ID_USER_CONFIG_SYNC, user_config_sync);
65}
66
67void user_transport_update(void) {
68 if (is_keyboard_master()) {
69 transport_keymap_config = keymap_config.raw;
70 transport_userspace_config = userspace_config.raw;
71#ifdef AUDIO_ENABLE
72 user_state.audio_enable = is_audio_on();
73 user_state.audio_clicky_enable = is_clicky_on();
74#endif
75#if defined(POINTING_DEVICE_ENABLE) && defined(KEYBOARD_handwired_tractyl_manuform)
76 user_state.tap_toggling = tap_toggling;
77#endif
78#ifdef UNICODE_ENABLE
79 user_state.unicode_mode = unicode_config.input_mode;
80#endif
81#ifdef SWAP_HANDS_ENABLE
82 user_state.swap_hands = swap_hands;
83#endif
84 user_state.host_driver_disabled = host_driver_disabled;
85
86 transport_user_state = user_state.raw;
87 } else {
88 keymap_config.raw = transport_keymap_config;
89 userspace_config.raw = transport_userspace_config;
90 user_state.raw = transport_user_state;
91#ifdef UNICODE_ENABLE
92 unicode_config.input_mode = user_state.unicode_mode;
93#endif
94#if defined(POINTING_DEVICE_ENABLE) && defined(KEYBOARD_handwired_tractyl_manuform)
95 tap_toggling = user_state.tap_toggling;
96#endif
97#ifdef SWAP_HANDS_ENABLE
98 swap_hands = user_state.swap_hands;
99#endif
100 host_driver_disabled = user_state.host_driver_disabled;
101 }
102}
103
104void user_transport_sync(void) {
105 if (is_keyboard_master()) {
106 // Keep track of the last state, so that we can tell if we need to propagate to slave
107 static uint16_t last_keymap = 0;
108 static uint32_t last_config = 0, last_sync[3], last_user_state = 0;
109 bool needs_sync = false;
110
111 // Check if the state values are different
112 if (memcmp(&transport_user_state, &last_user_state, sizeof(transport_user_state))) {
113 needs_sync = true;
114 memcpy(&last_user_state, &transport_user_state, sizeof(transport_user_state));
115 }
116 // Send to slave every 500ms regardless of state change
117 if (timer_elapsed32(last_sync[0]) > 250) {
118 needs_sync = true;
119 }
120
121 // Perform the sync if requested
122 if (needs_sync) {
123 if (transaction_rpc_send(RPC_ID_USER_STATE_SYNC, sizeof(user_state), &user_state)) {
124 last_sync[0] = timer_read32();
125 }
126 needs_sync = false;
127 }
128
129 // Check if the state values are different
130 if (memcmp(&transport_keymap_config, &last_keymap, sizeof(transport_keymap_config))) {
131 needs_sync = true;
132 memcpy(&last_keymap, &transport_keymap_config, sizeof(transport_keymap_config));
133 }
134
135 // Send to slave every 500ms regardless of state change
136 if (timer_elapsed32(last_sync[1]) > 250) {
137 needs_sync = true;
138 }
139
140 // Perform the sync if requested
141 if (needs_sync) {
142 if (transaction_rpc_send(RPC_ID_USER_KEYMAP_SYNC, sizeof(transport_keymap_config), &transport_keymap_config)) {
143 last_sync[1] = timer_read32();
144 }
145 needs_sync = false;
146 }
147
148 // Check if the state values are different
149 if (memcmp(&user_state, &last_config, sizeof(transport_userspace_config))) {
150 needs_sync = true;
151 memcpy(&last_config, &user_state, sizeof(transport_userspace_config));
152 }
153
154 // Send to slave every 500ms regardless of state change
155 if (timer_elapsed32(last_sync[2]) > 250) {
156 needs_sync = true;
157 }
158
159 // Perform the sync if requested
160 if (needs_sync) {
161 if (transaction_rpc_send(RPC_ID_USER_CONFIG_SYNC, sizeof(transport_userspace_config), &transport_userspace_config)) {
162 last_sync[2] = timer_read32();
163 }
164 }
165 }
166}
167
168void housekeeping_task_user(void) {
169 // Update kb_state so we can send to slave
170 user_transport_update();
171
172 // Data sync from master to slave
173 user_transport_sync();
174}