From f0b2bfd5ca5b416a9c7c9bef8c2850f1084bd106 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 15 Oct 2022 14:33:24 +1100 Subject: [PATCH] Programmable Button API refactor and improve docs (#18641) --- docs/feature_programmable_button.md | 192 ++++++++++++------ quantum/action.c | 1 - quantum/keyboard.c | 7 - .../process_programmable_button.c | 4 +- quantum/programmable_button.c | 27 ++- quantum/programmable_button.h | 75 ++++++- 6 files changed, 220 insertions(+), 86 deletions(-) diff --git a/docs/feature_programmable_button.md b/docs/feature_programmable_button.md index b1ef555d16..1982b8295e 100644 --- a/docs/feature_programmable_button.md +++ b/docs/feature_programmable_button.md @@ -1,74 +1,144 @@ -## Programmable Button +# Programmable Button :id=programmable-button -Programmable button is a feature that can be used to send keys that have no -predefined meaning. -This means they can be processed on the host side by custom software without -colliding without the operating system trying to interpret these keys. +Programmable Buttons are keys that have no predefined meaning. This means they can be processed on the host side by custom software without the operating system trying to interpret them. -The keycodes are emitted according to the HID usage -"Telephony Device Page" (0x0B), "Programmable button usage" (0x07). -On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` -keycodes. -(Up to `KEY_MACRO30`) +The keycodes are emitted according to the HID Telephony Device page (`0x0B`), Programmable Button usage (`0x07`). On Linux (> 5.14) they are handled automatically and translated to `KEY_MACRO#` keycodes (up to `KEY_MACRO30`). -### Enabling Programmable Button support +?> Currently there is no known support in Windows or macOS. It may be possible to write a custom HID driver to receive these usages, but this is out of the scope of the QMK documentation. -To enable Programmable Button, add the following line to your keymap’s `rules.mk`: +## Usage :id=usage -```c +Add the following to your `rules.mk`: + +```make PROGRAMMABLE_BUTTON_ENABLE = yes ``` -### Mapping +## Keycodes :id=keycodes -In your keymap you can use the following keycodes to map key presses to Programmable Buttons: +|Key |Aliases|Description | +|------------------------|-------|----------------------| +|`PROGRAMMABLE_BUTTON_1` |`PB_1` |Programmable button 1 | +|`PROGRAMMABLE_BUTTON_2` |`PB_2` |Programmable button 2 | +|`PROGRAMMABLE_BUTTON_3` |`PB_3` |Programmable button 3 | +|`PROGRAMMABLE_BUTTON_4` |`PB_4` |Programmable button 4 | +|`PROGRAMMABLE_BUTTON_5` |`PB_5` |Programmable button 5 | +|`PROGRAMMABLE_BUTTON_6` |`PB_6` |Programmable button 6 | +|`PROGRAMMABLE_BUTTON_7` |`PB_7` |Programmable button 7 | +|`PROGRAMMABLE_BUTTON_8` |`PB_8` |Programmable button 8 | +|`PROGRAMMABLE_BUTTON_9` |`PB_9` |Programmable button 9 | +|`PROGRAMMABLE_BUTTON_10`|`PB_10`|Programmable button 10| +|`PROGRAMMABLE_BUTTON_11`|`PB_11`|Programmable button 11| +|`PROGRAMMABLE_BUTTON_12`|`PB_12`|Programmable button 12| +|`PROGRAMMABLE_BUTTON_13`|`PB_13`|Programmable button 13| +|`PROGRAMMABLE_BUTTON_14`|`PB_14`|Programmable button 14| +|`PROGRAMMABLE_BUTTON_15`|`PB_15`|Programmable button 15| +|`PROGRAMMABLE_BUTTON_16`|`PB_16`|Programmable button 16| +|`PROGRAMMABLE_BUTTON_17`|`PB_17`|Programmable button 17| +|`PROGRAMMABLE_BUTTON_18`|`PB_18`|Programmable button 18| +|`PROGRAMMABLE_BUTTON_19`|`PB_19`|Programmable button 19| +|`PROGRAMMABLE_BUTTON_20`|`PB_20`|Programmable button 20| +|`PROGRAMMABLE_BUTTON_21`|`PB_21`|Programmable button 21| +|`PROGRAMMABLE_BUTTON_22`|`PB_22`|Programmable button 22| +|`PROGRAMMABLE_BUTTON_23`|`PB_23`|Programmable button 23| +|`PROGRAMMABLE_BUTTON_24`|`PB_24`|Programmable button 24| +|`PROGRAMMABLE_BUTTON_25`|`PB_25`|Programmable button 25| +|`PROGRAMMABLE_BUTTON_26`|`PB_26`|Programmable button 26| +|`PROGRAMMABLE_BUTTON_27`|`PB_27`|Programmable button 27| +|`PROGRAMMABLE_BUTTON_28`|`PB_28`|Programmable button 28| +|`PROGRAMMABLE_BUTTON_29`|`PB_29`|Programmable button 29| +|`PROGRAMMABLE_BUTTON_30`|`PB_30`|Programmable button 30| +|`PROGRAMMABLE_BUTTON_31`|`PB_31`|Programmable button 31| +|`PROGRAMMABLE_BUTTON_32`|`PB_32`|Programmable button 32| -|Key |Description | -|------------------------|----------------------| -|`PROGRAMMABLE_BUTTON_1` |Programmable button 1 | -|`PROGRAMMABLE_BUTTON_2` |Programmable button 2 | -|`PROGRAMMABLE_BUTTON_3` |Programmable button 3 | -|`PROGRAMMABLE_BUTTON_4` |Programmable button 4 | -|`PROGRAMMABLE_BUTTON_5` |Programmable button 5 | -|`PROGRAMMABLE_BUTTON_6` |Programmable button 6 | -|`PROGRAMMABLE_BUTTON_7` |Programmable button 7 | -|`PROGRAMMABLE_BUTTON_8` |Programmable button 8 | -|`PROGRAMMABLE_BUTTON_9` |Programmable button 9 | -|`PROGRAMMABLE_BUTTON_10`|Programmable button 10| -|`PROGRAMMABLE_BUTTON_11`|Programmable button 11| -|`PROGRAMMABLE_BUTTON_12`|Programmable button 12| -|`PROGRAMMABLE_BUTTON_13`|Programmable button 13| -|`PROGRAMMABLE_BUTTON_14`|Programmable button 14| -|`PROGRAMMABLE_BUTTON_15`|Programmable button 15| -|`PROGRAMMABLE_BUTTON_16`|Programmable button 16| -|`PROGRAMMABLE_BUTTON_17`|Programmable button 17| -|`PROGRAMMABLE_BUTTON_18`|Programmable button 18| -|`PROGRAMMABLE_BUTTON_19`|Programmable button 19| -|`PROGRAMMABLE_BUTTON_20`|Programmable button 20| -|`PROGRAMMABLE_BUTTON_21`|Programmable button 21| -|`PROGRAMMABLE_BUTTON_22`|Programmable button 22| -|`PROGRAMMABLE_BUTTON_23`|Programmable button 23| -|`PROGRAMMABLE_BUTTON_24`|Programmable button 24| -|`PROGRAMMABLE_BUTTON_25`|Programmable button 25| -|`PROGRAMMABLE_BUTTON_26`|Programmable button 26| -|`PROGRAMMABLE_BUTTON_27`|Programmable button 27| -|`PROGRAMMABLE_BUTTON_28`|Programmable button 28| -|`PROGRAMMABLE_BUTTON_29`|Programmable button 29| -|`PROGRAMMABLE_BUTTON_30`|Programmable button 30| -|`PROGRAMMABLE_BUTTON_31`|Programmable button 31| -|`PROGRAMMABLE_BUTTON_32`|Programmable button 32| -|`PB_1` to `PB_32` |Aliases for keymaps | +## API :id=api -### API +### `void programmable_button_clear(void)` :id=api-programmable-button-clear -You can also use a dedicated API defined in `programmable_button.h` to interact with this feature: +Clear the programmable button report. -``` -void programmable_button_clear(void); -void programmable_button_send(void); -void programmable_button_on(uint8_t code); -void programmable_button_off(uint8_t code); -bool programmable_button_is_on(uint8_t code); -uint32_t programmable_button_get_report(void); -void programmable_button_set_report(uint32_t report); -``` +--- + +### `void programmable_button_add(uint8_t index)` :id=api-programmable-button-add + +Set the state of a button. + +#### Arguments :id=api-programmable-button-add-arguments + + - `uint8_t index` + The index of the button to press, from 0 to 31. + +--- + +### `void programmable_button_remove(uint8_t index)` :id=api-programmable-button-remove + +Reset the state of a button. + +#### Arguments :id=api-programmable-button-remove-arguments + + - `uint8_t index` + The index of the button to release, from 0 to 31. + +--- + +### `void programmable_button_register(uint8_t index)` :id=api-programmable-button-register + +Set the state of a button, and flush the report. + +#### Arguments :id=api-programmable-button-register-arguments + + - `uint8_t index` + The index of the button to press, from 0 to 31. + +--- + +### `void programmable_button_unregister(uint8_t index)` :id=api-programmable-button-unregister + +Reset the state of a button, and flush the report. + +#### Arguments :id=api-programmable-button-unregister-arguments + + - `uint8_t index` + The index of the button to release, from 0 to 31. + +--- + +### `bool programmable_button_is_on(uint8_t index)` :id=api-programmable-button-is-on + +Get the state of a button. + +#### Arguments :id=api-programmable-button-is-on-arguments + + - `uint8_t index` + The index of the button to check, from 0 to 31. + +#### Return Value :id=api-programmable-button-is-on-return + +`true` if the button is pressed. + +--- + +### `void programmable_button_flush(void)` :id=api-programmable-button-flush + +Send the programmable button report to the host. + +--- + +### `uint32_t programmable_button_get_report(void)` :id=api-programmable-button-get-report + +Get the programmable button report. + +#### Return Value :id=api-programmable-button-get-report-return + +The bitmask of programmable button states. + +--- + +### `void programmable_button_set_report(uint32_t report)` :id=api-programmable-button-set-report + +Set the programmable button report. + +#### Arguments :id=api-programmable-button-set-report-arguments + + - `uint32_t report` + A bitmask of programmable button states. diff --git a/quantum/action.c b/quantum/action.c index 78322e4a83..abf9834d2f 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -1081,7 +1081,6 @@ void clear_keyboard_but_mods_and_keys() { #endif #ifdef PROGRAMMABLE_BUTTON_ENABLE programmable_button_clear(); - programmable_button_send(); #endif } diff --git a/quantum/keyboard.c b/quantum/keyboard.c index 280532a5fd..eb5e4b583a 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -66,9 +66,6 @@ along with this program. If not, see . #ifdef JOYSTICK_ENABLE # include "process_joystick.h" #endif -#ifdef PROGRAMMABLE_BUTTON_ENABLE -# include "programmable_button.h" -#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif @@ -669,10 +666,6 @@ void keyboard_task(void) { digitizer_task(); #endif -#ifdef PROGRAMMABLE_BUTTON_ENABLE - programmable_button_send(); -#endif - #ifdef BLUETOOTH_ENABLE bluetooth_task(); #endif diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c index c6e77faacc..6379698848 100644 --- a/quantum/process_keycode/process_programmable_button.c +++ b/quantum/process_keycode/process_programmable_button.c @@ -22,9 +22,9 @@ bool process_programmable_button(uint16_t keycode, keyrecord_t *record) { if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) { uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1; if (record->event.pressed) { - programmable_button_on(button); + programmable_button_register(button); } else { - programmable_button_off(button); + programmable_button_unregister(button); } } return true; diff --git a/quantum/programmable_button.c b/quantum/programmable_button.c index a3ef42d82b..b6c9ad3189 100644 --- a/quantum/programmable_button.c +++ b/quantum/programmable_button.c @@ -24,27 +24,38 @@ static uint32_t programmable_button_report = 0; void programmable_button_clear(void) { programmable_button_report = 0; + programmable_button_flush(); } -void programmable_button_send(void) { - host_programmable_button_send(programmable_button_report); -} - -void programmable_button_on(uint8_t index) { +void programmable_button_add(uint8_t index) { programmable_button_report |= REPORT_BIT(index); } -void programmable_button_off(uint8_t index) { +void programmable_button_remove(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); } +void programmable_button_register(uint8_t index) { + programmable_button_add(index); + programmable_button_flush(); +} + +void programmable_button_unregister(uint8_t index) { + programmable_button_remove(index); + programmable_button_flush(); +} + bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); -}; +} + +void programmable_button_flush(void) { + host_programmable_button_send(programmable_button_report); +} uint32_t programmable_button_get_report(void) { return programmable_button_report; -}; +} void programmable_button_set_report(uint32_t report) { programmable_button_report = report; diff --git a/quantum/programmable_button.h b/quantum/programmable_button.h index e89b8b9fd6..e8c916d75c 100644 --- a/quantum/programmable_button.h +++ b/quantum/programmable_button.h @@ -19,12 +19,73 @@ along with this program. If not, see . #include #include -#include "report.h" -void programmable_button_clear(void); -void programmable_button_send(void); -void programmable_button_on(uint8_t index); -void programmable_button_off(uint8_t index); -bool programmable_button_is_on(uint8_t index); +/** + * \defgroup programmable_button + * + * HID Programmable Buttons + * \{ + */ + +/** + * \brief Clear the programmable button report. + */ +void programmable_button_clear(void); + +/** + * \brief Set the state of a button. + * + * \param index The index of the button to press, from 0 to 31. + */ +void programmable_button_add(uint8_t index); + +/** + * \brief Reset the state of a button. + * + * \param index The index of the button to release, from 0 to 31. + */ +void programmable_button_remove(uint8_t index); + +/** + * \brief Set the state of a button, and flush the report. + * + * \param index The index of the button to press, from 0 to 31. + */ +void programmable_button_register(uint8_t index); + +/** + * \brief Reset the state of a button, and flush the report. + * + * \param index The index of the button to release, from 0 to 31. + */ +void programmable_button_unregister(uint8_t index); + +/** + * \brief Get the state of a button. + * + * \param index The index of the button to check, from 0 to 31. + * + * \return `true` if the button is pressed. + */ +bool programmable_button_is_on(uint8_t index); + +/** + * \brief Send the programmable button report to the host. + */ +void programmable_button_flush(void); + +/** + * \brief Get the programmable button report. + * + * \return The bitmask of programmable button states. + */ uint32_t programmable_button_get_report(void); -void programmable_button_set_report(uint32_t report); + +/** + * \brief Set the programmable button report. + * + * \param report A bitmask of programmable button states. + */ +void programmable_button_set_report(uint32_t report); + +/** \} */