diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk index 514191b17d4..c2c47c00fb8 100644 --- a/builddefs/build_keyboard.mk +++ b/builddefs/build_keyboard.mk @@ -274,10 +274,19 @@ $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h: $(KEYMAP_JSON) $(D $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(KEYMAP_JSON)) @$(BUILD_CMD) +$(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES) + @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) + $(eval CMD=$(QMK_BIN) generate-led-matrix-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(KEYMAP_JSON)) + @$(BUILD_CMD) + +$(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES) + @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD) + $(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) + 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 - +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 include $(BUILDDEFS_PATH)/converters.mk diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index a1fe78211ba..2042002ffea 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -271,22 +271,14 @@ ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none) ifeq ($(strip $(WEAR_LEVELING_DRIVER)), embedded_flash) OPT_DEFS += -DHAL_USE_EFL SRC += wear_leveling_efl.c - $(INTERMEDIATE_OUTPUT)/wear_leveling_efl.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_efl_config.h - $(INTERMEDIATE_OUTPUT)/wear_leveling.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_efl_config.h else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), spi_flash) FLASH_DRIVER := spi SRC += wear_leveling_flash_spi.c - $(INTERMEDIATE_OUTPUT)/wear_leveling_flash_spi.o: FILE_SPECIFIC_CFLAGS += -include $(DRIVER_PATH)/wear_leveling/wear_leveling_flash_spi_config.h - $(INTERMEDIATE_OUTPUT)/wear_leveling.o: FILE_SPECIFIC_CFLAGS += -include $(DRIVER_PATH)/wear_leveling/wear_leveling_flash_spi_config.h else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), rp2040_flash) SRC += wear_leveling_rp2040_flash.c - $(INTERMEDIATE_OUTPUT)/wear_leveling_rp2040_flash.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_rp2040_flash_config.h - $(INTERMEDIATE_OUTPUT)/wear_leveling.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_rp2040_flash_config.h else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), legacy) COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash SRC += legacy_flash_ops.c wear_leveling_legacy.c - $(INTERMEDIATE_OUTPUT)/wear_leveling_legacy.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_legacy_config.h - $(INTERMEDIATE_OUTPUT)/wear_leveling.o: FILE_SPECIFIC_CFLAGS += -include $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_PATH)/wear_leveling/wear_leveling_legacy_config.h endif endif endif @@ -663,6 +655,11 @@ ifeq ($(strip $(XAP_ENABLE)), yes) SRC += $(QUANTUM_DIR)/xap/xap.c $(QUANTUM_DIR)/xap/xap_handlers.c endif +ifeq ($(strip $(RAW_ENABLE)), yes) + OPT_DEFS += -DRAW_ENABLE + SRC += raw_hid.c +endif + ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes) SEND_STRING_ENABLE := yes endif diff --git a/data/constants/module_hooks/1.1.1.hjson b/data/constants/module_hooks/1.1.1.hjson new file mode 100644 index 00000000000..49f5d0d5d0b --- /dev/null +++ b/data/constants/module_hooks/1.1.1.hjson @@ -0,0 +1,3 @@ +{ + // This version exists to signify addition of LED/RGB effect support. +} diff --git a/docs/features/community_modules.md b/docs/features/community_modules.md index 8dede47bd48..eff07c939a1 100644 --- a/docs/features/community_modules.md +++ b/docs/features/community_modules.md @@ -123,6 +123,14 @@ The source file may provide functions which allow access to information specifie Introspection is a relatively advanced topic within QMK, and existing patterns should be followed. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/qmk). ::: +### `led_matrix_module.inc` + +This file defines LED matrix effects in the same form as used with `led_matrix_kb.inc` and `led_matrix_user.inc` (see [Custom LED Matrix Effects](led_matrix#custom-led-matrix-effects)). Effect mode names are prepended with `LED_MATRIX_COMMUNITY_MODULE_`. + +### `rgb_matrix_module.inc` + +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_`. + ### Compatible APIs Community Modules may provide specializations for the following APIs: diff --git a/docs/features/rgb_matrix.md b/docs/features/rgb_matrix.md index a22f931f1be..ca50fc52572 100644 --- a/docs/features/rgb_matrix.md +++ b/docs/features/rgb_matrix.md @@ -150,6 +150,7 @@ enum rgb_matrix_effects { RGB_MATRIX_SOLID_SPLASH, // Hue & value pulse away from a single key hit then fades value out RGB_MATRIX_SOLID_MULTISPLASH, // Hue & value pulse away from multiple key hits then fades value out RGB_MATRIX_STARLIGHT, // LEDs turn on and off at random at varying brightness, maintaining user set color + RGB_MATRIX_STARLIGHT_SMOOTH, // LEDs slowly increase and decrease in brightness randomly RGB_MATRIX_STARLIGHT_DUAL_HUE, // LEDs turn on and off at random at varying brightness, modifies user set hue by +- 30 RGB_MATRIX_STARLIGHT_DUAL_SAT, // LEDs turn on and off at random at varying brightness, modifies user set saturation by +- 30 RGB_MATRIX_RIVERFLOW, // Modification to breathing animation, offset's animation depending on key location to simulate a river flowing @@ -193,6 +194,7 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi |`#define ENABLE_RGB_MATRIX_PIXEL_FLOW` |Enables `RGB_MATRIX_PIXEL_FLOW` | |`#define ENABLE_RGB_MATRIX_PIXEL_RAIN` |Enables `RGB_MATRIX_PIXEL_RAIN` | |`#define ENABLE_RGB_MATRIX_STARLIGHT` |Enables `RGB_MATRIX_STARLIGHT` | +|`#define ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH` |Enables `RGB_MATRIX_STARLIGHT_SMOOTH` | |`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_HUE` |Enables `RGB_MATRIX_STARLIGHT_DUAL_HUE` | |`#define ENABLE_RGB_MATRIX_STARLIGHT_DUAL_SAT` |Enables `RGB_MATRIX_STARLIGHT_DUAL_SAT` | |`#define ENABLE_RGB_MATRIX_RIVERFLOW` |Enables `RGB_MATRIX_RIVERFLOW` | diff --git a/drivers/bluetooth/bluetooth.c b/drivers/bluetooth/bluetooth.c index 61a3f0f32a4..e61e24e1f22 100644 --- a/drivers/bluetooth/bluetooth.c +++ b/drivers/bluetooth/bluetooth.c @@ -28,3 +28,5 @@ __attribute__((weak)) void bluetooth_send_mouse(report_mouse_t *report) {} __attribute__((weak)) void bluetooth_send_consumer(uint16_t usage) {} __attribute__((weak)) void bluetooth_send_system(uint16_t usage) {} + +__attribute__((weak)) void bluetooth_send_raw_hid(uint8_t *data, uint8_t length) {} diff --git a/drivers/bluetooth/bluetooth.h b/drivers/bluetooth/bluetooth.h index e50b588db2f..bbd41a91943 100644 --- a/drivers/bluetooth/bluetooth.h +++ b/drivers/bluetooth/bluetooth.h @@ -81,3 +81,11 @@ void bluetooth_send_consumer(uint16_t usage); * \param usage The system usage to send. */ void bluetooth_send_system(uint16_t usage); + +/** + * \brief Send a raw_hid packet. + * + * \param data A pointer to the buffer to be sent. Always 32 bytes in length. + * \param length The length of the buffer. Always 32. + */ +void bluetooth_send_raw_hid(uint8_t *data, uint8_t length); diff --git a/drivers/wear_leveling/wear_leveling_flash_spi.c b/drivers/wear_leveling/wear_leveling_flash_spi.c index 304aed1641f..ca2c1745804 100644 --- a/drivers/wear_leveling/wear_leveling_flash_spi.c +++ b/drivers/wear_leveling/wear_leveling_flash_spi.c @@ -5,6 +5,7 @@ #include "util.h" #include "timer.h" #include "wear_leveling.h" +#include "wear_leveling_flash_spi_config.h" #include "wear_leveling_internal.h" #ifndef WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT diff --git a/keyboards/handwired/onekey/info.json b/keyboards/handwired/onekey/info.json index 7b6b7ddab89..d5f650f1bd4 100644 --- a/keyboards/handwired/onekey/info.json +++ b/keyboards/handwired/onekey/info.json @@ -26,5 +26,17 @@ {"x": 0, "y": 0, "matrix": [0, 0]} ] } + }, + "led_matrix": { + "driver": "snled27351", + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0, "flags": 1} + ] + }, + "rgb_matrix": { + "driver": "snled27351", + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0, "flags": 1} + ] } } diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h new file mode 100644 index 00000000000..aed1e4ac6fa --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h @@ -0,0 +1,16 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c new file mode 100644 index 00000000000..0bd835ff256 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c @@ -0,0 +1,27 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This keymap serves as a test for modules/qmk/flow_led_matrix_effect. + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(LM_TOGG)}; + +const snled27351_led_t PROGMEM g_snled27351_leds[LED_MATRIX_LED_COUNT] = { + {0, CB6_CA1}, +}; + +void keyboard_post_init_user(void) { + led_matrix_mode_noeeprom(LED_MATRIX_COMMUNITY_MODULE_FLOW); +} diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json new file mode 100644 index 00000000000..0ff6bf5a4dc --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json @@ -0,0 +1,3 @@ +{ + "modules": ["qmk/flow_led_matrix_effect"] +} diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h new file mode 100644 index 00000000000..aed1e4ac6fa --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h @@ -0,0 +1,16 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c new file mode 100644 index 00000000000..72ef2d3f80c --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c @@ -0,0 +1,27 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This keymap serves as a test for modules/qmk/flow_rgb_matrix_effect. + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(RM_TOGG)}; + +const snled27351_led_t PROGMEM g_snled27351_leds[LED_MATRIX_LED_COUNT] = { + {0, CB6_CA1}, +}; + +void keyboard_post_init_user(void) { + rgb_matrix_mode_noeeprom(RGB_MATRIX_COMMUNITY_MODULE_FLOW); +} diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json new file mode 100644 index 00000000000..56d2342867d --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json @@ -0,0 +1,3 @@ +{ + "modules": ["qmk/flow_rgb_matrix_effect"] +} diff --git a/lib/python/qmk/cli/generate/community_modules.py b/lib/python/qmk/cli/generate/community_modules.py index 61e24077d39..1f37b760ca0 100644 --- a/lib/python/qmk/cli/generate/community_modules.py +++ b/lib/python/qmk/cli/generate/community_modules.py @@ -278,33 +278,32 @@ def generate_community_modules_c(cli): dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) +def _generate_include_per_module(cli, include_file_name): + """Generates C code to include "/include_file_name" for each module.""" + 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): + full_path = f'{find_module_path(module)}/{include_file_name}' + lines.append('') + lines.append(f'#if __has_include("{full_path}")') + lines.append(f'#include "{full_path}"') + lines.append(f'#endif // __has_include("{full_path}")') + + 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.c for.') +@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules_introspection.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_modules_introspection.h from a keymap.json file.') def generate_community_modules_introspection_h(cli): """Creates a community_modules_introspection.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, - '', - ] - - modules = get_modules(cli.args.keyboard, cli.args.filename) - if len(modules) > 0: - for module in modules: - module_path = find_module_path(module) - lines.append(f'#if __has_include("{module_path}/introspection.h")') - lines.append(f'#include "{module_path}/introspection.h"') - lines.append(f'#endif // __has_include("{module_path}/introspection.h")') - lines.append('') - - dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) + _generate_include_per_module(cli, 'introspection.h') @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') @@ -315,22 +314,26 @@ def generate_community_modules_introspection_h(cli): def generate_community_modules_introspection_c(cli): """Creates a community_modules_introspection.c from a keymap.json file """ - if cli.args.output and cli.args.output.name == '-': - cli.args.output = None + _generate_include_per_module(cli, 'introspection.c') - lines = [ - GPL2_HEADER_C_LIKE, - GENERATED_HEADER_C_LIKE, - '', - ] - modules = get_modules(cli.args.keyboard, cli.args.filename) - if len(modules) > 0: - for module in modules: - module_path = find_module_path(module) - lines.append(f'#if __has_include("{module_path}/introspection.c")') - lines.append(f'#include "{module_path}/introspection.c"') - lines.append(f'#endif // __has_include("{module_path}/introspection.c")') - lines.append('') +@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 led_matrix_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 led_matrix_community_modules.inc from a keymap.json file.') +def generate_led_matrix_community_modules_inc(cli): + """Creates an led_matrix_community_modules.inc from a keymap.json file + """ + _generate_include_per_module(cli, 'led_matrix_module.inc') - 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 rgb_matrix_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 rgb_matrix_community_modules.inc from a keymap.json file.') +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') diff --git a/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc b/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc new file mode 100644 index 00000000000..734e0f34945 --- /dev/null +++ b/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc @@ -0,0 +1,58 @@ +// Copyright 2024-2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +LED_MATRIX_EFFECT(FLOW) + +#ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +// "Flow" animated effect. Draws moving wave patterns mimicking the appearance +// of flowing liquid. For interesting variety of patterns, space coordinates are +// slowly rotated and a function of several sine waves is evaluated. +static bool FLOW(effect_params_t* params) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + static uint16_t wrap_correction = 0; + static uint8_t last_high_byte = 0; + const uint8_t time_scale = 1 + led_matrix_eeconfig.speed / 8; + const uint8_t high_byte = (uint8_t)(g_led_timer >> 16); + if (last_high_byte != high_byte) { + last_high_byte = high_byte; + wrap_correction += ((uint16_t)time_scale) << 8; + } + const uint16_t time = scale16by8(g_led_timer, time_scale) + wrap_correction; + + // Compute rotation coefficients with 7 fractional bits. + const int8_t rot_c = cos8(time / 4) - 128; + const int8_t rot_s = sin8(time / 4) - 128; + const uint8_t omega = 32 + sin8(time) / 4; + + for (uint8_t i = led_min; i < led_max; ++i) { + LED_MATRIX_TEST_LED_FLAGS(); + const uint8_t x = g_led_config.point[i].x; + const uint8_t y = g_led_config.point[i].y; + + // Rotate (x, y) by the 2x2 rotation matrix described by rot_c, rot_s. + const uint8_t x1 = (uint8_t)((((int16_t)rot_c) * ((int16_t)x)) / 128) - (uint8_t)((((int16_t)rot_s) * ((int16_t)y)) / 128); + const uint8_t y1 = (uint8_t)((((int16_t)rot_s) * ((int16_t)x)) / 128) + (uint8_t)((((int16_t)rot_c) * ((int16_t)y)) / 128); + + uint8_t value = scale8(sin8(x1 - 2 * time), omega) + y1 + time / 4; + value = (value <= 127) ? value : (255 - value); + + led_matrix_set_value(i, scale8(led_matrix_eeconfig.val, value)); + } + + return led_matrix_check_finished_leds(led_max); +} + +#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/modules/qmk/flow_led_matrix_effect/qmk_module.json b/modules/qmk/flow_led_matrix_effect/qmk_module.json new file mode 100644 index 00000000000..2d047cd0d08 --- /dev/null +++ b/modules/qmk/flow_led_matrix_effect/qmk_module.json @@ -0,0 +1,8 @@ +{ + "module_name": "Flow LED matrix effect", + "maintainer": "QMK Maintainers", + "license": "Apache-2.0", + "features": { + "led_matrix": true + } +} diff --git a/modules/qmk/flow_rgb_matrix_effect/qmk_module.json b/modules/qmk/flow_rgb_matrix_effect/qmk_module.json new file mode 100644 index 00000000000..3e42fe1ef46 --- /dev/null +++ b/modules/qmk/flow_rgb_matrix_effect/qmk_module.json @@ -0,0 +1,8 @@ +{ + "module_name": "Flow RGB matrix effect", + "maintainer": "QMK Maintainers", + "license": "Apache-2.0", + "features": { + "rgb_matrix": true + } +} diff --git a/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc b/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc new file mode 100644 index 00000000000..410838f7ec4 --- /dev/null +++ b/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc @@ -0,0 +1,64 @@ +// Copyright 2024-2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +RGB_MATRIX_EFFECT(FLOW) + +#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +// "Flow" animated effect. Draws moving wave patterns mimicking the appearance +// of flowing liquid. For interesting variety of patterns, space coordinates are +// slowly rotated and a function of several sine waves is evaluated. +static bool FLOW(effect_params_t* params) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + static uint16_t wrap_correction = 0; + static uint8_t last_high_byte = 0; + const uint8_t time_scale = 1 + rgb_matrix_config.speed / 8; + const uint8_t high_byte = (uint8_t)(g_rgb_timer >> 16); + if (last_high_byte != high_byte) { + last_high_byte = high_byte; + wrap_correction += ((uint16_t)time_scale) << 8; + } + const uint16_t time = scale16by8(g_rgb_timer, time_scale) + wrap_correction; + + // Compute rotation coefficients with 7 fractional bits. + const int8_t rot_c = cos8(time / 4) - 128; + const int8_t rot_s = sin8(time / 4) - 128; + const uint8_t omega = 32 + sin8(time) / 4; + + for (uint8_t i = led_min; i < led_max; ++i) { + RGB_MATRIX_TEST_LED_FLAGS(); + const uint8_t x = g_led_config.point[i].x; + const uint8_t y = g_led_config.point[i].y; + + // Rotate (x, y) by the 2x2 rotation matrix described by rot_c, rot_s. + const uint8_t x1 = (uint8_t)((((int16_t)rot_c) * ((int16_t)x)) / 128) - (uint8_t)((((int16_t)rot_s) * ((int16_t)y)) / 128); + const uint8_t y1 = (uint8_t)((((int16_t)rot_s) * ((int16_t)x)) / 128) + (uint8_t)((((int16_t)rot_c) * ((int16_t)y)) / 128); + + uint8_t value = scale8(sin8(x1 - 2 * time), omega) + y1 + time / 4; + value = (value <= 127) ? value : (255 - value); + + hsv_t hsv = rgb_matrix_config.hsv; + hsv.h -= value / 4; + hsv.s = scale8(hsv.s, (value < 74) ? 255 : (549 - 4 * value)); + hsv.v = scale8(hsv.v, (value < 95) ? (64 + 2 * value) : 255); + + rgb_t rgb = rgb_matrix_hsv_to_rgb(hsv); + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + + return rgb_matrix_check_finished_leds(led_max); +} + +#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c index fed16d20b1a..fec4646a5b4 100644 --- a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c +++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c @@ -4,6 +4,7 @@ #include #include "timer.h" #include "wear_leveling.h" +#include "wear_leveling_efl_config.h" #include "wear_leveling_internal.h" static flash_offset_t base_offset = UINT32_MAX; diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c index 7c6fd2d808f..3d2af625cae 100644 --- a/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c +++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c @@ -4,6 +4,7 @@ #include #include "timer.h" #include "wear_leveling.h" +#include "wear_leveling_legacy_config.h" #include "wear_leveling_internal.h" #include "legacy_flash_ops.h" diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c index 6624c30b5b3..9bfc68f9d2c 100644 --- a/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c +++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c @@ -15,6 +15,7 @@ #include #include "timer.h" #include "wear_leveling.h" +#include "wear_leveling_rp2040_flash_config.h" #include "wear_leveling_internal.h" #ifndef WEAR_LEVELING_RP2040_FLASH_BULK_COUNT diff --git a/platforms/eeprom.h b/platforms/eeprom.h index 067fa016164..557bfb030c5 100644 --- a/platforms/eeprom.h +++ b/platforms/eeprom.h @@ -37,6 +37,7 @@ void eeprom_update_block(const void *__src, void *__dst, size_t __n); # endif # define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE) #elif defined(EEPROM_WEAR_LEVELING) +# include "wear_leveling_drivers.h" # define TOTAL_EEPROM_BYTE_COUNT (WEAR_LEVELING_LOGICAL_SIZE) #elif defined(EEPROM_TRANSIENT) # include "eeprom_transient.h" diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 00bc199ecf1..7a0e8a5ebbc 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -45,6 +45,9 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; #define LED_MATRIX_CUSTOM_EFFECT_IMPLS #include "led_matrix_effects.inc" +#ifdef COMMUNITY_MODULES_ENABLE +# include "led_matrix_community_modules.inc" +#endif #ifdef LED_MATRIX_CUSTOM_KB # include "led_matrix_kb.inc" #endif @@ -282,6 +285,15 @@ static void led_task_render(uint8_t effect) { #include "led_matrix_effects.inc" #undef LED_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_COMMUNITY_MODULE_##name: \ + rendering = name(&led_effect_params); \ + break; +# include "led_matrix_community_modules.inc" +# undef LED_MATRIX_EFFECT +#endif + #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) # define LED_MATRIX_EFFECT(name, ...) \ case LED_MATRIX_CUSTOM_##name: \ diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index 0006d487e9d..0dfe33ffab3 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -98,6 +98,12 @@ enum led_matrix_effects { #include "led_matrix_effects.inc" #undef LED_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_COMMUNITY_MODULE_##name, +# include "led_matrix_community_modules.inc" +# undef LED_MATRIX_EFFECT +#endif + #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) # define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name, # ifdef LED_MATRIX_CUSTOM_KB diff --git a/quantum/os_detection.c b/quantum/os_detection.c index 9a9f9052f24..552375f61c0 100644 --- a/quantum/os_detection.c +++ b/quantum/os_detection.c @@ -68,6 +68,15 @@ static volatile bool first_report = true; static volatile struct usb_device_state current_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; static volatile struct usb_device_state maxprev_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; +// to reset the keyboard on USB state change +#ifdef OS_DETECTION_KEYBOARD_RESET +# ifndef OS_DETECTION_RESET_DEBOUNCE +# define OS_DETECTION_RESET_DEBOUNCE OS_DETECTION_DEBOUNCE +# endif +static volatile fast_timer_t configured_since = 0; +static volatile bool reset_pending = false; +#endif + // the OS detection might be unstable for a while, "debounce" it static volatile bool debouncing = false; static volatile fast_timer_t last_time = 0; @@ -77,7 +86,10 @@ bool process_detected_host_os_modules(os_variant_t os); void os_detection_task(void) { #ifdef OS_DETECTION_KEYBOARD_RESET // resetting the keyboard on the USB device state change callback results in instability, so delegate that to this task - // only take action if it's been stable at least once, to avoid issues with some KVMs + if (reset_pending) { + soft_reset_keyboard(); + } + // reset the keyboard if it is stuck in the init state for longer than debounce duration, which can happen with some KVMs if (current_usb_device_state.configure_state <= USB_DEVICE_STATE_INIT && maxprev_usb_device_state.configure_state >= USB_DEVICE_STATE_CONFIGURED) { if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { soft_reset_keyboard(); @@ -187,6 +199,18 @@ void os_detection_notify_usb_device_state_change(struct usb_device_state usb_dev current_usb_device_state = usb_device_state; last_time = timer_read_fast(); debouncing = true; + +#ifdef OS_DETECTION_KEYBOARD_RESET + if (configured_since == 0 && current_usb_device_state.configure_state == USB_DEVICE_STATE_CONFIGURED) { + configured_since = timer_read_fast(); + } else if (current_usb_device_state.configure_state == USB_DEVICE_STATE_INIT) { + // reset the keyboard only if it's been stable for at least debounce duration, to avoid issues with some KVMs + if (configured_since > 0 && timer_elapsed_fast(configured_since) >= OS_DETECTION_RESET_DEBOUNCE) { + reset_pending = true; + } + configured_since = 0; + } +#endif } #if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) diff --git a/quantum/raw_hid.c b/quantum/raw_hid.c new file mode 100644 index 00000000000..2c7a75f325d --- /dev/null +++ b/quantum/raw_hid.c @@ -0,0 +1,15 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "raw_hid.h" +#include "host.h" + +void raw_hid_send(uint8_t *data, uint8_t length) { + host_raw_hid_send(data, length); +} + +__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { + // Users should #include "raw_hid.h" in their own code + // and implement this function there. Leave this as weak linkage + // so users can opt to not handle data coming in. +} diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc index e8b7a2bcde2..abc2adf2cc7 100644 --- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc +++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc @@ -39,6 +39,7 @@ #include "solid_reactive_nexus.h" #include "splash_anim.h" #include "solid_splash_anim.h" +#include "starlight_smooth_anim.h" #include "starlight_anim.h" #include "starlight_dual_sat_anim.h" #include "starlight_dual_hue_anim.h" diff --git a/quantum/rgb_matrix/animations/starlight_smooth_anim.h b/quantum/rgb_matrix/animations/starlight_smooth_anim.h new file mode 100644 index 00000000000..a87c06f9df6 --- /dev/null +++ b/quantum/rgb_matrix/animations/starlight_smooth_anim.h @@ -0,0 +1,26 @@ +// Copyright 2022 @art-was-here +// SPDX-License-Identifier: GPL-2.0+ + +#ifdef ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH +RGB_MATRIX_EFFECT(STARLIGHT_SMOOTH) +# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t phase_offsets[RGB_MATRIX_LED_COUNT]; + +hsv_t STARLIGHT_SMOOTH_math(hsv_t hsv, uint8_t i, uint8_t time) { + if (phase_offsets[i] == 0) { + phase_offsets[i] = rand() % 255; + } + hsv.v = scale8(abs8(sin8((time + phase_offsets[i]) / 2) - 128) * 2, hsv.v); + return hsv; +} + +bool STARLIGHT_SMOOTH(effect_params_t* params) { + if (params->init) { + memset(phase_offsets, 0, sizeof(phase_offsets)); + } + return effect_runner_i(params, &STARLIGHT_SMOOTH_math); +} + +# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 94852e3520a..2679c483426 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -47,6 +47,9 @@ __attribute__((weak)) rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) { #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS #include "rgb_matrix_effects.inc" +#ifdef COMMUNITY_MODULES_ENABLE +# include "rgb_matrix_community_modules.inc" +#endif #ifdef RGB_MATRIX_CUSTOM_KB # include "rgb_matrix_kb.inc" #endif @@ -310,6 +313,15 @@ static void rgb_task_render(uint8_t effect) { #include "rgb_matrix_effects.inc" #undef RGB_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define RGB_MATRIX_EFFECT(name, ...) \ + case RGB_MATRIX_COMMUNITY_MODULE_##name: \ + rendering = name(&rgb_effect_params); \ + break; +# include "rgb_matrix_community_modules.inc" +# undef RGB_MATRIX_EFFECT +#endif + #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) # define RGB_MATRIX_EFFECT(name, ...) \ case RGB_MATRIX_CUSTOM_##name: \ diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index e00e3927c76..c6b302631ed 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -123,6 +123,12 @@ enum rgb_matrix_effects { #include "rgb_matrix_effects.inc" #undef RGB_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_COMMUNITY_MODULE_##name, +# include "rgb_matrix_community_modules.inc" +# undef RGB_MATRIX_EFFECT +#endif + #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) # define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_CUSTOM_##name, # ifdef RGB_MATRIX_CUSTOM_KB diff --git a/quantum/wear_leveling/wear_leveling.c b/quantum/wear_leveling/wear_leveling.c index 429df45df5e..258f074a5c6 100644 --- a/quantum/wear_leveling/wear_leveling.c +++ b/quantum/wear_leveling/wear_leveling.c @@ -3,6 +3,7 @@ #include #include "fnv.h" #include "wear_leveling.h" +#include "wear_leveling_drivers.h" #include "wear_leveling_internal.h" /* diff --git a/quantum/wear_leveling/wear_leveling_drivers.h b/quantum/wear_leveling/wear_leveling_drivers.h new file mode 100644 index 00000000000..e81f833fd11 --- /dev/null +++ b/quantum/wear_leveling/wear_leveling_drivers.h @@ -0,0 +1,13 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#if defined(WEAR_LEVELING_EMBEDDED_FLASH) +# include "wear_leveling/wear_leveling_efl_config.h" +#elif defined(WEAR_LEVELING_SPI_FLASH) +# include "wear_leveling/wear_leveling_flash_spi_config.h" +#elif defined(WEAR_LEVELING_RP2040_FLASH) +# include "wear_leveling/wear_leveling_rp2040_flash_config.h" +#elif defined(WEAR_LEVELING_LEGACY) +# include "wear_leveling/wear_leveling_legacy_config.h" +#endif diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 2930efc2833..81520c1bc81 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -33,10 +33,6 @@ ifeq ($(strip $(PROGRAMMABLE_BUTTON_ENABLE)), yes) SHARED_EP_ENABLE = yes endif -ifeq ($(strip $(RAW_ENABLE)), yes) - OPT_DEFS += -DRAW_ENABLE -endif - ifeq ($(strip $(CONSOLE_ENABLE)), yes) OPT_DEFS += -DCONSOLE_ENABLE else diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c index d752f3746b0..19d8121e349 100644 --- a/tmk_core/protocol/chibios/chibios.c +++ b/tmk_core/protocol/chibios/chibios.c @@ -66,9 +66,19 @@ void send_keyboard(report_keyboard_t *report); void send_nkro(report_nkro_t *report); void send_mouse(report_mouse_t *report); void send_extra(report_extra_t *report); +void send_raw_hid(uint8_t *data, uint8_t length); /* host struct */ -host_driver_t chibios_driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +host_driver_t chibios_driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; #ifdef VIRTSER_ENABLE void virtser_task(void); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 39669c99a42..837f22cbd87 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -32,6 +32,10 @@ #include "usb_driver.h" #include "usb_types.h" +#ifdef RAW_ENABLE +# include "raw_hid.h" +#endif + #ifdef NKRO_ENABLE # include "keycode_config.h" @@ -519,19 +523,13 @@ void console_task(void) { #endif /* CONSOLE_ENABLE */ #ifdef RAW_ENABLE -void raw_hid_send(uint8_t *data, uint8_t length) { +void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_EPSIZE) { return; } send_report(USB_ENDPOINT_IN_RAW, data, length); } -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - void raw_hid_task(void) { uint8_t buffer[RAW_EPSIZE]; while (receive_report(USB_ENDPOINT_OUT_RAW, buffer, sizeof(buffer))) { diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c index e785cb24cc6..4874d7c1d36 100644 --- a/tmk_core/protocol/host.c +++ b/tmk_core/protocol/host.c @@ -55,6 +55,9 @@ host_driver_t bt_driver = { .send_nkro = bluetooth_send_nkro, .send_mouse = bluetooth_send_mouse, .send_extra = bluetooth_send_extra, +# ifdef RAW_ENABLE + .send_raw_hid = bluetooth_send_raw_hid, +# endif }; #endif @@ -299,6 +302,15 @@ void host_programmable_button_send(uint32_t data) { __attribute__((weak)) void send_programmable_button(report_programmable_button_t *report) {} +#ifdef RAW_ENABLE +void host_raw_hid_send(uint8_t *data, uint8_t length) { + host_driver_t *driver = host_get_active_driver(); + if (!driver || !driver->send_raw_hid) return; + + (*driver->send_raw_hid)(data, length); +} +#endif + uint16_t host_last_system_usage(void) { return last_system_usage; } diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h index 8e8a18e2ed3..a0b1e73dccc 100644 --- a/tmk_core/protocol/host.h +++ b/tmk_core/protocol/host.h @@ -41,6 +41,7 @@ void host_mouse_send(report_mouse_t *report); void host_system_send(uint16_t usage); void host_consumer_send(uint16_t usage); void host_programmable_button_send(uint32_t data); +void host_raw_hid_send(uint8_t *data, uint8_t length); uint16_t host_last_system_usage(void); uint16_t host_last_consumer_usage(void); diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h index 8aa38b6dee2..c2835aaa99f 100644 --- a/tmk_core/protocol/host_driver.h +++ b/tmk_core/protocol/host_driver.h @@ -29,6 +29,9 @@ typedef struct { void (*send_nkro)(report_nkro_t *); void (*send_mouse)(report_mouse_t *); void (*send_extra)(report_extra_t *); +#ifdef RAW_ENABLE + void (*send_raw_hid)(uint8_t *, uint8_t); +#endif } host_driver_t; void send_joystick(report_joystick_t *report); diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index bc608a6829c..3cb9e96144f 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -79,11 +79,24 @@ static report_keyboard_t keyboard_report_sent; /* Host driver */ -static void send_keyboard(report_keyboard_t *report); -static void send_nkro(report_nkro_t *report); -static void send_mouse(report_mouse_t *report); -static void send_extra(report_extra_t *report); -host_driver_t lufa_driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +static void send_keyboard(report_keyboard_t *report); +static void send_nkro(report_nkro_t *report); +static void send_mouse(report_mouse_t *report); +static void send_extra(report_extra_t *report); +#ifdef RAW_ENABLE +static void send_raw_hid(uint8_t *data, uint8_t length); +#endif + +host_driver_t lufa_driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; void send_report(uint8_t endpoint, void *report, size_t size) { uint8_t timeout = 255; @@ -135,21 +148,11 @@ USB_ClassInfo_CDC_Device_t cdc_device = { * * FIXME: Needs doc */ -void raw_hid_send(uint8_t *data, uint8_t length) { +static void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_EPSIZE) return; send_report(RAW_IN_EPNUM, data, RAW_EPSIZE); } -/** \brief Raw HID Receive - * - * FIXME: Needs doc - */ -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - /** \brief Raw HID Task * * FIXME: Needs doc diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index e7872471e98..d96b8faad18 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -153,7 +153,7 @@ static void send_report(uint8_t endpoint, void *report, size_t size) { static uint8_t raw_output_buffer[RAW_BUFFER_SIZE]; static uint8_t raw_output_received_bytes = 0; -void raw_hid_send(uint8_t *data, uint8_t length) { +static void send_raw_hid(uint8_t *data, uint8_t length) { if (length != RAW_BUFFER_SIZE) { return; } @@ -161,12 +161,6 @@ void raw_hid_send(uint8_t *data, uint8_t length) { send_report(4, data, RAW_BUFFER_SIZE); } -__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { - // Users should #include "raw_hid.h" in their own code - // and implement this function there. Leave this as weak linkage - // so users can opt to not handle data coming in. -} - void raw_hid_task(void) { usbPoll(); @@ -296,8 +290,20 @@ static void send_keyboard(report_keyboard_t *report); static void send_nkro(report_nkro_t *report); static void send_mouse(report_mouse_t *report); static void send_extra(report_extra_t *report); +#ifdef RAW_ENABLE +static void send_raw_hid(uint8_t *data, uint8_t length); +#endif -static host_driver_t driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra}; +static host_driver_t driver = { + .keyboard_leds = usb_device_state_get_leds, + .send_keyboard = send_keyboard, + .send_nkro = send_nkro, + .send_mouse = send_mouse, + .send_extra = send_extra, +#ifdef RAW_ENABLE + .send_raw_hid = send_raw_hid, +#endif +}; host_driver_t *vusb_driver(void) { return &driver;