diff --git a/docs/feature_programmable_button.md b/docs/feature_programmable_button.md
index b1ef555d16a9..1982b8295e87 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
-
-In your keymap you can use the following keycodes to map key presses to Programmable Buttons:
-
-|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
-
-You can also use a dedicated API defined in `programmable_button.h` to interact with this feature:
+## Keycodes :id=keycodes
-```
-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);
-```
+|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|
+
+## API :id=api
+
+### `void programmable_button_clear(void)` :id=api-programmable-button-clear
+
+Clear the programmable button 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 78322e4a83af..abf9834d2f39 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 280532a5fdb7..eb5e4b583a99 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 c6e77faacc0e..6379698848f5 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 a3ef42d82ba2..b6c9ad318992 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 e89b8b9fd6a8..e8c916d75c90 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);
+
+/** \} */