diff options
Diffstat (limited to 'quantum/split_common/transactions.c')
| -rw-r--r-- | quantum/split_common/transactions.c | 723 |
1 files changed, 723 insertions, 0 deletions
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c new file mode 100644 index 000000000..fd676f072 --- /dev/null +++ b/quantum/split_common/transactions.c | |||
| @@ -0,0 +1,723 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 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 <string.h> | ||
| 18 | #include <stddef.h> | ||
| 19 | |||
| 20 | #include "crc.h" | ||
| 21 | #include "debug.h" | ||
| 22 | #include "matrix.h" | ||
| 23 | #include "quantum.h" | ||
| 24 | #include "transactions.h" | ||
| 25 | #include "transport.h" | ||
| 26 | #include "split_util.h" | ||
| 27 | #include "transaction_id_define.h" | ||
| 28 | |||
| 29 | #define SYNC_TIMER_OFFSET 2 | ||
| 30 | |||
| 31 | #ifndef FORCED_SYNC_THROTTLE_MS | ||
| 32 | # define FORCED_SYNC_THROTTLE_MS 100 | ||
| 33 | #endif // FORCED_SYNC_THROTTLE_MS | ||
| 34 | |||
| 35 | #define sizeof_member(type, member) sizeof(((type *)NULL)->member) | ||
| 36 | |||
| 37 | #define trans_initiator2target_initializer_cb(member, cb) \ | ||
| 38 | { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb } | ||
| 39 | #define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL) | ||
| 40 | |||
| 41 | #define trans_target2initiator_initializer_cb(member, cb) \ | ||
| 42 | { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb } | ||
| 43 | #define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL) | ||
| 44 | |||
| 45 | #define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0) | ||
| 46 | #define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length) | ||
| 47 | |||
| 48 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 49 | // Forward-declare the RPC callback handlers | ||
| 50 | void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); | ||
| 51 | void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); | ||
| 52 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 53 | |||
| 54 | //////////////////////////////////////////////////// | ||
| 55 | // Helpers | ||
| 56 | |||
| 57 | static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) { | ||
| 58 | int num_retries = is_transport_connected() ? 10 : 1; | ||
| 59 | for (int iter = 1; iter <= num_retries; ++iter) { | ||
| 60 | if (iter > 1) { | ||
| 61 | for (int i = 0; i < iter * iter; ++i) { | ||
| 62 | wait_us(10); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | bool this_okay = true; | ||
| 66 | ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; | ||
| 67 | if (this_okay) return true; | ||
| 68 | } | ||
| 69 | dprintf("Failed to execute %s\n", prefix); | ||
| 70 | return false; | ||
| 71 | } | ||
| 72 | |||
| 73 | #define TRANSACTION_HANDLER_MASTER(prefix) \ | ||
| 74 | do { \ | ||
| 75 | if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \ | ||
| 76 | } while (0) | ||
| 77 | |||
| 78 | #define TRANSACTION_HANDLER_SLAVE(prefix) \ | ||
| 79 | do { \ | ||
| 80 | ATOMIC_BLOCK_FORCEON { prefix##_handlers_slave(master_matrix, slave_matrix); }; \ | ||
| 81 | } while (0) | ||
| 82 | |||
| 83 | inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) { | ||
| 84 | uint8_t curr_checksum; | ||
| 85 | bool okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum)); | ||
| 86 | if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) { | ||
| 87 | okay &= transport_read(trans_id_retrieve, destination, length); | ||
| 88 | okay &= curr_checksum == crc8(equiv_shmem, length); | ||
| 89 | if (okay) { | ||
| 90 | *last_update = timer_read32(); | ||
| 91 | } | ||
| 92 | } else { | ||
| 93 | memcpy(destination, equiv_shmem, length); | ||
| 94 | } | ||
| 95 | return okay; | ||
| 96 | } | ||
| 97 | |||
| 98 | inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) { | ||
| 99 | bool okay = true; | ||
| 100 | if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) { | ||
| 101 | okay &= transport_write(trans_id, source, length); | ||
| 102 | if (okay) { | ||
| 103 | *last_update = timer_read32(); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | return okay; | ||
| 107 | } | ||
| 108 | |||
| 109 | inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) { | ||
| 110 | // Just run a memcmp to compare the source and equivalent shmem location | ||
| 111 | return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length); | ||
| 112 | } | ||
| 113 | |||
| 114 | //////////////////////////////////////////////////// | ||
| 115 | // Slave matrix | ||
| 116 | |||
| 117 | static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 118 | static uint32_t last_update = 0; | ||
| 119 | static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0}; // last successfully-read matrix, so we can replicate if there are checksum errors | ||
| 120 | matrix_row_t temp_matrix[(MATRIX_ROWS) / 2]; // holding area while we test whether or not checksum is correct | ||
| 121 | |||
| 122 | bool okay = read_if_checksum_mismatch(GET_SLAVE_MATRIX_CHECKSUM, GET_SLAVE_MATRIX_DATA, &last_update, temp_matrix, split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); | ||
| 123 | if (okay) { | ||
| 124 | // Checksum matches the received data, save as the last matrix state | ||
| 125 | memcpy(last_matrix, temp_matrix, sizeof(temp_matrix)); | ||
| 126 | } | ||
| 127 | // Copy out the last-known-good matrix state to the slave matrix | ||
| 128 | memcpy(slave_matrix, last_matrix, sizeof(last_matrix)); | ||
| 129 | return okay; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 133 | memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix)); | ||
| 134 | split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); | ||
| 135 | } | ||
| 136 | |||
| 137 | // clang-format off | ||
| 138 | #define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix) | ||
| 139 | #define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix) | ||
| 140 | #define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ | ||
| 141 | [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ | ||
| 142 | [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix), | ||
| 143 | // clang-format on | ||
| 144 | |||
| 145 | //////////////////////////////////////////////////// | ||
| 146 | // Master matrix | ||
| 147 | |||
| 148 | #ifdef SPLIT_TRANSPORT_MIRROR | ||
| 149 | |||
| 150 | static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 151 | static uint32_t last_update = 0; | ||
| 152 | return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 156 | // Always copy to the master matrix | ||
| 157 | memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); | ||
| 158 | } | ||
| 159 | |||
| 160 | # define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix) | ||
| 161 | # define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix) | ||
| 162 | # define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), | ||
| 163 | |||
| 164 | #else // SPLIT_TRANSPORT_MIRROR | ||
| 165 | |||
| 166 | # define TRANSACTIONS_MASTER_MATRIX_MASTER() | ||
| 167 | # define TRANSACTIONS_MASTER_MATRIX_SLAVE() | ||
| 168 | # define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS | ||
| 169 | |||
| 170 | #endif // SPLIT_TRANSPORT_MIRROR | ||
| 171 | |||
| 172 | //////////////////////////////////////////////////// | ||
| 173 | // Encoders | ||
| 174 | |||
| 175 | #ifdef ENCODER_ENABLE | ||
| 176 | |||
| 177 | static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 178 | static uint32_t last_update = 0; | ||
| 179 | uint8_t temp_state[NUMBER_OF_ENCODERS]; | ||
| 180 | |||
| 181 | bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); | ||
| 182 | if (okay) encoder_update_raw(temp_state); | ||
| 183 | return okay; | ||
| 184 | } | ||
| 185 | |||
| 186 | static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 187 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | ||
| 188 | encoder_state_raw(encoder_state); | ||
| 189 | // Always prepare the encoder state for read. | ||
| 190 | memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); | ||
| 191 | // Now update the checksum given that the encoders has been written to | ||
| 192 | split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state)); | ||
| 193 | } | ||
| 194 | |||
| 195 | // clang-format off | ||
| 196 | # define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder) | ||
| 197 | # define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder) | ||
| 198 | # define TRANSACTIONS_ENCODERS_REGISTRATIONS \ | ||
| 199 | [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ | ||
| 200 | [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state), | ||
| 201 | // clang-format on | ||
| 202 | |||
| 203 | #else // ENCODER_ENABLE | ||
| 204 | |||
| 205 | # define TRANSACTIONS_ENCODERS_MASTER() | ||
| 206 | # define TRANSACTIONS_ENCODERS_SLAVE() | ||
| 207 | # define TRANSACTIONS_ENCODERS_REGISTRATIONS | ||
| 208 | |||
| 209 | #endif // ENCODER_ENABLE | ||
| 210 | |||
| 211 | //////////////////////////////////////////////////// | ||
| 212 | // Sync timer | ||
| 213 | |||
| 214 | #ifndef DISABLE_SYNC_TIMER | ||
| 215 | |||
| 216 | static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 217 | static uint32_t last_update = 0; | ||
| 218 | |||
| 219 | bool okay = true; | ||
| 220 | if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) { | ||
| 221 | uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; | ||
| 222 | okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer)); | ||
| 223 | if (okay) { | ||
| 224 | last_update = timer_read32(); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | return okay; | ||
| 228 | } | ||
| 229 | |||
| 230 | static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 231 | static uint32_t last_sync_timer = 0; | ||
| 232 | if (last_sync_timer != split_shmem->sync_timer) { | ||
| 233 | last_sync_timer = split_shmem->sync_timer; | ||
| 234 | sync_timer_update(last_sync_timer); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | # define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer) | ||
| 239 | # define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer) | ||
| 240 | # define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), | ||
| 241 | |||
| 242 | #else // DISABLE_SYNC_TIMER | ||
| 243 | |||
| 244 | # define TRANSACTIONS_SYNC_TIMER_MASTER() | ||
| 245 | # define TRANSACTIONS_SYNC_TIMER_SLAVE() | ||
| 246 | # define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS | ||
| 247 | |||
| 248 | #endif // DISABLE_SYNC_TIMER | ||
| 249 | |||
| 250 | //////////////////////////////////////////////////// | ||
| 251 | // Layer state | ||
| 252 | |||
| 253 | #if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 254 | |||
| 255 | static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 256 | static uint32_t last_layer_state_update = 0; | ||
| 257 | static uint32_t last_default_layer_state_update = 0; | ||
| 258 | |||
| 259 | bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state)); | ||
| 260 | if (okay) { | ||
| 261 | okay &= send_if_condition(PUT_DEFAULT_LAYER_STATE, &last_default_layer_state_update, (default_layer_state != split_shmem->layers.default_layer_state), &default_layer_state, sizeof(default_layer_state)); | ||
| 262 | } | ||
| 263 | return okay; | ||
| 264 | } | ||
| 265 | |||
| 266 | static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 267 | layer_state = split_shmem->layers.layer_state; | ||
| 268 | default_layer_state = split_shmem->layers.default_layer_state; | ||
| 269 | } | ||
| 270 | |||
| 271 | // clang-format off | ||
| 272 | # define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state) | ||
| 273 | # define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state) | ||
| 274 | # define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ | ||
| 275 | [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \ | ||
| 276 | [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), | ||
| 277 | // clang-format on | ||
| 278 | |||
| 279 | #else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 280 | |||
| 281 | # define TRANSACTIONS_LAYER_STATE_MASTER() | ||
| 282 | # define TRANSACTIONS_LAYER_STATE_SLAVE() | ||
| 283 | # define TRANSACTIONS_LAYER_STATE_REGISTRATIONS | ||
| 284 | |||
| 285 | #endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 286 | |||
| 287 | //////////////////////////////////////////////////// | ||
| 288 | // LED state | ||
| 289 | |||
| 290 | #ifdef SPLIT_LED_STATE_ENABLE | ||
| 291 | |||
| 292 | static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 293 | static uint32_t last_update = 0; | ||
| 294 | uint8_t led_state = host_keyboard_leds(); | ||
| 295 | return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state)); | ||
| 296 | } | ||
| 297 | |||
| 298 | static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 299 | void set_split_host_keyboard_leds(uint8_t led_state); | ||
| 300 | set_split_host_keyboard_leds(split_shmem->led_state); | ||
| 301 | } | ||
| 302 | |||
| 303 | # define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state) | ||
| 304 | # define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state) | ||
| 305 | # define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), | ||
| 306 | |||
| 307 | #else // SPLIT_LED_STATE_ENABLE | ||
| 308 | |||
| 309 | # define TRANSACTIONS_LED_STATE_MASTER() | ||
| 310 | # define TRANSACTIONS_LED_STATE_SLAVE() | ||
| 311 | # define TRANSACTIONS_LED_STATE_REGISTRATIONS | ||
| 312 | |||
| 313 | #endif // SPLIT_LED_STATE_ENABLE | ||
| 314 | |||
| 315 | //////////////////////////////////////////////////// | ||
| 316 | // Mods | ||
| 317 | |||
| 318 | #ifdef SPLIT_MODS_ENABLE | ||
| 319 | |||
| 320 | static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 321 | static uint32_t last_update = 0; | ||
| 322 | bool mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS; | ||
| 323 | split_mods_sync_t new_mods; | ||
| 324 | new_mods.real_mods = get_mods(); | ||
| 325 | if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) { | ||
| 326 | mods_need_sync = true; | ||
| 327 | } | ||
| 328 | |||
| 329 | new_mods.weak_mods = get_weak_mods(); | ||
| 330 | if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) { | ||
| 331 | mods_need_sync = true; | ||
| 332 | } | ||
| 333 | |||
| 334 | # ifndef NO_ACTION_ONESHOT | ||
| 335 | new_mods.oneshot_mods = get_oneshot_mods(); | ||
| 336 | if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) { | ||
| 337 | mods_need_sync = true; | ||
| 338 | } | ||
| 339 | # endif // NO_ACTION_ONESHOT | ||
| 340 | |||
| 341 | bool okay = true; | ||
| 342 | if (mods_need_sync) { | ||
| 343 | okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods)); | ||
| 344 | if (okay) { | ||
| 345 | last_update = timer_read32(); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | return okay; | ||
| 350 | } | ||
| 351 | |||
| 352 | static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 353 | set_mods(split_shmem->mods.real_mods); | ||
| 354 | set_weak_mods(split_shmem->mods.weak_mods); | ||
| 355 | # ifndef NO_ACTION_ONESHOT | ||
| 356 | set_oneshot_mods(split_shmem->mods.oneshot_mods); | ||
| 357 | # endif | ||
| 358 | } | ||
| 359 | |||
| 360 | # define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods) | ||
| 361 | # define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods) | ||
| 362 | # define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods), | ||
| 363 | |||
| 364 | #else // SPLIT_MODS_ENABLE | ||
| 365 | |||
| 366 | # define TRANSACTIONS_MODS_MASTER() | ||
| 367 | # define TRANSACTIONS_MODS_SLAVE() | ||
| 368 | # define TRANSACTIONS_MODS_REGISTRATIONS | ||
| 369 | |||
| 370 | #endif // SPLIT_MODS_ENABLE | ||
| 371 | |||
| 372 | //////////////////////////////////////////////////// | ||
| 373 | // Backlight | ||
| 374 | |||
| 375 | #ifdef BACKLIGHT_ENABLE | ||
| 376 | |||
| 377 | static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 378 | static uint32_t last_update = 0; | ||
| 379 | uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; | ||
| 380 | return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level)); | ||
| 381 | } | ||
| 382 | |||
| 383 | static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); } | ||
| 384 | |||
| 385 | # define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight) | ||
| 386 | # define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight) | ||
| 387 | # define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level), | ||
| 388 | |||
| 389 | #else // BACKLIGHT_ENABLE | ||
| 390 | |||
| 391 | # define TRANSACTIONS_BACKLIGHT_MASTER() | ||
| 392 | # define TRANSACTIONS_BACKLIGHT_SLAVE() | ||
| 393 | # define TRANSACTIONS_BACKLIGHT_REGISTRATIONS | ||
| 394 | |||
| 395 | #endif // BACKLIGHT_ENABLE | ||
| 396 | |||
| 397 | //////////////////////////////////////////////////// | ||
| 398 | // RGBLIGHT | ||
| 399 | |||
| 400 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 401 | |||
| 402 | static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 403 | static uint32_t last_update = 0; | ||
| 404 | rgblight_syncinfo_t rgblight_sync; | ||
| 405 | rgblight_get_syncinfo(&rgblight_sync); | ||
| 406 | if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) { | ||
| 407 | rgblight_clear_change_flags(); | ||
| 408 | } else { | ||
| 409 | return false; | ||
| 410 | } | ||
| 411 | return true; | ||
| 412 | } | ||
| 413 | |||
| 414 | static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 415 | // Update the RGB with the new data | ||
| 416 | if (split_shmem->rgblight_sync.status.change_flags != 0) { | ||
| 417 | rgblight_update_sync(&split_shmem->rgblight_sync, false); | ||
| 418 | split_shmem->rgblight_sync.status.change_flags = 0; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | # define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight) | ||
| 423 | # define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight) | ||
| 424 | # define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync), | ||
| 425 | |||
| 426 | #else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 427 | |||
| 428 | # define TRANSACTIONS_RGBLIGHT_MASTER() | ||
| 429 | # define TRANSACTIONS_RGBLIGHT_SLAVE() | ||
| 430 | # define TRANSACTIONS_RGBLIGHT_REGISTRATIONS | ||
| 431 | |||
| 432 | #endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 433 | |||
| 434 | //////////////////////////////////////////////////// | ||
| 435 | // LED Matrix | ||
| 436 | |||
| 437 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 438 | |||
| 439 | static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 440 | static uint32_t last_update = 0; | ||
| 441 | led_matrix_sync_t led_matrix_sync; | ||
| 442 | memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t)); | ||
| 443 | led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state(); | ||
| 444 | return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync)); | ||
| 445 | } | ||
| 446 | |||
| 447 | static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 448 | memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); | ||
| 449 | led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); | ||
| 450 | } | ||
| 451 | |||
| 452 | # define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix) | ||
| 453 | # define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix) | ||
| 454 | # define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync), | ||
| 455 | |||
| 456 | #else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 457 | |||
| 458 | # define TRANSACTIONS_LED_MATRIX_MASTER() | ||
| 459 | # define TRANSACTIONS_LED_MATRIX_SLAVE() | ||
| 460 | # define TRANSACTIONS_LED_MATRIX_REGISTRATIONS | ||
| 461 | |||
| 462 | #endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 463 | |||
| 464 | //////////////////////////////////////////////////// | ||
| 465 | // RGB Matrix | ||
| 466 | |||
| 467 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 468 | |||
| 469 | static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 470 | static uint32_t last_update = 0; | ||
| 471 | rgb_matrix_sync_t rgb_matrix_sync; | ||
| 472 | memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t)); | ||
| 473 | rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state(); | ||
| 474 | return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync)); | ||
| 475 | } | ||
| 476 | |||
| 477 | static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 478 | memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); | ||
| 479 | rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); | ||
| 480 | } | ||
| 481 | |||
| 482 | # define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix) | ||
| 483 | # define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix) | ||
| 484 | # define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync), | ||
| 485 | |||
| 486 | #else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 487 | |||
| 488 | # define TRANSACTIONS_RGB_MATRIX_MASTER() | ||
| 489 | # define TRANSACTIONS_RGB_MATRIX_SLAVE() | ||
| 490 | # define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS | ||
| 491 | |||
| 492 | #endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 493 | |||
| 494 | //////////////////////////////////////////////////// | ||
| 495 | // WPM | ||
| 496 | |||
| 497 | #if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 498 | |||
| 499 | static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 500 | static uint32_t last_update = 0; | ||
| 501 | uint8_t current_wpm = get_current_wpm(); | ||
| 502 | return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), ¤t_wpm, sizeof(current_wpm)); | ||
| 503 | } | ||
| 504 | |||
| 505 | static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); } | ||
| 506 | |||
| 507 | # define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm) | ||
| 508 | # define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm) | ||
| 509 | # define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), | ||
| 510 | |||
| 511 | #else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 512 | |||
| 513 | # define TRANSACTIONS_WPM_MASTER() | ||
| 514 | # define TRANSACTIONS_WPM_SLAVE() | ||
| 515 | # define TRANSACTIONS_WPM_REGISTRATIONS | ||
| 516 | |||
| 517 | #endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 518 | |||
| 519 | //////////////////////////////////////////////////// | ||
| 520 | // OLED | ||
| 521 | |||
| 522 | #if defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE) | ||
| 523 | |||
| 524 | static bool oled_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 525 | static uint32_t last_update = 0; | ||
| 526 | bool current_oled_state = is_oled_on(); | ||
| 527 | return send_if_condition(PUT_OLED, &last_update, (current_oled_state != split_shmem->current_oled_state), ¤t_oled_state, sizeof(current_oled_state)); | ||
| 528 | } | ||
| 529 | |||
| 530 | static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 531 | if (split_shmem->current_oled_state) { | ||
| 532 | oled_on(); | ||
| 533 | } else { | ||
| 534 | oled_off(); | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | # define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled) | ||
| 539 | # define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled) | ||
| 540 | # define TRANSACTIONS_OLED_REGISTRATIONS [PUT_OLED] = trans_initiator2target_initializer(current_oled_state), | ||
| 541 | |||
| 542 | #else // defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE) | ||
| 543 | |||
| 544 | # define TRANSACTIONS_OLED_MASTER() | ||
| 545 | # define TRANSACTIONS_OLED_SLAVE() | ||
| 546 | # define TRANSACTIONS_OLED_REGISTRATIONS | ||
| 547 | |||
| 548 | #endif // defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE) | ||
| 549 | |||
| 550 | //////////////////////////////////////////////////// | ||
| 551 | // ST7565 | ||
| 552 | |||
| 553 | #if defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) | ||
| 554 | |||
| 555 | static bool st7565_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 556 | static uint32_t last_update = 0; | ||
| 557 | bool current_st7565_state = st7565_is_on(); | ||
| 558 | return send_if_condition(PUT_ST7565, &last_update, (current_st7565_state != split_shmem->current_st7565_state), ¤t_st7565_state, sizeof(current_st7565_state)); | ||
| 559 | } | ||
| 560 | |||
| 561 | static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 562 | if (split_shmem->current_st7565_state) { | ||
| 563 | st7565_on(); | ||
| 564 | } else { | ||
| 565 | st7565_off(); | ||
| 566 | } | ||
| 567 | } | ||
| 568 | |||
| 569 | # define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565) | ||
| 570 | # define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565) | ||
| 571 | # define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state), | ||
| 572 | |||
| 573 | #else // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) | ||
| 574 | |||
| 575 | # define TRANSACTIONS_ST7565_MASTER() | ||
| 576 | # define TRANSACTIONS_ST7565_SLAVE() | ||
| 577 | # define TRANSACTIONS_ST7565_REGISTRATIONS | ||
| 578 | |||
| 579 | #endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) | ||
| 580 | |||
| 581 | //////////////////////////////////////////////////// | ||
| 582 | |||
| 583 | uint8_t dummy; | ||
| 584 | split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { | ||
| 585 | // Set defaults | ||
| 586 | [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0}, | ||
| 587 | |||
| 588 | #ifdef USE_I2C | ||
| 589 | [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id), | ||
| 590 | #endif // USE_I2C | ||
| 591 | |||
| 592 | // clang-format off | ||
| 593 | TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS | ||
| 594 | TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS | ||
| 595 | TRANSACTIONS_ENCODERS_REGISTRATIONS | ||
| 596 | TRANSACTIONS_SYNC_TIMER_REGISTRATIONS | ||
| 597 | TRANSACTIONS_LAYER_STATE_REGISTRATIONS | ||
| 598 | TRANSACTIONS_LED_STATE_REGISTRATIONS | ||
| 599 | TRANSACTIONS_MODS_REGISTRATIONS | ||
| 600 | TRANSACTIONS_BACKLIGHT_REGISTRATIONS | ||
| 601 | TRANSACTIONS_RGBLIGHT_REGISTRATIONS | ||
| 602 | TRANSACTIONS_LED_MATRIX_REGISTRATIONS | ||
| 603 | TRANSACTIONS_RGB_MATRIX_REGISTRATIONS | ||
| 604 | TRANSACTIONS_WPM_REGISTRATIONS | ||
| 605 | TRANSACTIONS_OLED_REGISTRATIONS | ||
| 606 | TRANSACTIONS_ST7565_REGISTRATIONS | ||
| 607 | // clang-format on | ||
| 608 | |||
| 609 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 610 | [PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback), | ||
| 611 | [PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer), | ||
| 612 | [EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback), | ||
| 613 | [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer), | ||
| 614 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 615 | }; | ||
| 616 | |||
| 617 | bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 618 | TRANSACTIONS_SLAVE_MATRIX_MASTER(); | ||
| 619 | TRANSACTIONS_MASTER_MATRIX_MASTER(); | ||
| 620 | TRANSACTIONS_ENCODERS_MASTER(); | ||
| 621 | TRANSACTIONS_SYNC_TIMER_MASTER(); | ||
| 622 | TRANSACTIONS_LAYER_STATE_MASTER(); | ||
| 623 | TRANSACTIONS_LED_STATE_MASTER(); | ||
| 624 | TRANSACTIONS_MODS_MASTER(); | ||
| 625 | TRANSACTIONS_BACKLIGHT_MASTER(); | ||
| 626 | TRANSACTIONS_RGBLIGHT_MASTER(); | ||
| 627 | TRANSACTIONS_LED_MATRIX_MASTER(); | ||
| 628 | TRANSACTIONS_RGB_MATRIX_MASTER(); | ||
| 629 | TRANSACTIONS_WPM_MASTER(); | ||
| 630 | TRANSACTIONS_OLED_MASTER(); | ||
| 631 | TRANSACTIONS_ST7565_MASTER(); | ||
| 632 | return true; | ||
| 633 | } | ||
| 634 | |||
| 635 | void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 636 | TRANSACTIONS_SLAVE_MATRIX_SLAVE(); | ||
| 637 | TRANSACTIONS_MASTER_MATRIX_SLAVE(); | ||
| 638 | TRANSACTIONS_ENCODERS_SLAVE(); | ||
| 639 | TRANSACTIONS_SYNC_TIMER_SLAVE(); | ||
| 640 | TRANSACTIONS_LAYER_STATE_SLAVE(); | ||
| 641 | TRANSACTIONS_LED_STATE_SLAVE(); | ||
| 642 | TRANSACTIONS_MODS_SLAVE(); | ||
| 643 | TRANSACTIONS_BACKLIGHT_SLAVE(); | ||
| 644 | TRANSACTIONS_RGBLIGHT_SLAVE(); | ||
| 645 | TRANSACTIONS_LED_MATRIX_SLAVE(); | ||
| 646 | TRANSACTIONS_RGB_MATRIX_SLAVE(); | ||
| 647 | TRANSACTIONS_WPM_SLAVE(); | ||
| 648 | TRANSACTIONS_OLED_SLAVE(); | ||
| 649 | TRANSACTIONS_ST7565_SLAVE(); | ||
| 650 | } | ||
| 651 | |||
| 652 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 653 | |||
| 654 | void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) { | ||
| 655 | // Prevent invoking RPC on QMK core sync data | ||
| 656 | if (transaction_id <= GET_RPC_RESP_DATA) return; | ||
| 657 | |||
| 658 | // Set the callback | ||
| 659 | split_transaction_table[transaction_id].slave_callback = callback; | ||
| 660 | split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer); | ||
| 661 | split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer); | ||
| 662 | } | ||
| 663 | |||
| 664 | bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { | ||
| 665 | // Prevent transaction attempts while transport is disconnected | ||
| 666 | if (!is_transport_connected()) { | ||
| 667 | return false; | ||
| 668 | } | ||
| 669 | // Prevent invoking RPC on QMK core sync data | ||
| 670 | if (transaction_id <= GET_RPC_RESP_DATA) return false; | ||
| 671 | // Prevent sizing issues | ||
| 672 | if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false; | ||
| 673 | if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false; | ||
| 674 | |||
| 675 | // Prepare the metadata block | ||
| 676 | rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size}; | ||
| 677 | |||
| 678 | // Make sure the local side knows that we're not sending the full block of data | ||
| 679 | split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size; | ||
| 680 | split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size; | ||
| 681 | |||
| 682 | // Run through the sequence: | ||
| 683 | // * set the transaction ID and lengths | ||
| 684 | // * send the request data | ||
| 685 | // * execute RPC callback | ||
| 686 | // * retrieve the response data | ||
| 687 | if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) { | ||
| 688 | return false; | ||
| 689 | } | ||
| 690 | if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) { | ||
| 691 | return false; | ||
| 692 | } | ||
| 693 | if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) { | ||
| 694 | return false; | ||
| 695 | } | ||
| 696 | if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) { | ||
| 697 | return false; | ||
| 698 | } | ||
| 699 | return true; | ||
| 700 | } | ||
| 701 | |||
| 702 | void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { | ||
| 703 | // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data. | ||
| 704 | // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it. | ||
| 705 | // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime. | ||
| 706 | |||
| 707 | split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length; | ||
| 708 | split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length; | ||
| 709 | } | ||
| 710 | |||
| 711 | void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { | ||
| 712 | // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed. | ||
| 713 | // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs. | ||
| 714 | int8_t transaction_id = split_shmem->rpc_info.transaction_id; | ||
| 715 | if (transaction_id < NUM_TOTAL_TRANSACTIONS) { | ||
| 716 | split_transaction_desc_t *trans = &split_transaction_table[transaction_id]; | ||
| 717 | if (trans->slave_callback) { | ||
| 718 | trans->slave_callback(split_shmem->rpc_info.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.s2m_length, split_shmem->rpc_s2m_buffer); | ||
| 719 | } | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
