mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-06-03 14:13:46 -03:00
Allow custom data sync for community modules (#25955)
* Allow custom data sync for community modules * Stub out community_config.h codegen * Fix SPLIT_TRANSACTION_RPC logic
This commit is contained in:
@@ -187,6 +187,11 @@ include $(COMMUNITY_RULES_MK)
|
||||
|
||||
ifneq ($(COMMUNITY_MODULES),)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/community_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-community-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_config.h $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-community-modules-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(KEYMAP_JSON))
|
||||
@@ -217,9 +222,15 @@ $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc: $(KEYMAP_JSON) $(DD
|
||||
$(eval CMD=$(QMK_BIN) generate-rgb-matrix-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) generate-split-transaction-id-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc $(KEYMAP_JSON))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
COMMUNITY_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_config.h
|
||||
SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c
|
||||
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
|
||||
|
||||
endif
|
||||
|
||||
@@ -320,6 +331,10 @@ define config_h_community_module_appender
|
||||
endef
|
||||
$(foreach module,$(COMMUNITY_MODULE_PATHS),$(eval $(call config_h_community_module_appender,$(module))))
|
||||
|
||||
ifneq ($(COMMUNITY_CONFIG_H),)
|
||||
CONFIG_H += $(COMMUNITY_CONFIG_H)
|
||||
endif
|
||||
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","")
|
||||
CONFIG_H += $(KEYBOARD_PATH_5)/config.h
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
// This version exists to signify addition of split data sync support.
|
||||
}
|
||||
@@ -95,6 +95,10 @@ The use of `features` matches the definition normally provided within `keyboard.
|
||||
|
||||
The `keycodes` array allows a module to provide new keycodes (as well as corresponding aliases) to a keymap.
|
||||
|
||||
### `config.h`
|
||||
|
||||
This file will be automatically added to the build as if it were present in the keyboard or keymap.
|
||||
|
||||
### `rules.mk` / `post_rules.mk`
|
||||
|
||||
These two files follows standard QMK build system logic, allowing for `Makefile`-style customisation as if it were present in the keyboard or keymap.
|
||||
@@ -131,6 +135,10 @@ This file defines LED matrix effects in the same form as used with `led_matrix_k
|
||||
|
||||
This file defines RGB matrix effects in the same form as used with `rgb_matrix_kb.inc` and `rgb_matrix_user.inc` (see [Custom RGB Matrix Effects](rgb_matrix#custom-rgb-matrix-effects)). Effect mode names are prepended with `RGB_MATRIX_COMMUNITY_MODULE_`.
|
||||
|
||||
### Custom split keyboard data sync
|
||||
|
||||
Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_<MODULE>` (see [Custom LED Matrix Effects](split_keyboard#custom-data-sync)).
|
||||
|
||||
### Compatible APIs
|
||||
|
||||
Community Modules may provide specializations for the following APIs:
|
||||
|
||||
@@ -194,6 +194,38 @@ def generate_community_modules_rules_mk(cli):
|
||||
cli.log.info('Wrote rules.mk to %s.', cli.args.output)
|
||||
|
||||
|
||||
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
|
||||
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
|
||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_config.h for.')
|
||||
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
|
||||
@cli.subcommand('Creates a community_config.h from a keymap.json file.')
|
||||
def generate_community_config_h(cli):
|
||||
"""Creates a community_config.h from a keymap.json file
|
||||
"""
|
||||
if cli.args.output and cli.args.output.name == '-':
|
||||
cli.args.output = None
|
||||
|
||||
lines = [
|
||||
GPL2_HEADER_C_LIKE,
|
||||
GENERATED_HEADER_C_LIKE,
|
||||
'#pragma once',
|
||||
'',
|
||||
]
|
||||
|
||||
modules = get_modules(cli.args.keyboard, cli.args.filename)
|
||||
if len(modules) > 0:
|
||||
lines.append('// Split transactions')
|
||||
for module in modules:
|
||||
lines.extend([
|
||||
f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{Path(module).name.upper()}',
|
||||
'# define SPLIT_TRANSACTION_RPC',
|
||||
'#endif',
|
||||
])
|
||||
lines.append('')
|
||||
|
||||
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
|
||||
|
||||
|
||||
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
|
||||
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
|
||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.h for.')
|
||||
@@ -339,3 +371,26 @@ def generate_rgb_matrix_community_modules_inc(cli):
|
||||
"""Creates an rgb_matrix_community_modules.inc from a keymap.json file
|
||||
"""
|
||||
_generate_include_per_module(cli, 'rgb_matrix_module.inc')
|
||||
|
||||
|
||||
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
|
||||
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
|
||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate split_transaction_id_community_modules.inc for.')
|
||||
@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
|
||||
@cli.subcommand('Creates an split_transaction_id_community_modules.inc from a keymap.json file.')
|
||||
def generate_split_transaction_id_community_modules_inc(cli):
|
||||
"""Creates an split_transaction_id_community_modules.inc from a keymap.json file
|
||||
"""
|
||||
if cli.args.output and cli.args.output.name == '-':
|
||||
cli.args.output = None
|
||||
|
||||
lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE]
|
||||
|
||||
for module in get_modules(cli.args.keyboard, cli.args.filename):
|
||||
lines.extend([
|
||||
f'#ifdef SPLIT_TRANSACTION_IDS_MODULE_{Path(module).name.upper()}',
|
||||
f' SPLIT_TRANSACTION_IDS_MODULE_{Path(module).name.upper()},',
|
||||
'#endif',
|
||||
])
|
||||
|
||||
dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#define SPLIT_TRANSACTION_IDS_MODULE_SPLIT_DATA_SYNC EXAMPLE_MODULE_SYNC_A
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"module_name": "Example split data sync",
|
||||
"maintainer": "QMK Maintainers",
|
||||
"license": "GPL-2.0-or-later"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include "debug.h"
|
||||
#include "timer.h"
|
||||
#include "transactions.h"
|
||||
|
||||
typedef struct _master_to_slave_t {
|
||||
int m2s_data;
|
||||
} master_to_slave_t;
|
||||
|
||||
typedef struct _slave_to_master_t {
|
||||
int s2m_data;
|
||||
} slave_to_master_t;
|
||||
|
||||
static void module_sync_slave_handler(uint8_t in_buflen, const void *in_data, uint8_t out_buflen, void *out_data) {
|
||||
const master_to_slave_t *m2s = (const master_to_slave_t *)in_data;
|
||||
slave_to_master_t *s2m = (slave_to_master_t *)out_data;
|
||||
s2m->s2m_data = m2s->m2s_data + 5; // whatever comes in, add 5 so it can be sent back
|
||||
}
|
||||
|
||||
void keyboard_post_init_split_data_sync(void) {
|
||||
transaction_register_rpc(EXAMPLE_MODULE_SYNC_A, module_sync_slave_handler);
|
||||
}
|
||||
|
||||
void housekeeping_task_split_data_sync(void) {
|
||||
if (is_keyboard_master()) {
|
||||
// Interact with slave every 500ms
|
||||
static uint32_t last_sync = 0;
|
||||
if (timer_elapsed32(last_sync) > 500) {
|
||||
master_to_slave_t m2s = {6};
|
||||
slave_to_master_t s2m = {0};
|
||||
if (transaction_rpc_exec(EXAMPLE_MODULE_SYNC_A, sizeof(m2s), &m2s, sizeof(s2m), &s2m)) {
|
||||
last_sync = timer_read32();
|
||||
dprintf("Slave value: %d\n", s2m.s2m_data); // this will now be 11, as the slave adds 5
|
||||
} else {
|
||||
dprint("Slave sync failed!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
#include "compiler_support.h"
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
# define SPLIT_TRANSACTION_RPC
|
||||
#endif
|
||||
|
||||
enum serial_transaction_id {
|
||||
#ifdef USE_I2C
|
||||
I2C_EXECUTE_CALLBACK,
|
||||
@@ -99,12 +103,12 @@ enum serial_transaction_id {
|
||||
PUT_ACTIVITY,
|
||||
#endif // SPLIT_ACTIVITY_ENABLE
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
PUT_RPC_INFO,
|
||||
PUT_RPC_REQ_DATA,
|
||||
EXECUTE_RPC,
|
||||
GET_RPC_RESP_DATA,
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
// keyboard-specific
|
||||
#ifdef SPLIT_TRANSACTION_IDS_KB
|
||||
@@ -116,6 +120,11 @@ enum serial_transaction_id {
|
||||
SPLIT_TRANSACTION_IDS_USER,
|
||||
#endif // SPLIT_TRANSACTION_IDS_USER
|
||||
|
||||
// community module specific
|
||||
#ifdef COMMUNITY_MODULES_ENABLE
|
||||
# include "split_transaction_id_community_modules.inc"
|
||||
#endif // COMMUNITY_MODULES_ENABLE
|
||||
|
||||
#if defined(OS_DETECTION_ENABLE) && defined(SPLIT_DETECTED_OS_ENABLE)
|
||||
PUT_DETECTED_OS,
|
||||
#endif // defined(OS_DETECTION_ENABLE) && defined(SPLIT_DETECTED_OS_ENABLE)
|
||||
|
||||
@@ -85,11 +85,11 @@
|
||||
#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
|
||||
#define transport_exec(id) transport_execute_transaction(id, NULL, 0, NULL, 0)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
// Forward-declare the RPC callback handlers
|
||||
void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
|
||||
void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
@@ -943,12 +943,12 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
||||
TRANSACTIONS_DETECTED_OS_REGISTRATIONS
|
||||
// clang-format on
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
[PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback),
|
||||
[PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer),
|
||||
[EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.payload.transaction_id, slave_rpc_exec_callback),
|
||||
[GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer),
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
};
|
||||
|
||||
bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||
@@ -996,7 +996,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
|
||||
TRANSACTIONS_DETECTED_OS_SLAVE();
|
||||
}
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) {
|
||||
// Prevent invoking RPC on QMK core sync data
|
||||
@@ -1073,4 +1073,4 @@ void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *i
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "progmem.h"
|
||||
#include "action_layer.h"
|
||||
#include "matrix.h"
|
||||
#include "transaction_id_define.h"
|
||||
|
||||
#ifndef RPC_M2S_BUFFER_SIZE
|
||||
# define RPC_M2S_BUFFER_SIZE 32
|
||||
@@ -132,7 +133,7 @@ typedef struct _split_slave_activity_sync_t {
|
||||
} split_slave_activity_sync_t;
|
||||
#endif // defined(SPLIT_ACTIVITY_ENABLE)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
typedef struct _rpc_sync_info_t {
|
||||
uint8_t checksum;
|
||||
struct {
|
||||
@@ -141,7 +142,7 @@ typedef struct _rpc_sync_info_t {
|
||||
uint8_t s2m_length;
|
||||
} payload;
|
||||
} rpc_sync_info_t;
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
#if defined(OS_DETECTION_ENABLE) && defined(SPLIT_DETECTED_OS_ENABLE)
|
||||
# include "os_detection.h"
|
||||
@@ -222,11 +223,11 @@ typedef struct _split_shared_memory_t {
|
||||
split_slave_activity_sync_t activity_sync;
|
||||
#endif // defined(SPLIT_ACTIVITY_ENABLE)
|
||||
|
||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#if defined(SPLIT_TRANSACTION_RPC)
|
||||
rpc_sync_info_t rpc_info;
|
||||
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
|
||||
uint8_t rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE];
|
||||
#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||
#endif // defined(SPLIT_TRANSACTION_RPC)
|
||||
|
||||
#if defined(OS_DETECTION_ENABLE) && defined(SPLIT_DETECTED_OS_ENABLE)
|
||||
os_variant_t detected_os;
|
||||
|
||||
Reference in New Issue
Block a user