Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] add support for USB programmable buttons usage #12950

Merged
merged 1 commit into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/pointing_device.c
endif

ifeq ($(strip $(PROGRAMMABLE_BUTTON_ENABLE)), yes)
OPT_DEFS += -DPROGRAMMABLE_BUTTON_ENABLE
SRC += $(QUANTUM_DIR)/programmable_button.c
SRC += $(QUANTUM_DIR)/process_keycode/process_programmable_button.c
endif

VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
EEPROM_DRIVER ?= vendor
ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),)
Expand Down
1 change: 1 addition & 0 deletions docs/_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
* [Mod-Tap](mod_tap.md)
* [Macros](feature_macros.md)
* [Mouse Keys](feature_mouse_keys.md)
* [Programmable Button](feature_programmable_button.md)
* [Space Cadet Shift](feature_space_cadet.md)
* [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md)

Expand Down
74 changes: 74 additions & 0 deletions docs/feature_programmable_button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
## Programmable Button

Programmable button is a feature that can be used to send keys that have no
drashna marked this conversation as resolved.
Show resolved Hide resolved
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.

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`)

### Enabling Programmable Button support

To enable Programmable Button, add the following line to your keymap’s `rules.mk`:

```c
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:

```
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);
```
40 changes: 40 additions & 0 deletions docs/keycodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,46 @@ See also: [One Shot Keys](one_shot_keys.md)
|`OS_OFF` |Turns One Shot keys off |
|`OS_TOGG` |Toggles One Shot keys status |

## Programmable Button Support :id=programmable-button

See also: [Programmable Button](feature_programmable_button.md)

|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 |

## Space Cadet :id=space-cadet

See also: [Space Cadet](feature_space_cadet.md)
Expand Down
5 changes: 5 additions & 0 deletions quantum/action.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keycode.h"
#include "keyboard.h"
#include "mousekey.h"
#include "programmable_button.h"
#include "command.h"
#include "led.h"
#include "action_layer.h"
Expand Down Expand Up @@ -994,6 +995,10 @@ void clear_keyboard_but_mods_and_keys() {
mousekey_clear();
mousekey_send();
#endif
#ifdef PROGRAMMABLE_BUTTON_ENABLE
programmable_button_clear();
programmable_button_send();
#endif
}

/** \brief Utilities for actions. (FIXME: Needs better description)
Expand Down
7 changes: 7 additions & 0 deletions quantum/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef JOYSTICK_ENABLE
# include "process_joystick.h"
#endif
#ifdef PROGRAMMABLE_BUTTON_ENABLE
# include "programmable_button.h"
#endif
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
Expand Down Expand Up @@ -548,6 +551,10 @@ void keyboard_task(void) {
digitizer_task();
#endif

#ifdef PROGRAMMABLE_BUTTON_ENABLE
programmable_button_send();
#endif

// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
Expand Down
31 changes: 31 additions & 0 deletions quantum/process_keycode/process_programmable_button.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>

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 <http://www.gnu.org/licenses/>.
*/

#include "process_programmable_button.h"
#include "programmable_button.h"

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);
} else {
programmable_button_off(button);
}
}
return true;
}
23 changes: 23 additions & 0 deletions quantum/process_keycode/process_programmable_button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>

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 <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <stdint.h>
#include "quantum.h"

bool process_programmable_button(uint16_t keycode, keyrecord_t *record);
37 changes: 37 additions & 0 deletions quantum/programmable_button.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>

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 <http://www.gnu.org/licenses/>.
*/

#include "programmable_button.h"
drashna marked this conversation as resolved.
Show resolved Hide resolved
#include "host.h"

#define REPORT_BIT(index) (((uint32_t)1) << (index - 1))

static uint32_t programmable_button_report = 0;

void programmable_button_clear(void) { programmable_button_report = 0; }

void programmable_button_send(void) { host_programmable_button_send(programmable_button_report); }

void programmable_button_on(uint8_t index) { programmable_button_report |= REPORT_BIT(index); }

void programmable_button_off(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); }

bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); };

uint32_t programmable_button_get_report(void) { return programmable_button_report; };

void programmable_button_set_report(uint32_t report) { programmable_button_report = report; }
30 changes: 30 additions & 0 deletions quantum/programmable_button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>

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 <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <stdint.h>
#include <stdbool.h>
#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);
uint32_t programmable_button_get_report(void);
void programmable_button_set_report(uint32_t report);
3 changes: 3 additions & 0 deletions quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ bool process_record_quantum(keyrecord_t *record) {
#endif
#ifdef JOYSTICK_ENABLE
process_joystick(keycode, record) &&
#endif
#ifdef PROGRAMMABLE_BUTTON_ENABLE
process_programmable_button(keycode, record) &&
#endif
true)) {
return false;
Expand Down
4 changes: 4 additions & 0 deletions quantum/quantum.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ extern layer_state_t layer_state;
# include "process_joystick.h"
#endif

#ifdef PROGRAMMABLE_BUTTON_ENABLE
# include "process_programmable_button.h"
#endif

#ifdef GRAVE_ESC_ENABLE
# include "process_grave_esc.h"
#endif
Expand Down
Loading