diff --git a/.travis.yml b/.travis.yml index 84fa63faf3d3..bfac998c11ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ install: - npm install -g moxygen script: - git rev-parse --short HEAD + - git diff --name-only HEAD $TRAVIS_BRANCH - bash util/travis_test.sh - bash util/travis_build.sh - bash util/travis_docs.sh diff --git a/common_features.mk b/common_features.mk index a1f95955a60c..e50207b0b4b5 100644 --- a/common_features.mk +++ b/common_features.mk @@ -407,8 +407,12 @@ ifeq ($(strip $(SPACE_CADET_ENABLE)), yes) OPT_DEFS += -DSPACE_CADET_ENABLE endif - ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes) SRC += $(QUANTUM_DIR)/dip_switch.c OPT_DEFS += -DDIP_SWITCH_ENABLE endif + +ifeq ($(strip $(DYNAMIC_MACRO_ENABLE)), yes) + SRC += $(QUANTUM_DIR)/process_keycode/process_dynamic_macro.c + OPT_DEFS += -DDYNAMIC_MACRO_ENABLE +endif diff --git a/docs/config_options.md b/docs/config_options.md index abd98ec8a802..c44a47178cee 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -348,7 +348,8 @@ Use these to enable or disable building certain features. The more you have enab * `NO_USB_STARTUP_CHECK` * Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master. * `LINK_TIME_OPTIMIZATION_ENABLE` - = Enables Link Time Optimization (`LTO`) when compiling the keyboard. This makes the process take longer, but can significantly reduce the compiled size (and since the firmware is small, the added time is not noticable). However, this will automatically disable the old Macros and Functions features automatically, as these break when `LTO` is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION` + * Enables Link Time Optimization (`LTO`) when compiling the keyboard. This makes the process take longer, but can significantly reduce the compiled size (and since the firmware is small, the added time is not noticeable). However, this will automatically disable the old Macros and Functions features automatically, as these break when `LTO` is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION` + * Alternatively, you can use `LTO_ENABLE` instead of `LINK_TIME_OPTIMIZATION_ENABLE`. ## USB Endpoint Limitations diff --git a/docs/feature_dynamic_macros.md b/docs/feature_dynamic_macros.md index 0d11a28641a6..b86df6c60ffe 100644 --- a/docs/feature_dynamic_macros.md +++ b/docs/feature_dynamic_macros.md @@ -4,51 +4,45 @@ QMK supports temporary macros created on the fly. We call these Dynamic Macros. You can store one or two macros and they may have a combined total of 128 keypresses. You can increase this size at the cost of RAM. -To enable them, first add a new element to the end of your `keycodes` enum — `DYNAMIC_MACRO_RANGE`: +To enable them, first include `DYNAMIC_MACRO_ENABLE = yes` in your `rules.mk`. Then, add the following keys to your keymap: -```c -enum keycodes { - QWERTY = SAFE_RANGE, - COLEMAK, - DVORAK, - PLOVER, - LOWER, - RAISE, - BACKLIT, - EXT_PLV, - DYNAMIC_MACRO_RANGE, -}; -``` +|Key |Alias |Description | +|------------------|----------|---------------------------------------------------| +|`DYN_REC_START1` |`DM_REC1` |Start recording Macro 1 | +|`DYN_REC_START2` |`DM_REC2` |Start recording Macro 2 | +|`DYN_MACRO_PLAY1` |`DM_PLY1` |Replay Macro 1 | +|`DYN_MACRO_PLAY2` |`DM_PLY2` |Replay Macro 2 | +|`DYN_REC_STOP` |`DM_RSTP` |Finish the macro that is currently being recorded. | -Your `keycodes` enum may have a slightly different name. You must add `DYNAMIC_MACRO_RANGE` as the last element because `dynamic_macros.h` will add some more keycodes after it. +That should be everything necessary. -Below it, include the `dynamic_macro.h` header: +To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`. -```c - #include "dynamic_macro.h"` -``` +To finish the recording, press the `DYN_REC_STOP` layer button. -Add the following keys to your keymap: +To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`. -* `DYN_REC_START1` — start recording the macro 1, -* `DYN_REC_START2` — start recording the macro 2, -* `DYN_MACRO_PLAY1` — replay the macro 1, -* `DYN_MACRO_PLAY2` — replay the macro 2, -* `DYN_REC_STOP` — finish the macro that is currently being recorded. +It is possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. You can disable this completly by defining `DYNAMIC_MACRO_NO_NESTING` in your `config.h` file. -Add the following code to the very beginning of your `process_record_user()` function: +?> For the details about the internals of the dynamic macros, please read the comments in the `process_dynamic_macro.h` and `process_dynamic_macro.c` files. -```c - if (!process_record_dynamic_macro(keycode, record)) { - return false; - } -``` +## Customization -That should be everything necessary. To start recording the macro, press either `DYN_REC_START1` or `DYN_REC_START2`. To finish the recording, press the `DYN_REC_STOP` layer button. To replay the macro, press either `DYN_MACRO_PLAY1` or `DYN_MACRO_PLAY2`. +There are a number of options added that should allow some additional degree of customization -Note that it's possible to replay a macro as part of a macro. It's ok to replay macro 2 while recording macro 1 and vice versa but never create recursive macros i.e. macro 1 that replays macro 1. If you do so and the keyboard will get unresponsive, unplug the keyboard and plug it again. +|Define |Default |Description | +|----------------------------|----------------|-----------------------------------------------------------------------------------------------------------------| +|`DYNAMIC_MACRO_SIZE` |128 |Sets the amount of memory that Dynamic Macros can use. This is a limited resource, dependent on the controller. | +|`DYNAMIC_MACRO_USER_CALL` |*Not defined* |Defining this falls back to using the user `keymap.c` file to trigger the macro behavior. | +|`DYNAMIC_MACRO_NO_NESTING` |*Not Defined* |Defining this disables the ability to call a macro from another macro (nested macros). | -For users of the earlier versions of dynamic macros: It is still possible to finish the macro recording using just the layer modifier used to access the dynamic macro keys, without a dedicated `DYN_REC_STOP` key. If you want this behavior back, use the following snippet instead of the one above: + +If the LEDs start blinking during the recording with each keypress, it means there is no more space for the macro in the macro buffer. To fit the macro in, either make the other macro shorter (they share the same buffer) or increase the buffer size by adding the `DYNAMIC_MACRO_SIZE` define in your `config.h` (default value: 128; please read the comments for it in the header). + + +### DYNAMIC_MACRO_USER_CALL + +For users of the earlier versions of dynamic macros: It is still possible to finish the macro recording using just the layer modifier used to access the dynamic macro keys, without a dedicated `DYN_REC_STOP` key. If you want this behavior back, add `#define DYNAMIC_MACRO_USER_CALL` to your `config.h` and insert the following snippet at the beginning of your `process_record_user()` function: ```c uint16_t macro_kc = (keycode == MO(_DYN) ? DYN_REC_STOP : keycode); @@ -58,6 +52,15 @@ For users of the earlier versions of dynamic macros: It is still possible to fin } ``` -If the LEDs start blinking during the recording with each keypress, it means there is no more space for the macro in the macro buffer. To fit the macro in, either make the other macro shorter (they share the same buffer) or increase the buffer size by setting the `DYNAMIC_MACRO_SIZE` preprocessor macro (default value: 128; please read the comments for it in the header). +### User Hooks + +There are a number of hooks that you can use to add custom functionality and feedback options to Dynamic Macro feature. This allows for some additional degree of customization. + +Note, that direction indicates which macro it is, with `1` being Macro 1, `-1` being Macro 2, and 0 being no macro. + +* `dynamic_macro_record_start_user(void)` - Triggered when you start recording a macro. +* `dynamic_macro_play_user(int8_t direction)` - Triggered when you play back a macro. +* `dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record)` - Triggered on each keypress while recording a macro. +* `dynamic_macro_record_end_user(int8_t direction)` - Triggered when the macro recording is stopped. -For the details about the internals of the dynamic macros, please read the comments in the `dynamic_macro.h` header. +Additionally, you can call `dynamic_macro_led_blink()` to flash the backlights if that feature is enabled. diff --git a/docs/keycodes.md b/docs/keycodes.md index 7dcff03fd549..fa01df63dca7 100644 --- a/docs/keycodes.md +++ b/docs/keycodes.md @@ -297,6 +297,16 @@ This is a reference only. Each group of keys links to the page documenting their |`OUT_USB` |USB only | |`OUT_BT` |Bluetooth only | +## [Dynamic Macros](feature_dynamic_macros.md) + +|Key |Alias |Description | +|-----------------|---------|--------------------------------------------------| +|`DYN_REC_START1` |`DM_REC1`|Start recording Macro 1 | +|`DYN_REC_START2` |`DM_REC2`|Start recording Macro 2 | +|`DYN_MACRO_PLAY1`|`DM_PLY1`|Replay Macro 1 | +|`DYN_MACRO_PLAY2`|`DM_PLY2`|Replay Macro 2 | +|`DYN_REC_STOP` |`DM_RSTP`|Finish the macro that is currently being recorded.| + ## [Layer Switching](feature_advanced_keycodes.md#switching-and-toggling-layers) |Key |Description | diff --git a/drivers/arm/i2c_master.h b/drivers/arm/i2c_master.h index a8ed66403a58..efe3909a6610 100644 --- a/drivers/arm/i2c_master.h +++ b/drivers/arm/i2c_master.h @@ -1,9 +1,9 @@ /* Copyright 2018 Jack Humbert * Copyright 2018 Yiancar * - * This program is free sofare: you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Sofare Foundation, either version 2 of the License, or + * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h index c7632c004b1c..fe9de6fa6516 100644 --- a/quantum/dynamic_macro.h +++ b/quantum/dynamic_macro.h @@ -15,8 +15,10 @@ */ /* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ -#ifndef DYNAMIC_MACROS_H -#define DYNAMIC_MACROS_H +#pragma once + +/* Warn users that this is now deprecated and they should use the core feature instead. */ +#pragma message "Dynamic Macros is now a core feature. See updated documentation to see how to configure it: https://docs.qmk.fm/#/feature_dynamic_macros" #include "action_layer.h" @@ -33,18 +35,6 @@ # define DYNAMIC_MACRO_SIZE 128 #endif -/* DYNAMIC_MACRO_RANGE must be set as the last element of user's - * "planck_keycodes" enum prior to including this header. This allows - * us to 'extend' it. - */ -enum dynamic_macro_keycodes { - DYN_REC_START1 = DYNAMIC_MACRO_RANGE, - DYN_REC_START2, - DYN_REC_STOP, - DYN_MACRO_PLAY1, - DYN_MACRO_PLAY2, -}; - /* Blink the LEDs to notify the user about some event. */ void dynamic_macro_led_blink(void) { #ifdef BACKLIGHT_ENABLE @@ -272,5 +262,3 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record) { #undef DYNAMIC_MACRO_CURRENT_SLOT #undef DYNAMIC_MACRO_CURRENT_LENGTH #undef DYNAMIC_MACRO_CURRENT_CAPACITY - -#endif diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c new file mode 100644 index 000000000000..2065f242db9e --- /dev/null +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -0,0 +1,257 @@ +/* Copyright 2016 Jack Humbert + * Copyright 2019 Drashna Jael're (@drashna, aka Christopher Courtney) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ +#include "process_dynamic_macro.h" + +// default feedback method +void dynamic_macro_led_blink(void) { +#ifdef BACKLIGHT_ENABLE + backlight_toggle(); + wait_ms(100); + backlight_toggle(); +#endif +} + +/* User hooks for Dynamic Macros */ + +__attribute__((weak)) void dynamic_macro_record_start_user(void) { dynamic_macro_led_blink(); } + +__attribute__((weak)) void dynamic_macro_play_user(int8_t direction) { dynamic_macro_led_blink(); } + +__attribute__((weak)) void dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record) { dynamic_macro_led_blink(); } + +__attribute__((weak)) void dynamic_macro_record_end_user(int8_t direction) { dynamic_macro_led_blink(); } + +/* Convenience macros used for retrieving the debug info. All of them + * need a `direction` variable accessible at the call site. + */ +#define DYNAMIC_MACRO_CURRENT_SLOT() (direction > 0 ? 1 : 2) +#define DYNAMIC_MACRO_CURRENT_LENGTH(BEGIN, POINTER) ((int)(direction * ((POINTER) - (BEGIN)))) +#define DYNAMIC_MACRO_CURRENT_CAPACITY(BEGIN, END2) ((int)(direction * ((END2) - (BEGIN)) + 1)) + +/** + * Start recording of the dynamic macro. + * + * @param[out] macro_pointer The new macro buffer iterator. + * @param[in] macro_buffer The macro buffer used to initialize macro_pointer. + */ +void dynamic_macro_record_start(keyrecord_t **macro_pointer, keyrecord_t *macro_buffer) { + dprintln("dynamic macro recording: started"); + + dynamic_macro_record_start_user(); + + clear_keyboard(); + layer_clear(); + *macro_pointer = macro_buffer; +} + +/** + * Play the dynamic macro. + * + * @param macro_buffer[in] The beginning of the macro buffer being played. + * @param macro_end[in] The element after the last macro buffer element. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + */ +void dynamic_macro_play(keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction) { + dprintf("dynamic macro: slot %d playback\n", DYNAMIC_MACRO_CURRENT_SLOT()); + + layer_state_t saved_layer_state = layer_state; + + clear_keyboard(); + layer_clear(); + + while (macro_buffer != macro_end) { + process_record(macro_buffer); + macro_buffer += direction; + } + + clear_keyboard(); + + layer_state = saved_layer_state; + + dynamic_macro_play_user(direction); +} + +/** + * Record a single key in a dynamic macro. + * + * @param macro_buffer[in] The start of the used macro buffer. + * @param macro_pointer[in,out] The current buffer position. + * @param macro2_end[in] The end of the other macro. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + * @param record[in] The current keypress. + */ +void dynamic_macro_record_key(keyrecord_t *macro_buffer, keyrecord_t **macro_pointer, keyrecord_t *macro2_end, int8_t direction, keyrecord_t *record) { + /* If we've just started recording, ignore all the key releases. */ + if (!record->event.pressed && *macro_pointer == macro_buffer) { + dprintln("dynamic macro: ignoring a leading key-up event"); + return; + } + + /* The other end of the other macro is the last buffer element it + * is safe to use before overwriting the other macro. + */ + if (*macro_pointer - direction != macro2_end) { + **macro_pointer = *record; + *macro_pointer += direction; + } else { + dynamic_macro_record_key_user(direction, record); + } + + dprintf("dynamic macro: slot %d length: %d/%d\n", DYNAMIC_MACRO_CURRENT_SLOT(), DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, *macro_pointer), DYNAMIC_MACRO_CURRENT_CAPACITY(macro_buffer, macro2_end)); +} + +/** + * End recording of the dynamic macro. Essentially just update the + * pointer to the end of the macro. + */ +void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_pointer, int8_t direction, keyrecord_t **macro_end) { + dynamic_macro_record_end_user(direction); + + /* Do not save the keys being held when stopping the recording, + * i.e. the keys used to access the layer DYN_REC_STOP is on. + */ + while (macro_pointer != macro_buffer && (macro_pointer - direction)->event.pressed) { + dprintln("dynamic macro: trimming a trailing key-down event"); + macro_pointer -= direction; + } + + dprintf("dynamic macro: slot %d saved, length: %d\n", DYNAMIC_MACRO_CURRENT_SLOT(), DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, macro_pointer)); + + *macro_end = macro_pointer; +} + +/* Handle the key events related to the dynamic macros. Should be + * called from process_record_user() like this: + * + * bool process_record_user(uint16_t keycode, keyrecord_t *record) { + * if (!process_record_dynamic_macro(keycode, record)) { + * return false; + * } + * <...THE REST OF THE FUNCTION...> + * } + */ +bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) { + /* Both macros use the same buffer but read/write on different + * ends of it. + * + * Macro1 is written left-to-right starting from the beginning of + * the buffer. + * + * Macro2 is written right-to-left starting from the end of the + * buffer. + * + * ¯o_buffer macro_end + * v v + * +------------------------------------------------------------+ + * |>>>>>> MACRO1 >>>>>> <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| + * +------------------------------------------------------------+ + * ^ ^ + * r_macro_end r_macro_buffer + * + * During the recording when one macro encounters the end of the + * other macro, the recording is stopped. Apart from this, there + * are no arbitrary limits for the macros' length in relation to + * each other: for example one can either have two medium sized + * macros or one long macro and one short macro. Or even one empty + * and one using the whole buffer. + */ + static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; + + /* Pointer to the first buffer element after the first macro. + * Initially points to the very beginning of the buffer since the + * macro is empty. */ + static keyrecord_t *macro_end = macro_buffer; + + /* The other end of the macro buffer. Serves as the beginning of + * the second macro. */ + static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; + + /* Like macro_end but for the second macro. */ + static keyrecord_t *r_macro_end = r_macro_buffer; + + /* A persistent pointer to the current macro position (iterator) + * used during the recording. */ + static keyrecord_t *macro_pointer = NULL; + + /* 0 - no macro is being recorded right now + * 1,2 - either macro 1 or 2 is being recorded */ + static uint8_t macro_id = 0; + + if (macro_id == 0) { + /* No macro recording in progress. */ + if (!record->event.pressed) { + switch (keycode) { + case DYN_REC_START1: + dynamic_macro_record_start(¯o_pointer, macro_buffer); + macro_id = 1; + return false; + case DYN_REC_START2: + dynamic_macro_record_start(¯o_pointer, r_macro_buffer); + macro_id = 2; + return false; + case DYN_MACRO_PLAY1: + dynamic_macro_play(macro_buffer, macro_end, +1); + return false; + case DYN_MACRO_PLAY2: + dynamic_macro_play(r_macro_buffer, r_macro_end, -1); + return false; + } + } + } else { + /* A macro is being recorded right now. */ + switch (keycode) { + case DYN_REC_STOP: + /* Stop the macro recording. */ + if (record->event.pressed) { /* Ignore the initial release + * just after the recoding + * starts. */ + switch (macro_id) { + case 1: + dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); + break; + case 2: + dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); + break; + } + macro_id = 0; + } + return false; +#ifdef DYNAMIC_MACRO_NO_NESTING + case DYN_MACRO_PLAY1: + case DYN_MACRO_PLAY2: + dprintln("dynamic macro: ignoring macro play key while recording"); + return false; +#endif + default: + /* Store the key in the macro buffer and process it normally. */ + switch (macro_id) { + case 1: + dynamic_macro_record_key(macro_buffer, ¯o_pointer, r_macro_end, +1, record); + break; + case 2: + dynamic_macro_record_key(r_macro_buffer, ¯o_pointer, macro_end, -1, record); + break; + } + return true; + break; + } + } + + return true; +} diff --git a/quantum/process_keycode/process_dynamic_macro.h b/quantum/process_keycode/process_dynamic_macro.h new file mode 100644 index 000000000000..39036541b8d9 --- /dev/null +++ b/quantum/process_keycode/process_dynamic_macro.h @@ -0,0 +1,41 @@ +/* Copyright 2016 Jack Humbert + * Copyright 2019 Drashna Jael're (@drashna, aka Christopher Courtney) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ +#pragma once + +#include "quantum.h" + +/* May be overridden with a custom value. Be aware that the effective + * macro length is half of this value: each keypress is recorded twice + * because of the down-event and up-event. This is not a bug, it's the + * intended behavior. + * + * Usually it should be fine to set the macro size to at least 256 but + * there have been reports of it being too much in some users' cases, + * so 128 is considered a safe default. + */ +#ifndef DYNAMIC_MACRO_SIZE +# define DYNAMIC_MACRO_SIZE 128 +#endif + +void dynamic_macro_led_blink(void); +bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record); +void dynamic_macro_record_start_user(void); +void dynamic_macro_play_user(int8_t direction); +void dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record); +void dynamic_macro_record_end_user(int8_t direction); diff --git a/quantum/quantum.c b/quantum/quantum.c index e0c0f8bde6b9..a2ebbdd878a4 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -26,7 +26,7 @@ #ifdef BACKLIGHT_ENABLE # include "backlight.h" - extern backlight_config_t backlight_config; +extern backlight_config_t backlight_config; #endif #ifdef FAUXCLICKY_ENABLE @@ -89,7 +89,7 @@ static void do_code16(uint16_t code, void (*f)(uint8_t)) { uint8_t mods_to_send = 0; - if (code & QK_RMODS_MIN) { // Right mod flag is set + if (code & QK_RMODS_MIN) { // Right mod flag is set if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL); if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT); if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT); @@ -222,6 +222,10 @@ bool process_record_quantum(keyrecord_t *record) { // Must run first to be able to mask key_up events. process_key_lock(&keycode, record) && #endif +#if defined(DYNAMIC_MACRO_ENABLE) && !defined(DYNAMIC_MACRO_USER_CALL) + // Must run asap to ensure all keypresses are recorded. + process_dynamic_macro(keycode, record) && +#endif #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY) process_clicky(keycode, record) && #endif // AUDIO_CLICKY @@ -566,7 +570,7 @@ bool process_record_quantum(keyrecord_t *record) { keymap_config.swap_backslash_backspace = true; break; case MAGIC_HOST_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys + clear_keyboard(); // clear first buffer to prevent stuck keys keymap_config.nkro = true; break; case MAGIC_SWAP_ALT_GUI: @@ -609,7 +613,7 @@ bool process_record_quantum(keyrecord_t *record) { keymap_config.swap_backslash_backspace = false; break; case MAGIC_UNHOST_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys + clear_keyboard(); // clear first buffer to prevent stuck keys keymap_config.nkro = false; break; case MAGIC_UNSWAP_ALT_GUI: @@ -647,7 +651,7 @@ bool process_record_quantum(keyrecord_t *record) { #endif break; case MAGIC_TOGGLE_NKRO: - clear_keyboard(); // clear first buffer to prevent stuck keys + clear_keyboard(); // clear first buffer to prevent stuck keys keymap_config.nkro = !keymap_config.nkro; break; case MAGIC_EE_HANDS_LEFT: diff --git a/quantum/quantum.h b/quantum/quantum.h index 0a0c94d9d6aa..a993eb2c8e7a 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -150,6 +150,10 @@ extern layer_state_t layer_state; #include "dip_switch.h" #endif +#ifdef DYNAMIC_MACRO_ENABLE + #include "process_dynamic_macro.h" +#endif + // Function substitutions to ease GPIO manipulation #if defined(__AVR__) diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 5fac6a5cae88..51a7e290fa62 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -505,6 +505,13 @@ enum quantum_keycodes { MAGIC_EE_HANDS_LEFT, MAGIC_EE_HANDS_RIGHT, + // Dynamic Macros + DYN_REC_START1, + DYN_REC_START2, + DYN_REC_STOP, + DYN_MACRO_PLAY1, + DYN_MACRO_PLAY2, + // always leave at the end SAFE_RANGE }; @@ -757,4 +764,11 @@ enum quantum_keycodes { # define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF) #endif -#endif // QUANTUM_KEYCODES_H +// Dynamic Macros aliases +#define DM_REC1 DYN_REC_START1 +#define DM_REC2 DYN_REC_START2 +#define DM_RSTP DYN_REC_STOP +#define DM_PLY1 DYN_MACRO_PLAY1 +#define DM_PLY2 DYN_MACRO_PLAY2 + +#endif // QUANTUM_KEYCODES_H diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 4b37367575df..8211b2fd8046 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -204,6 +204,9 @@ ifeq ($(strip $(SHARED_EP_ENABLE)), yes) TMK_COMMON_DEFS += -DSHARED_EP_ENABLE endif +ifeq ($(strip $(LTO_ENABLE)), yes) + LINK_TIME_OPTIMIZATION_ENABLE = yes +endif ifeq ($(strip $(LINK_TIME_OPTIMIZATION_ENABLE)), yes) EXTRAFLAGS += -flto diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index ffcf0957f358..70032d69fa52 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -40,6 +40,8 @@ #include "report.h" #include "usb_descriptor.h" +// clang-format off + /* * HID report descriptors */ @@ -49,46 +51,46 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #else const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = { #endif - HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop - HID_RI_USAGE(8, 0x06), // Keyboard - HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x06), // Keyboard + HID_RI_COLLECTION(8, 0x01), // Application #ifdef KEYBOARD_SHARED_EP - HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD), + HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD), #endif - // Modifiers (8 bits) - HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad - HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control - HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x08), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Reserved (1 byte) - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_CONSTANT), - // Keycodes (6 bytes) - HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad - HID_RI_USAGE_MINIMUM(8, 0x00), - HID_RI_USAGE_MAXIMUM(8, 0xFF), - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), - HID_RI_REPORT_COUNT(8, 0x06), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), - - // Status LEDs (5 bits) - HID_RI_USAGE_PAGE(8, 0x08), // LED - HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock - HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana - HID_RI_REPORT_COUNT(8, 0x05), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), - // LED padding (3 bits) - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x03), - HID_RI_OUTPUT(8, HID_IOF_CONSTANT), + // Modifiers (8 bits) + HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad + HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control + HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x08), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + // Reserved (1 byte) + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_CONSTANT), + // Keycodes (6 bytes) + HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad + HID_RI_USAGE_MINIMUM(8, 0x00), + HID_RI_USAGE_MAXIMUM(8, 0xFF), + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), + HID_RI_REPORT_COUNT(8, 0x06), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), + + // Status LEDs (5 bits) + HID_RI_USAGE_PAGE(8, 0x08), // LED + HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock + HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana + HID_RI_REPORT_COUNT(8, 0x05), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + // LED padding (3 bits) + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x03), + HID_RI_OUTPUT(8, HID_IOF_CONSTANT), HID_RI_END_COLLECTION(0), #ifndef KEYBOARD_SHARED_EP }; @@ -101,54 +103,54 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = { const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { # define SHARED_REPORT_STARTED # endif - HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop - HID_RI_USAGE(8, 0x02), // Mouse - HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x02), // Mouse + HID_RI_COLLECTION(8, 0x01), // Application # ifdef MOUSE_SHARED_EP - HID_RI_REPORT_ID(8, REPORT_ID_MOUSE), + HID_RI_REPORT_ID(8, REPORT_ID_MOUSE), # endif - HID_RI_USAGE(8, 0x01), // Pointer - HID_RI_COLLECTION(8, 0x00), // Physical - // Buttons (5 bits) - HID_RI_USAGE_PAGE(8, 0x09), // Button - HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 - HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5 - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x05), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Button padding (3 bits) - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x03), - HID_RI_INPUT(8, HID_IOF_CONSTANT), - - // X/Y position (2 bytes) - HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop - HID_RI_USAGE(8, 0x30), // X - HID_RI_USAGE(8, 0x31), // Y - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), - HID_RI_REPORT_COUNT(8, 0x02), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - - // Vertical wheel (1 byte) - HID_RI_USAGE(8, 0x38), // Wheel - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - // Horizontal wheel (1 byte) - HID_RI_USAGE_PAGE(8, 0x0C), // Consumer - HID_RI_USAGE(16, 0x0238), // AC Pan - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - HID_RI_END_COLLECTION(0), + HID_RI_USAGE(8, 0x01), // Pointer + HID_RI_COLLECTION(8, 0x00), // Physical + // Buttons (5 bits) + HID_RI_USAGE_PAGE(8, 0x09), // Button + HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 + HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5 + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x05), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + // Button padding (3 bits) + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x03), + HID_RI_INPUT(8, HID_IOF_CONSTANT), + + // X/Y position (2 bytes) + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x30), // X + HID_RI_USAGE(8, 0x31), // Y + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, 0x02), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + + // Vertical wheel (1 byte) + HID_RI_USAGE(8, 0x38), // Wheel + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + // Horizontal wheel (1 byte) + HID_RI_USAGE_PAGE(8, 0x0C), // Consumer + HID_RI_USAGE(16, 0x0238), // AC Pan + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0), # ifndef MOUSE_SHARED_EP }; @@ -160,68 +162,68 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #endif #ifdef EXTRAKEY_ENABLE - HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop - HID_RI_USAGE(8, 0x80), // System Control - HID_RI_COLLECTION(8, 0x01), // Application - HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM), - HID_RI_USAGE_MINIMUM(16, 0x0081), // System Power Down - HID_RI_USAGE_MAXIMUM(16, 0x0083), // System Wake Up - HID_RI_LOGICAL_MINIMUM(16, 0x0001), - HID_RI_LOGICAL_MAXIMUM(16, 0x0003), - HID_RI_REPORT_COUNT(8, 1), - HID_RI_REPORT_SIZE(8, 16), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x80), // System Control + HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM), + HID_RI_USAGE_MINIMUM(16, 0x0081), // System Power Down + HID_RI_USAGE_MAXIMUM(16, 0x0083), // System Wake Up + HID_RI_LOGICAL_MINIMUM(16, 0x0001), + HID_RI_LOGICAL_MAXIMUM(16, 0x0003), + HID_RI_REPORT_COUNT(8, 1), + HID_RI_REPORT_SIZE(8, 16), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), HID_RI_END_COLLECTION(0), - HID_RI_USAGE_PAGE(8, 0x0C), // Consumer - HID_RI_USAGE(8, 0x01), // Consumer Control - HID_RI_COLLECTION(8, 0x01), // Application - HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER), - HID_RI_USAGE_MINIMUM(16, 0x0001), // Consumer Control - HID_RI_USAGE_MAXIMUM(16, 0x029C), // AC Distribute Vertically - HID_RI_LOGICAL_MINIMUM(16, 0x0001), - HID_RI_LOGICAL_MAXIMUM(16, 0x029C), - HID_RI_REPORT_COUNT(8, 1), - HID_RI_REPORT_SIZE(8, 16), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), + HID_RI_USAGE_PAGE(8, 0x0C), // Consumer + HID_RI_USAGE(8, 0x01), // Consumer Control + HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER), + HID_RI_USAGE_MINIMUM(16, 0x0001), // Consumer Control + HID_RI_USAGE_MAXIMUM(16, 0x029C), // AC Distribute Vertically + HID_RI_LOGICAL_MINIMUM(16, 0x0001), + HID_RI_LOGICAL_MAXIMUM(16, 0x029C), + HID_RI_REPORT_COUNT(8, 1), + HID_RI_REPORT_SIZE(8, 16), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), HID_RI_END_COLLECTION(0), #endif #ifdef NKRO_ENABLE - HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop - HID_RI_USAGE(8, 0x06), // Keyboard - HID_RI_COLLECTION(8, 0x01), // Application - HID_RI_REPORT_ID(8, REPORT_ID_NKRO), - // Modifiers (8 bits) - HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad - HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control - HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x08), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Keycodes - HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad - HID_RI_USAGE_MINIMUM(8, 0x00), - HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1), - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS * 8), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - - // Status LEDs (5 bits) - HID_RI_USAGE_PAGE(8, 0x08), // LED - HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock - HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana - HID_RI_REPORT_COUNT(8, 0x05), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), - // LED padding (3 bits) - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x03), - HID_RI_OUTPUT(8, HID_IOF_CONSTANT), + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x06), // Keyboard + HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_REPORT_ID(8, REPORT_ID_NKRO), + // Modifiers (8 bits) + HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad + HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control + HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, 0x08), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + // Keycodes + HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad + HID_RI_USAGE_MINIMUM(8, 0x00), + HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1), + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS * 8), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + + // Status LEDs (5 bits) + HID_RI_USAGE_PAGE(8, 0x08), // LED + HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock + HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana + HID_RI_REPORT_COUNT(8, 0x05), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + // LED padding (3 bits) + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x03), + HID_RI_OUTPUT(8, HID_IOF_CONSTANT), HID_RI_END_COLLECTION(0), #endif #ifdef SHARED_EP_ENABLE @@ -230,46 +232,48 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #ifdef RAW_ENABLE const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = { - HID_RI_USAGE_PAGE(16, 0xFF60), // Vendor Defined - HID_RI_USAGE(8, 0x61), // Vendor Defined - HID_RI_COLLECTION(8, 0x01), // Application - // Data to host - HID_RI_USAGE(8, 0x62), // Vendor Defined - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), - HID_RI_REPORT_COUNT(8, RAW_EPSIZE), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Data from host - HID_RI_USAGE(8, 0x63), // Vendor Defined - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), - HID_RI_REPORT_COUNT(8, RAW_EPSIZE), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + HID_RI_USAGE_PAGE(16, 0xFF60), // Vendor Defined + HID_RI_USAGE(8, 0x61), // Vendor Defined + HID_RI_COLLECTION(8, 0x01), // Application + // Data to host + HID_RI_USAGE(8, 0x62), // Vendor Defined + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), + HID_RI_REPORT_COUNT(8, RAW_EPSIZE), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + + // Data from host + HID_RI_USAGE(8, 0x63), // Vendor Defined + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), + HID_RI_REPORT_COUNT(8, RAW_EPSIZE), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), HID_RI_END_COLLECTION(0), }; #endif #ifdef CONSOLE_ENABLE const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { - HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible) - HID_RI_USAGE(8, 0x74), // Vendor Defined (PJRC Teensy compatible) - HID_RI_COLLECTION(8, 0x01), // Application - // Data to host - HID_RI_USAGE(8, 0x75), // Vendor Defined - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), - HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Data from host - HID_RI_USAGE(8, 0x76), // Vendor Defined - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), - HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), + HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible) + HID_RI_USAGE(8, 0x74), // Vendor Defined (PJRC Teensy compatible) + HID_RI_COLLECTION(8, 0x01), // Application + // Data to host + HID_RI_USAGE(8, 0x75), // Vendor Defined + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), + HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + + // Data from host + HID_RI_USAGE(8, 0x76), // Vendor Defined + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), + HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), HID_RI_END_COLLECTION(0), }; #endif @@ -277,26 +281,33 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { /* * Device descriptor */ -const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, - .USBSpecification = VERSION_BCD(1, 1, 0), +const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { + .Header = { + .Size = sizeof(USB_Descriptor_Device_t), + .Type = DTYPE_Device + }, + .USBSpecification = VERSION_BCD(1, 1, 0), + #if VIRTSER_ENABLE - .Class = USB_CSCP_IADDeviceClass, - .SubClass = USB_CSCP_IADDeviceSubclass, - .Protocol = USB_CSCP_IADDeviceProtocol, + .Class = USB_CSCP_IADDeviceClass, + .SubClass = USB_CSCP_IADDeviceSubclass, + .Protocol = USB_CSCP_IADDeviceProtocol, #else - .Class = USB_CSCP_NoDeviceClass, - .SubClass = USB_CSCP_NoDeviceSubclass, - .Protocol = USB_CSCP_NoDeviceProtocol, + .Class = USB_CSCP_NoDeviceClass, + .SubClass = USB_CSCP_NoDeviceSubclass, + .Protocol = USB_CSCP_NoDeviceProtocol, #endif - .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, - // Specified in config.h - .VendorID = VENDOR_ID, - .ProductID = PRODUCT_ID, - .ReleaseNumber = DEVICE_VER, - .ManufacturerStrIndex = 0x01, - .ProductStrIndex = 0x02, - .SerialNumStrIndex = 0x03, - .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS}; + + .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, + // Specified in config.h + .VendorID = VENDOR_ID, + .ProductID = PRODUCT_ID, + .ReleaseNumber = DEVICE_VER, + .ManufacturerStrIndex = 0x01, + .ProductStrIndex = 0x02, + .SerialNumStrIndex = 0x03, + .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS +}; #ifndef USB_MAX_POWER_CONSUMPTION # define USB_MAX_POWER_CONSUMPTION 500 @@ -309,197 +320,540 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {.Header = {. /* * Configuration descriptors */ -const USB_Descriptor_Configuration_t PROGMEM - ConfigurationDescriptor = - { - .Config = {.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), .TotalInterfaces = TOTAL_INTERFACES, .ConfigurationNumber = 1, .ConfigurationStrIndex = NO_DESCRIPTOR, .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP), .MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)}, - +const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { + .Config = { + .Header = { + .Size = sizeof(USB_Descriptor_Configuration_Header_t), + .Type = DTYPE_Configuration + }, + .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), + .TotalInterfaces = TOTAL_INTERFACES, + .ConfigurationNumber = 1, + .ConfigurationStrIndex = NO_DESCRIPTOR, + .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP), + .MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION) + }, #ifndef KEYBOARD_SHARED_EP - /* - * Keyboard - */ - .Keyboard_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - .InterfaceNumber = KEYBOARD_INTERFACE, - .AlternateSetting = 0x00, - .TotalEndpoints = 1, - .Class = HID_CSCP_HIDClass, - .SubClass = HID_CSCP_BootSubclass, - .Protocol = HID_CSCP_KeyboardBootProtocol, - - .InterfaceStrIndex = NO_DESCRIPTOR}, - .Keyboard_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(KeyboardReport)}, - .Keyboard_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = KEYBOARD_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS}, + /* + * Keyboard + */ + .Keyboard_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = KEYBOARD_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_BootSubclass, + .Protocol = HID_CSCP_KeyboardBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Keyboard_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(KeyboardReport) + }, + .Keyboard_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = KEYBOARD_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + }, #endif #ifdef RAW_ENABLE - /* - * Raw HID - */ - .Raw_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = RAW_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 2, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_NonBootSubclass, .Protocol = HID_CSCP_NonBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR}, - .Raw_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(RawReport)}, - .Raw_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | RAW_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = RAW_EPSIZE, .PollingIntervalMS = 0x01}, - .Raw_OUTEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_OUT | RAW_OUT_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = RAW_EPSIZE, .PollingIntervalMS = 0x01}, + /* + * Raw HID + */ + .Raw_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = RAW_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 2, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Raw_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(RawReport) + }, + .Raw_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | RAW_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = RAW_EPSIZE, + .PollingIntervalMS = 0x01 + }, + .Raw_OUTEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_OUT | RAW_OUT_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = RAW_EPSIZE, + .PollingIntervalMS = 0x01 + }, #endif #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP) - /* - * Mouse - */ - .Mouse_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = MOUSE_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 1, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_BootSubclass, .Protocol = HID_CSCP_MouseBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR}, - .Mouse_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(MouseReport)}, - .Mouse_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MOUSE_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS}, + /* + * Mouse + */ + .Mouse_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = MOUSE_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_BootSubclass, + .Protocol = HID_CSCP_MouseBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Mouse_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(MouseReport) + }, + .Mouse_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = MOUSE_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + }, #endif #ifdef SHARED_EP_ENABLE - /* - * Shared - */ - .Shared_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - .InterfaceNumber = SHARED_INTERFACE, - .AlternateSetting = 0x00, - .TotalEndpoints = 1, - .Class = HID_CSCP_HIDClass, + /* + * Shared + */ + .Shared_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = SHARED_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, # ifdef KEYBOARD_SHARED_EP - .SubClass = HID_CSCP_BootSubclass, - .Protocol = HID_CSCP_KeyboardBootProtocol, + .SubClass = HID_CSCP_BootSubclass, + .Protocol = HID_CSCP_KeyboardBootProtocol, # else - .SubClass = HID_CSCP_NonBootSubclass, - .Protocol = HID_CSCP_NonBootProtocol, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, # endif - .InterfaceStrIndex = NO_DESCRIPTOR}, - .Shared_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(SharedReport)}, - .Shared_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = SHARED_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS}, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Shared_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(SharedReport) + }, + .Shared_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = SHARED_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + }, #endif #ifdef CONSOLE_ENABLE - /* - * Console - */ - .Console_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CONSOLE_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 2, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_NonBootSubclass, .Protocol = HID_CSCP_NonBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR}, - .Console_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(ConsoleReport)}, - .Console_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CONSOLE_EPSIZE, .PollingIntervalMS = 0x01}, - .Console_OUTEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CONSOLE_EPSIZE, .PollingIntervalMS = 0x01}, + /* + * Console + */ + .Console_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = CONSOLE_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 2, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Console_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(ConsoleReport) + }, + .Console_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CONSOLE_EPSIZE, + .PollingIntervalMS = 0x01 + }, + .Console_OUTEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CONSOLE_EPSIZE, + .PollingIntervalMS = 0x01 + }, #endif #ifdef MIDI_ENABLE - /* - * MIDI - */ - .Audio_Interface_Association = - { - .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation}, - .FirstInterfaceIndex = AC_INTERFACE, - .TotalInterfaces = 2, - .Class = AUDIO_CSCP_AudioClass, - .SubClass = AUDIO_CSCP_ControlSubclass, - .Protocol = AUDIO_CSCP_ControlProtocol, - .IADStrIndex = NO_DESCRIPTOR, - }, - .Audio_ControlInterface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - - .InterfaceNumber = AC_INTERFACE, - .AlternateSetting = 0, - .TotalEndpoints = 0, - .Class = AUDIO_CSCP_AudioClass, - .SubClass = AUDIO_CSCP_ControlSubclass, - .Protocol = AUDIO_CSCP_ControlProtocol, - .InterfaceStrIndex = NO_DESCRIPTOR}, - .Audio_ControlInterface_SPC = - { - .Header = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = AUDIO_DTYPE_CSInterface}, - .Subtype = AUDIO_DSUBTYPE_CSInterface_Header, - .ACSpecification = VERSION_BCD(1, 0, 0), - .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t), - .InCollection = 1, - .InterfaceNumber = AS_INTERFACE, - }, - .Audio_StreamInterface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - - .InterfaceNumber = AS_INTERFACE, - .AlternateSetting = 0, - .TotalEndpoints = 2, - .Class = AUDIO_CSCP_AudioClass, - .SubClass = AUDIO_CSCP_MIDIStreamingSubclass, - .Protocol = AUDIO_CSCP_StreamingProtocol, - .InterfaceStrIndex = NO_DESCRIPTOR}, - .Audio_StreamInterface_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_General, .AudioSpecification = VERSION_BCD(1, 0, 0), .TotalLength = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC) + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t) - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)}, - .MIDI_In_Jack_Emb = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, .JackType = MIDI_JACKTYPE_Embedded, .JackID = 0x01, .JackStrIndex = NO_DESCRIPTOR}, - .MIDI_In_Jack_Ext = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, .JackType = MIDI_JACKTYPE_External, .JackID = 0x02, .JackStrIndex = NO_DESCRIPTOR}, - .MIDI_Out_Jack_Emb = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, .JackType = MIDI_JACKTYPE_Embedded, .JackID = 0x03, .NumberOfPins = 1, .SourceJackID = {0x02}, .SourcePinID = {0x01}, .JackStrIndex = NO_DESCRIPTOR}, - .MIDI_Out_Jack_Ext = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, .JackType = MIDI_JACKTYPE_External, .JackID = 0x04, .NumberOfPins = 1, .SourceJackID = {0x01}, .SourcePinID = {0x01}, .JackStrIndex = NO_DESCRIPTOR}, - .MIDI_In_Jack_Endpoint = {.Endpoint = {.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, .EndpointAddress = MIDI_STREAM_OUT_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MIDI_STREAM_EPSIZE, .PollingIntervalMS = 0x05}, - - .Refresh = 0, - .SyncEndpointNumber = 0}, - .MIDI_In_Jack_Endpoint_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = AUDIO_DSUBTYPE_CSEndpoint_General}, .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, .TotalEmbeddedJacks = 0x01, .AssociatedJackID = {0x01}}, - .MIDI_Out_Jack_Endpoint = {.Endpoint = {.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, .EndpointAddress = MIDI_STREAM_IN_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MIDI_STREAM_EPSIZE, .PollingIntervalMS = 0x05}, - - .Refresh = 0, - .SyncEndpointNumber = 0}, - .MIDI_Out_Jack_Endpoint_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = AUDIO_DTYPE_CSEndpoint}, .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, .TotalEmbeddedJacks = 0x01, .AssociatedJackID = {0x03}}, + /* + * MIDI + */ + .Audio_Interface_Association = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_Association_t), + .Type = DTYPE_InterfaceAssociation + }, + .FirstInterfaceIndex = AC_INTERFACE, + .TotalInterfaces = 2, + .Class = AUDIO_CSCP_AudioClass, + .SubClass = AUDIO_CSCP_ControlSubclass, + .Protocol = AUDIO_CSCP_ControlProtocol, + .IADStrIndex = NO_DESCRIPTOR, + }, + .Audio_ControlInterface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = AC_INTERFACE, + .AlternateSetting = 0, + .TotalEndpoints = 0, + .Class = AUDIO_CSCP_AudioClass, + .SubClass = AUDIO_CSCP_ControlSubclass, + .Protocol = AUDIO_CSCP_ControlProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Audio_ControlInterface_SPC = { + .Header = { + .Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_Header, + .ACSpecification = VERSION_BCD(1, 0, 0), + .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t), + .InCollection = 1, + .InterfaceNumber = AS_INTERFACE, + }, + .Audio_StreamInterface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = AS_INTERFACE, + .AlternateSetting = 0, + .TotalEndpoints = 2, + .Class = AUDIO_CSCP_AudioClass, + .SubClass = AUDIO_CSCP_MIDIStreamingSubclass, + .Protocol = AUDIO_CSCP_StreamingProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Audio_StreamInterface_SPC = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_General, + .AudioSpecification = VERSION_BCD(1, 0, 0), + .TotalLength = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC) + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t) - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC) + }, + .MIDI_In_Jack_Emb = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_InputJack_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, + .JackType = MIDI_JACKTYPE_Embedded, + .JackID = 0x01, + .JackStrIndex = NO_DESCRIPTOR + }, + .MIDI_In_Jack_Ext = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_InputJack_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, + .JackType = MIDI_JACKTYPE_External, + .JackID = 0x02, + .JackStrIndex = NO_DESCRIPTOR + }, + .MIDI_Out_Jack_Emb = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, + .JackType = MIDI_JACKTYPE_Embedded, + .JackID = 0x03, + .NumberOfPins = 1, + .SourceJackID = {0x02}, + .SourcePinID = {0x01}, + .JackStrIndex = NO_DESCRIPTOR + }, + .MIDI_Out_Jack_Ext = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), + .Type = AUDIO_DTYPE_CSInterface + }, + .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, + .JackType = MIDI_JACKTYPE_External, + .JackID = 0x04, + .NumberOfPins = 1, + .SourceJackID = {0x01}, + .SourcePinID = {0x01}, + .JackStrIndex = NO_DESCRIPTOR + }, + .MIDI_In_Jack_Endpoint = { + .Endpoint = { + .Header = { + .Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = MIDI_STREAM_OUT_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = MIDI_STREAM_EPSIZE, + .PollingIntervalMS = 0x05 + }, + .Refresh = 0, + .SyncEndpointNumber = 0 + }, + .MIDI_In_Jack_Endpoint_SPC = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), + .Type = AUDIO_DTYPE_CSEndpoint + }, + .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, + .TotalEmbeddedJacks = 0x01, + .AssociatedJackID = {0x01} + }, + .MIDI_Out_Jack_Endpoint = { + .Endpoint = { + .Header = { + .Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = MIDI_STREAM_IN_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = MIDI_STREAM_EPSIZE, + .PollingIntervalMS = 0x05 + }, + .Refresh = 0, + .SyncEndpointNumber = 0 + }, + .MIDI_Out_Jack_Endpoint_SPC = { + .Header = { + .Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), + .Type = AUDIO_DTYPE_CSEndpoint + }, + .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, + .TotalEmbeddedJacks = 0x01, + .AssociatedJackID = {0x03} + }, #endif #ifdef VIRTSER_ENABLE - /* - * Virtual Serial - */ - .CDC_Interface_Association = - { - .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation}, - .FirstInterfaceIndex = CCI_INTERFACE, - .TotalInterfaces = 2, - .Class = CDC_CSCP_CDCClass, - .SubClass = CDC_CSCP_ACMSubclass, - .Protocol = CDC_CSCP_ATCommandProtocol, - .IADStrIndex = NO_DESCRIPTOR, - }, - .CDC_CCI_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CCI_INTERFACE, .AlternateSetting = 0, .TotalEndpoints = 1, .Class = CDC_CSCP_CDCClass, .SubClass = CDC_CSCP_ACMSubclass, .Protocol = CDC_CSCP_ATCommandProtocol, .InterfaceStrIndex = NO_DESCRIPTOR}, - .CDC_Functional_Header = - { - .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = CDC_DTYPE_CSInterface}, - .Subtype = 0x00, - .CDCSpecification = VERSION_BCD(1, 1, 0), - }, - .CDC_Functional_ACM = - { - .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = CDC_DTYPE_CSInterface}, - .Subtype = 0x02, - .Capabilities = 0x02, - }, - .CDC_Functional_Union = - { - .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = CDC_DTYPE_CSInterface}, - .Subtype = 0x06, - .MasterInterfaceNumber = CCI_INTERFACE, - .SlaveInterfaceNumber = CDI_INTERFACE, - }, - .CDC_NotificationEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_NOTIFICATION_EPADDR, .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_NOTIFICATION_EPSIZE, .PollingIntervalMS = 0xFF}, - .CDC_DCI_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CDI_INTERFACE, .AlternateSetting = 0, .TotalEndpoints = 2, .Class = CDC_CSCP_CDCDataClass, .SubClass = CDC_CSCP_NoDataSubclass, .Protocol = CDC_CSCP_NoDataProtocol, .InterfaceStrIndex = NO_DESCRIPTOR}, - .CDC_DataOutEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_OUT_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_EPSIZE, .PollingIntervalMS = 0x05}, - .CDC_DataInEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_IN_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_EPSIZE, .PollingIntervalMS = 0x05}, + /* + * Virtual Serial + */ + .CDC_Interface_Association = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_Association_t), + .Type = DTYPE_InterfaceAssociation + }, + .FirstInterfaceIndex = CCI_INTERFACE, + .TotalInterfaces = 2, + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_ATCommandProtocol, + .IADStrIndex = NO_DESCRIPTOR, + }, + .CDC_CCI_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = CCI_INTERFACE, + .AlternateSetting = 0, + .TotalEndpoints = 1, + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_ATCommandProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .CDC_Functional_Header = { + .Header = { + .Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), + .Type = CDC_DTYPE_CSInterface + }, + .Subtype = 0x00, + .CDCSpecification = VERSION_BCD(1, 1, 0), + }, + .CDC_Functional_ACM = { + .Header = { + .Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), + .Type = CDC_DTYPE_CSInterface + }, + .Subtype = 0x02, + .Capabilities = 0x02, + }, + .CDC_Functional_Union = { + .Header = { + .Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), + .Type = CDC_DTYPE_CSInterface + }, + .Subtype = 0x06, + .MasterInterfaceNumber = CCI_INTERFACE, + .SlaveInterfaceNumber = CDI_INTERFACE, + }, + .CDC_NotificationEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = CDC_NOTIFICATION_EPADDR, + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_NOTIFICATION_EPSIZE, + .PollingIntervalMS = 0xFF + }, + .CDC_DCI_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = CDI_INTERFACE, + .AlternateSetting = 0, + .TotalEndpoints = 2, + .Class = CDC_CSCP_CDCDataClass, + .SubClass = CDC_CSCP_NoDataSubclass, + .Protocol = CDC_CSCP_NoDataProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .CDC_DataOutEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = CDC_OUT_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_EPSIZE, + .PollingIntervalMS = 0x05 + }, + .CDC_DataInEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = CDC_IN_EPADDR, + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_EPSIZE, + .PollingIntervalMS = 0x05 + }, #endif }; /* * String descriptors */ -const USB_Descriptor_String_t PROGMEM LanguageString = {.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, .UnicodeString = {LANGUAGE_ID_ENG}}; +const USB_Descriptor_String_t PROGMEM LanguageString = { + .Header = { + .Size = USB_STRING_LEN(1), + .Type = DTYPE_String + }, + .UnicodeString = {LANGUAGE_ID_ENG} +}; -const USB_Descriptor_String_t PROGMEM ManufacturerString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER)) - 1), // Subtract 1 for null terminator - .Type = DTYPE_String}, - .UnicodeString = LSTR(MANUFACTURER)}; +const USB_Descriptor_String_t PROGMEM ManufacturerString = { + .Header = { + .Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER)) - 1), // Subtract 1 for null terminator + .Type = DTYPE_String + }, + .UnicodeString = LSTR(MANUFACTURER) +}; -const USB_Descriptor_String_t PROGMEM ProductString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT)) - 1), // Subtract 1 for null terminator - .Type = DTYPE_String}, - .UnicodeString = LSTR(PRODUCT)}; +const USB_Descriptor_String_t PROGMEM ProductString = { + .Header = { + .Size = USB_STRING_LEN(sizeof(STR(PRODUCT)) - 1), // Subtract 1 for null terminator + .Type = DTYPE_String + }, + .UnicodeString = LSTR(PRODUCT) +}; #ifndef SERIAL_NUMBER # define SERIAL_NUMBER 0 #endif -const USB_Descriptor_String_t PROGMEM SerialNumberString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER)) - 1), // Subtract 1 for null terminator - .Type = DTYPE_String}, - .UnicodeString = LSTR(SERIAL_NUMBER)}; +const USB_Descriptor_String_t PROGMEM SerialNumberString = { + .Header = { + .Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER)) - 1), // Subtract 1 for null terminator + .Type = DTYPE_String + }, + .UnicodeString = LSTR(SERIAL_NUMBER) +}; + +// clang-format on /** * This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" diff --git a/users/dshields/dshields.h b/users/dshields/dshields.h index a65ccfea0046..d8f76e8c0088 100644 --- a/users/dshields/dshields.h +++ b/users/dshields/dshields.h @@ -21,20 +21,27 @@ // mod-tap keys #define MT_SPC SFT_T(KC_SPC) +// LED/RGB controls #ifdef KEYBOARD_planck_light #define LGT_TOG RGB_TOG #define LGT_MOD RGB_MOD #define LGT_BRT _______ + #define LGT_INC RGB_HUI + #define LGT_DEC RGB_HUD #endif #ifdef KEYBOARD_planck_rev3 #define LGT_TOG BL_TOGG #define LGT_MOD BL_STEP #define LGT_BRT BL_BRTG + #define LGT_INC BL_INC + #define LGT_DEC BL_DEC #endif #ifdef KEYBOARD_planck_rev6 #define LGT_TOG _______ #define LGT_MOD _______ #define LGT_BRT _______ + #define LGT_INC _______ + #define LGT_DEC _______ #endif enum layers { DEF, LWR, RSE, FUN }; diff --git a/util/travis_build.sh b/util/travis_build.sh index 225c8548f525..6d5dbed6843d 100755 --- a/util/travis_build.sh +++ b/util/travis_build.sh @@ -1,57 +1,42 @@ #!/bin/bash -# if docker is installed - patch calls to within the qmk docker image -if command -v docker >/dev/null; then - function make() { - docker run --rm -e MAKEFLAGS="$MAKEFLAGS" -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container make "$@" - } +source util/travis_utils.sh + +NUM_CORE_CHANGES=$(echo "$QMK_CHANGES" | grep -Ecv -e '^(docs/)' -e '^(keyboards/)' -e '^(layouts/)' -e '^(util/)' -e '^(lib/python/)' -e '^(bin/qmk)' -e '^(requirements.txt)' -e '(.travis.yml)') + +if [[ "$TRAVIS_COMMIT_MESSAGE" == *"[skip build]"* ]]; then + echo "Skipping due to commit message" + exit 0 fi -# test force push -#TRAVIS_COMMIT_RANGE="c287f1bfc5c8...81f62atc4c1d" +if [ "$LOCAL_BRANCH" == "master" ] || [ "$NUM_CORE_CHANGES" != "0" ]; then + echo "Making default keymaps for all keyboards" + make all:default + exit $? +fi -TRAVIS_COMMIT_MESSAGE="${TRAVIS_COMMIT_MESSAGE:-none}" -TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-HEAD~1..HEAD}" -MAKE_ALL="make all:default" +exit_code=0 -if [[ "$TRAVIS_COMMIT_MESSAGE" != *"[skip build]"* ]] ; then - exit_code=0 - git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} - if [ $? -eq 128 ]; then - # We don't know what changed so just build the default keymaps - echo "Making default keymaps for all keyboards (fallback)" - eval $MAKE_ALL +for KB in $(make list-keyboards); do + KEYBOARD_CHANGES=$(echo "$QMK_CHANGES" | grep -E '^(keyboards/'${KB}'/)') + if [[ -z "$KEYBOARD_CHANGES" ]]; then + # skip as no changes for this keyboard + continue + fi + + KEYMAP_ONLY=$(echo "$KEYBOARD_CHANGES" | grep -cv /keymaps/) + if [[ $KEYMAP_ONLY -gt 0 ]]; then + echo "Making all keymaps for $KB" + make ${KB}:all : $((exit_code = $exit_code + $?)) else - NEFM=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} | grep -Ev '^(keyboards/)' | grep -Ev '^(docs/)' | grep -Ev '^(lib/python/)' | grep -Ev '^(bin/qmk)' | grep -Ev '^(requirements.txt)' | grep -Ev '^(util/)' | wc -l) - BRANCH=$(git rev-parse --abbrev-ref HEAD) - # is this branch master or a "non docs, non keyboards" change - if [ $NEFM -gt 0 -o "$BRANCH" = "master" ]; then - echo "Making default keymaps for all keyboards" - eval $MAKE_ALL + CHANGED_KEYMAPS=$(echo "$KEYBOARD_CHANGES" | grep -oP '(?<=keyboards/'${KB}'/keymaps/)([a-zA-Z0-9_-]+)(?=\/)') + for KM in $CHANGED_KEYMAPS ; do + echo "Making $KM for $KB" + make ${KB}:${KM} : $((exit_code = $exit_code + $?)) - else - # keyboards project format - # /keyboards/board1/rev/keymaps/ - # /keyboards/board2/keymaps/ - # ensure we strip everything off after and including the keymaps folder to get board and/or revision - MKB=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} | grep -oP '(?<=keyboards\/)([a-zA-Z0-9_\/]+)(?=\/)' | sed 's^/keymaps/.*^^' | sort -u) - for KB in $MKB ; do - KEYMAP_ONLY=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} | grep -Ev '^(keyboards/'${KB}'/keymaps/)' | wc -l) - if [[ $KEYMAP_ONLY -gt 0 ]]; then - echo "Making all keymaps for $KB" - make ${KB}:all - : $((exit_code = $exit_code + $?)) - else - MKM=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} | grep -oP '(?<=keyboards/'${KB}'/keymaps/)([a-zA-Z0-9_]+)(?=\/)' | sort -u) - for KM in $MKM ; do - echo "Making $KM for $KB" - make ${KB}:${KM} - : $((exit_code = $exit_code + $?)) - done - fi - done - fi + done fi - exit $exit_code -fi +done + +exit $exit_code diff --git a/util/travis_compiled_push.sh b/util/travis_compiled_push.sh index 8ca65f21a05d..e0490cd702a9 100755 --- a/util/travis_compiled_push.sh +++ b/util/travis_compiled_push.sh @@ -1,5 +1,6 @@ #!/bin/bash +source util/travis_utils.sh source util/travis_push.sh set -o errexit -o nounset diff --git a/util/travis_docs.sh b/util/travis_docs.sh index 5cfd63466d22..93c2d7186729 100755 --- a/util/travis_docs.sh +++ b/util/travis_docs.sh @@ -1,5 +1,6 @@ #!/bin/bash +source util/travis_utils.sh source util/travis_push.sh if [[ "$TRAVIS_COMMIT_MESSAGE" != *"[skip docs]"* ]] ; then diff --git a/util/travis_push.sh b/util/travis_push.sh index d100f9d48f7a..7f7d4c2c647d 100755 --- a/util/travis_push.sh +++ b/util/travis_push.sh @@ -1,10 +1,5 @@ # Use this by sourcing it in your script. -TRAVIS_BRANCH="${TRAVIS_BRANCH:master}" -TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST:false}" -TRAVIS_COMMIT_MESSAGE="${TRAVIS_COMMIT_MESSAGE:-none}" -TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-HEAD~1..HEAD}" - if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == "false" ]] ; then git config --global user.name "QMK Bot" git config --global user.email "hello@qmk.fm" diff --git a/util/travis_test.sh b/util/travis_test.sh index 9b7402c28241..95991907ef35 100644 --- a/util/travis_test.sh +++ b/util/travis_test.sh @@ -1,26 +1,9 @@ #!/bin/bash -# if docker is installed - patch calls to within the qmk docker image -if command -v docker >/dev/null; then - function make() { - docker run --rm -e MAKEFLAGS="$MAKEFLAGS" -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container make "$@" - } - function qmk() { - docker run --rm -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container bin/qmk "$@" - } -fi - -TRAVIS_COMMIT_MESSAGE="${TRAVIS_COMMIT_MESSAGE:-none}" -TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-HEAD~1..HEAD}" - -# test force push -#TRAVIS_COMMIT_RANGE="c287f1bfc5c8...81f62atc4c1d" - -BRANCH=$(git rev-parse --abbrev-ref HEAD) -CHANGES=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE}) +source util/travis_utils.sh -NUM_CORE_CHANGES=$(echo "$CHANGES" | grep -Ecv -e '^(docs/)' -e '^(keyboards/)' -e '^(layouts/)') -NUM_PY_CHANGES=$(echo "$CHANGES" | grep -Ec -e '^(lib/python/)' -e '^(bin/qmk)') +NUM_CORE_CHANGES=$(echo "$QMK_CHANGES" | grep -Ecv -e '^(docs/)' -e '^(keyboards/)' -e '^(layouts/)' -e '^(util/)' -e '^(lib/python/)' -e '^(bin/qmk)' -e '^(requirements.txt)' -e '(.travis.yml)') +NUM_PY_CHANGES=$(echo "$QMK_CHANGES" | grep -Ec -e '^(lib/python/)' -e '^(bin/qmk)') if [[ "$TRAVIS_COMMIT_MESSAGE" == *"[skip test]"* ]]; then echo "Skipping due to commit message" @@ -29,14 +12,14 @@ fi exit_code=0 -if [ "$BRANCH" == "master" ] || [ "$NUM_CORE_CHANGES" != "0" ]; then +if [ "$LOCAL_BRANCH" == "master" ] || [ "$NUM_CORE_CHANGES" != "0" ]; then echo "Running tests." make test:all : $((exit_code = $exit_code + $?)) fi -if [ "$BRANCH" == "master" ] || [ "$NUM_PY_CHANGES" != "0" ]; then +if [ "$LOCAL_BRANCH" == "master" ] || [ "$NUM_PY_CHANGES" != "0" ]; then echo "Running python tests." qmk pytest : $((exit_code = $exit_code + $?)) diff --git a/util/travis_utils.sh b/util/travis_utils.sh new file mode 100755 index 000000000000..031bcda1a82c --- /dev/null +++ b/util/travis_utils.sh @@ -0,0 +1,24 @@ +# Use this by sourcing it in your script. + +# Provide sane defaults for travis environment +TRAVIS_BRANCH="${TRAVIS_BRANCH:master}" +TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST:false}" +TRAVIS_COMMIT_MESSAGE="${TRAVIS_COMMIT_MESSAGE:-none}" +TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-HEAD~1..HEAD}" + +# test force push +#TRAVIS_COMMIT_RANGE="c287f1bfc5c8...81f62atc4c1d" + +# Extra variables +LOCAL_BRANCH=${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}} +QMK_CHANGES=$(git diff --name-only HEAD ${TRAVIS_BRANCH}) + +# if docker is installed - patch calls to within the qmk docker image +if command -v docker >/dev/null; then + function make() { + docker run --rm -e MAKEFLAGS="$MAKEFLAGS" -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container make "$@" + } + function qmk() { + docker run --rm -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container bin/qmk "$@" + } +fi