forked from mirrors/qmk_userspace
		
	Add Support for USB programmable buttons (#12950)
This commit is contained in:
		
					parent
					
						
							
								1a68feb842
							
						
					
				
			
			
				commit
				
					
						83988597f4
					
				
			
		
					 22 changed files with 436 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -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)),)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										74
									
								
								docs/feature_programmable_button.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								docs/feature_programmable_button.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
## 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.
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -988,6 +989,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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -542,6 +545,10 @@ MATRIX_LOOP_END:
 | 
			
		|||
    digitizer_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    programmable_button_send();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // update LED
 | 
			
		||||
    if (led_status != host_keyboard_leds()) {
 | 
			
		||||
        led_status = host_keyboard_leds();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								quantum/process_keycode/process_programmable_button.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								quantum/process_keycode/process_programmable_button.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
									
								
								quantum/process_keycode/process_programmable_button.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								quantum/process_keycode/process_programmable_button.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
									
								
								quantum/programmable_button.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								quantum/programmable_button.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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"
 | 
			
		||||
#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
									
								
								quantum/programmable_button.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								quantum/programmable_button.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -524,6 +524,40 @@ enum quantum_keycodes {
 | 
			
		|||
    // Additional magic key
 | 
			
		||||
    MAGIC_TOGGLE_GUI,
 | 
			
		||||
 | 
			
		||||
    // Programmable Button
 | 
			
		||||
    PROGRAMMABLE_BUTTON_1,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_2,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_3,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_4,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_5,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_6,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_7,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_8,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_9,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_10,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_11,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_12,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_13,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_14,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_15,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_16,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_17,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_18,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_19,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_20,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_21,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_22,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_23,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_24,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_25,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_26,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_27,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_28,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_29,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_30,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_31,
 | 
			
		||||
    PROGRAMMABLE_BUTTON_32,
 | 
			
		||||
 | 
			
		||||
    // Start of custom keycode range for keyboards and keymaps - always leave at the end
 | 
			
		||||
    SAFE_RANGE
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -854,3 +888,39 @@ enum quantum_keycodes {
 | 
			
		|||
#define OS_TOGG ONESHOT_TOGGLE
 | 
			
		||||
#define OS_ON ONESHOT_ENABLE
 | 
			
		||||
#define OS_OFF ONESHOT_DISABLE
 | 
			
		||||
 | 
			
		||||
// Programmable Button aliases
 | 
			
		||||
#define PB_1 PROGRAMMABLE_BUTTON_1
 | 
			
		||||
#define PB_2 PROGRAMMABLE_BUTTON_2
 | 
			
		||||
#define PB_3 PROGRAMMABLE_BUTTON_3
 | 
			
		||||
#define PB_4 PROGRAMMABLE_BUTTON_4
 | 
			
		||||
#define PB_5 PROGRAMMABLE_BUTTON_5
 | 
			
		||||
#define PB_6 PROGRAMMABLE_BUTTON_6
 | 
			
		||||
#define PB_7 PROGRAMMABLE_BUTTON_7
 | 
			
		||||
#define PB_8 PROGRAMMABLE_BUTTON_8
 | 
			
		||||
#define PB_9 PROGRAMMABLE_BUTTON_9
 | 
			
		||||
#define PB_10 PROGRAMMABLE_BUTTON_10
 | 
			
		||||
#define PB_11 PROGRAMMABLE_BUTTON_11
 | 
			
		||||
#define PB_12 PROGRAMMABLE_BUTTON_12
 | 
			
		||||
#define PB_13 PROGRAMMABLE_BUTTON_13
 | 
			
		||||
#define PB_14 PROGRAMMABLE_BUTTON_14
 | 
			
		||||
#define PB_15 PROGRAMMABLE_BUTTON_15
 | 
			
		||||
#define PB_16 PROGRAMMABLE_BUTTON_16
 | 
			
		||||
#define PB_17 PROGRAMMABLE_BUTTON_17
 | 
			
		||||
#define PB_18 PROGRAMMABLE_BUTTON_18
 | 
			
		||||
#define PB_19 PROGRAMMABLE_BUTTON_19
 | 
			
		||||
#define PB_20 PROGRAMMABLE_BUTTON_20
 | 
			
		||||
#define PB_21 PROGRAMMABLE_BUTTON_21
 | 
			
		||||
#define PB_22 PROGRAMMABLE_BUTTON_22
 | 
			
		||||
#define PB_23 PROGRAMMABLE_BUTTON_23
 | 
			
		||||
#define PB_24 PROGRAMMABLE_BUTTON_24
 | 
			
		||||
#define PB_25 PROGRAMMABLE_BUTTON_25
 | 
			
		||||
#define PB_26 PROGRAMMABLE_BUTTON_26
 | 
			
		||||
#define PB_27 PROGRAMMABLE_BUTTON_27
 | 
			
		||||
#define PB_28 PROGRAMMABLE_BUTTON_28
 | 
			
		||||
#define PB_29 PROGRAMMABLE_BUTTON_29
 | 
			
		||||
#define PB_30 PROGRAMMABLE_BUTTON_30
 | 
			
		||||
#define PB_31 PROGRAMMABLE_BUTTON_31
 | 
			
		||||
#define PB_32 PROGRAMMABLE_BUTTON_32
 | 
			
		||||
#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1
 | 
			
		||||
#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,7 +83,8 @@ OTHER_OPTION_NAMES = \
 | 
			
		|||
  RGB_MATRIX_KEYPRESSES \
 | 
			
		||||
  LED_MIRRORED \
 | 
			
		||||
  RGBLIGHT_FULL_POWER \
 | 
			
		||||
  LTO_ENABLE
 | 
			
		||||
  LTO_ENABLE \
 | 
			
		||||
  PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
 | 
			
		||||
define NAME_ECHO
 | 
			
		||||
       @printf "  %-30s = %-16s # %s\\n" "$1" "$($1)" "$(origin $1)"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
#include "action.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "mousekey.h"
 | 
			
		||||
#include "programmable_button.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "suspend.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +80,9 @@ void suspend_wakeup_init(void) {
 | 
			
		|||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    mousekey_clear();
 | 
			
		||||
#endif /* MOUSEKEY_ENABLE */
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    programmable_button_clear();
 | 
			
		||||
#endif /* PROGRAMMABLE_BUTTON_ENABLE */
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
    host_system_send(0);
 | 
			
		||||
    host_consumer_send(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,8 +30,9 @@ extern keymap_config_t keymap_config;
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
static host_driver_t *driver;
 | 
			
		||||
static uint16_t       last_system_report   = 0;
 | 
			
		||||
static uint16_t       last_consumer_report = 0;
 | 
			
		||||
static uint16_t       last_system_report              = 0;
 | 
			
		||||
static uint16_t       last_consumer_report            = 0;
 | 
			
		||||
static uint32_t       last_programmable_button_report = 0;
 | 
			
		||||
 | 
			
		||||
void host_set_driver(host_driver_t *d) { driver = d; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +123,16 @@ void host_digitizer_send(digitizer_t *digitizer) {
 | 
			
		|||
 | 
			
		||||
__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {}
 | 
			
		||||
 | 
			
		||||
void host_programmable_button_send(uint32_t report) {
 | 
			
		||||
    if (report == last_programmable_button_report) return;
 | 
			
		||||
    last_programmable_button_report = report;
 | 
			
		||||
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_programmable_button)(report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_system_report(void) { return last_system_report; }
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_consumer_report(void) { return last_consumer_report; }
 | 
			
		||||
 | 
			
		||||
uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,9 +47,11 @@ void    host_keyboard_send(report_keyboard_t *report);
 | 
			
		|||
void    host_mouse_send(report_mouse_t *report);
 | 
			
		||||
void    host_system_send(uint16_t data);
 | 
			
		||||
void    host_consumer_send(uint16_t data);
 | 
			
		||||
void    host_programmable_button_send(uint32_t data);
 | 
			
		||||
 | 
			
		||||
uint16_t host_last_system_report(void);
 | 
			
		||||
uint16_t host_last_consumer_report(void);
 | 
			
		||||
uint32_t host_last_programmable_button_report(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ typedef struct {
 | 
			
		|||
    void (*send_mouse)(report_mouse_t *);
 | 
			
		||||
    void (*send_system)(uint16_t);
 | 
			
		||||
    void (*send_consumer)(uint16_t);
 | 
			
		||||
    void (*send_programmable_button)(uint32_t);
 | 
			
		||||
} host_driver_t;
 | 
			
		||||
 | 
			
		||||
void send_digitizer(report_digitizer_t *report);
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ enum hid_report_ids {
 | 
			
		|||
    REPORT_ID_MOUSE,
 | 
			
		||||
    REPORT_ID_SYSTEM,
 | 
			
		||||
    REPORT_ID_CONSUMER,
 | 
			
		||||
    REPORT_ID_PROGRAMMABLE_BUTTON,
 | 
			
		||||
    REPORT_ID_NKRO,
 | 
			
		||||
    REPORT_ID_JOYSTICK,
 | 
			
		||||
    REPORT_ID_DIGITIZER
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +196,11 @@ typedef struct {
 | 
			
		|||
    uint16_t usage;
 | 
			
		||||
} __attribute__((packed)) report_extra_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t  report_id;
 | 
			
		||||
    uint32_t usage;
 | 
			
		||||
} __attribute__((packed)) report_programmable_button_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
#ifdef MOUSE_SHARED_EP
 | 
			
		||||
    uint8_t report_id;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,7 +142,8 @@ static void    send_keyboard(report_keyboard_t *report);
 | 
			
		|||
static void    send_mouse(report_mouse_t *report);
 | 
			
		||||
static void    send_system(uint16_t data);
 | 
			
		||||
static void    send_consumer(uint16_t data);
 | 
			
		||||
host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
 | 
			
		||||
static void    send_programmable_button(uint32_t data);
 | 
			
		||||
host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
 | 
			
		||||
 | 
			
		||||
#ifdef VIRTSER_ENABLE
 | 
			
		||||
// clang-format off
 | 
			
		||||
| 
						 | 
				
			
			@ -760,27 +761,31 @@ static void send_mouse(report_mouse_t *report) {
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Send Extra
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs doc
 | 
			
		||||
 */
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
static void send_extra(uint8_t report_id, uint16_t data) {
 | 
			
		||||
static void send_report(void *report, size_t size) {
 | 
			
		||||
    uint8_t timeout = 255;
 | 
			
		||||
 | 
			
		||||
    if (USB_DeviceState != DEVICE_STATE_Configured) return;
 | 
			
		||||
 | 
			
		||||
    static report_extra_t r;
 | 
			
		||||
    r = (report_extra_t){.report_id = report_id, .usage = data};
 | 
			
		||||
    Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
 | 
			
		||||
 | 
			
		||||
    /* Check if write ready for a polling interval around 10ms */
 | 
			
		||||
    while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
 | 
			
		||||
    if (!Endpoint_IsReadWriteAllowed()) return;
 | 
			
		||||
 | 
			
		||||
    Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
 | 
			
		||||
    Endpoint_Write_Stream_LE(report, size, NULL);
 | 
			
		||||
    Endpoint_ClearIN();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Send Extra
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs doc
 | 
			
		||||
 */
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
static void send_extra(uint8_t report_id, uint16_t data) {
 | 
			
		||||
    static report_extra_t r;
 | 
			
		||||
    r = (report_extra_t){.report_id = report_id, .usage = data};
 | 
			
		||||
    send_report(&r, sizeof(r));
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Send System
 | 
			
		||||
| 
						 | 
				
			
			@ -822,6 +827,14 @@ static void send_consumer(uint16_t data) {
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void send_programmable_button(uint32_t data) {
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    static report_programmable_button_t r;
 | 
			
		||||
    r = (report_programmable_button_t){.report_id = REPORT_ID_PROGRAMMABLE_BUTTON, .usage = data};
 | 
			
		||||
    send_report(&r, sizeof(r));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * sendchar
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,6 +237,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
 | 
			
		|||
    HID_RI_END_COLLECTION(0),
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    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_PROGRAMMABLE_BUTTON),
 | 
			
		||||
        HID_RI_USAGE(8, 0x09),             // Programmable Buttons
 | 
			
		||||
        HID_RI_COLLECTION(8, 0x04),        // Named Array
 | 
			
		||||
            HID_RI_USAGE_PAGE(8, 0x09),    // Button
 | 
			
		||||
            HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
 | 
			
		||||
            HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32
 | 
			
		||||
            HID_RI_LOGICAL_MINIMUM(8, 0x01),
 | 
			
		||||
            HID_RI_LOGICAL_MAXIMUM(8, 0x01),
 | 
			
		||||
            HID_RI_REPORT_COUNT(8, 32),
 | 
			
		||||
            HID_RI_REPORT_SIZE(8, 1),
 | 
			
		||||
            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
 | 
			
		||||
        HID_RI_END_COLLECTION(0),
 | 
			
		||||
    HID_RI_END_COLLECTION(0),
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    HID_RI_USAGE_PAGE(8, 0x01),        // Generic Desktop
 | 
			
		||||
    HID_RI_USAGE(8, 0x06),             // Keyboard
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -226,8 +226,9 @@ static void    send_keyboard(report_keyboard_t *report);
 | 
			
		|||
static void    send_mouse(report_mouse_t *report);
 | 
			
		||||
static void    send_system(uint16_t data);
 | 
			
		||||
static void    send_consumer(uint16_t data);
 | 
			
		||||
static void    send_programmable_button(uint32_t data);
 | 
			
		||||
 | 
			
		||||
static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
 | 
			
		||||
static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
 | 
			
		||||
 | 
			
		||||
host_driver_t *vusb_driver(void) { return &driver; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -296,6 +297,19 @@ void send_digitizer(report_digitizer_t *report) {
 | 
			
		|||
#ifdef DIGITIZER_ENABLE
 | 
			
		||||
    if (usbInterruptIsReadyShared()) {
 | 
			
		||||
        usbSetInterruptShared((void *)report, sizeof(report_digitizer_t));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void send_programmable_button(uint32_t data) {
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    static report_programmable_button_t report = {
 | 
			
		||||
        .report_id = REPORT_ID_PROGRAMMABLE_BUTTON,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    report.usage = data;
 | 
			
		||||
 | 
			
		||||
    if (usbInterruptIsReadyShared()) {
 | 
			
		||||
        usbSetInterruptShared((void *)&report, sizeof(report));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -558,6 +572,26 @@ const PROGMEM uchar shared_hid_report[] = {
 | 
			
		|||
    0xC0               // End Collection
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PROGRAMMABLE_BUTTON_ENABLE
 | 
			
		||||
    // Programmable buttons report descriptor
 | 
			
		||||
    0x05, 0x0C,                           // Usage Page (Consumer)
 | 
			
		||||
    0x09, 0x01,                           // Usage (Consumer Control)
 | 
			
		||||
    0xA1, 0x01,                           // Collection (Application)
 | 
			
		||||
    0x85, REPORT_ID_PROGRAMMABLE_BUTTON,  //   Report ID
 | 
			
		||||
    0x09, 0x03,                           //   Usage (Programmable Buttons)
 | 
			
		||||
    0xA1, 0x04,                           //   Collection (Named Array)
 | 
			
		||||
    0x05, 0x09,                           //     Usage Page (Button)
 | 
			
		||||
    0x19, 0x01,                           //     Usage Minimum (Button 1)
 | 
			
		||||
    0x29, 0x20,                           //     Usage Maximum (Button 32)
 | 
			
		||||
    0x15, 0x00,                           //     Logical Minimum (0)
 | 
			
		||||
    0x25, 0x01,                           //     Logical Maximum (1)
 | 
			
		||||
    0x95, 0x20,                           //     Report Count (32)
 | 
			
		||||
    0x75, 0x01,                           //     Report Size (1)
 | 
			
		||||
    0x81, 0x02,                           //     Input (Data, Variable, Absolute)
 | 
			
		||||
    0xC0,                                 //   End Collection
 | 
			
		||||
    0xC0                                  // End Collection
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SHARED_EP_ENABLE
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue