mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-06-20 14:23:45 -04:00
Compare commits
2 Commits
6ada0933db
...
b64014d5df
| Author | SHA1 | Date | |
|---|---|---|---|
| b64014d5df | |||
| 0d401d1182 |
@@ -98,6 +98,12 @@ endif
|
||||
|
||||
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
|
||||
STENO_PROTOCOL ?= all
|
||||
|
||||
ifeq ($(strip $(PLOVER_HID_ENABLE)), yes)
|
||||
OPT_DEFS += -DPLOVER_HID_ENABLE
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_plover_hid.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(STENO_ENABLE)), yes)
|
||||
ifeq ($(filter $(STENO_PROTOCOL),$(VALID_STENO_PROTOCOL_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid STENO_PROTOCOL,STENO_PROTOCOL="$(STENO_PROTOCOL)" is not a valid stenography protocol)
|
||||
|
||||
@@ -63,6 +63,7 @@ OTHER_OPTION_NAMES = \
|
||||
LCD_BACKLIGHT_ENABLE \
|
||||
MACROS_ENABLED \
|
||||
PS2_ENABLE \
|
||||
PLOVER_HID_ENABLE \
|
||||
PS2_MOUSE_ENABLE \
|
||||
PS2_DRIVER \
|
||||
RAW_ENABLE \
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
{
|
||||
"ranges": {
|
||||
"0x5A40/0x003F": {
|
||||
"define": "QK_PLOVER_HID"
|
||||
}
|
||||
},
|
||||
"keycodes": {
|
||||
"0x5A40": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_S1"
|
||||
},
|
||||
"0x5A41": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_TL"
|
||||
},
|
||||
"0x5A42": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_KL"
|
||||
},
|
||||
"0x5A43": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_PL"
|
||||
},
|
||||
"0x5A44": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_WL"
|
||||
},
|
||||
"0x5A45": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_HL"
|
||||
},
|
||||
"0x5A46": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_RL"
|
||||
},
|
||||
"0x5A47": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_A"
|
||||
},
|
||||
"0x5A48": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_O"
|
||||
},
|
||||
"0x5A49": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_ST1"
|
||||
},
|
||||
"0x5A4A": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_E"
|
||||
},
|
||||
"0x5A4B": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_U"
|
||||
},
|
||||
"0x5A4C": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_FR"
|
||||
},
|
||||
"0x5A4D": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_RR"
|
||||
},
|
||||
"0x5A4E": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_PR"
|
||||
},
|
||||
"0x5A4F": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_BR"
|
||||
},
|
||||
"0x5A50": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_LR"
|
||||
},
|
||||
"0x5A51": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_GR"
|
||||
},
|
||||
"0x5A52": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_TR"
|
||||
},
|
||||
"0x5A53": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_SR"
|
||||
},
|
||||
"0x5A54": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_DR"
|
||||
},
|
||||
"0x5A55": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_ZR"
|
||||
},
|
||||
"0x5A56": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N1"
|
||||
},
|
||||
"0x5A57": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_S2"
|
||||
},
|
||||
"0x5A58": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_ST2"
|
||||
},
|
||||
"0x5A59": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_ST3"
|
||||
},
|
||||
"0x5A5A": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_ST4"
|
||||
},
|
||||
"0x5A5B": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N2"
|
||||
},
|
||||
"0x5A5C": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N3"
|
||||
},
|
||||
"0x5A5D": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N4"
|
||||
},
|
||||
"0x5A5E": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N5"
|
||||
},
|
||||
"0x5A5F": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N6"
|
||||
},
|
||||
"0x5A60": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N7"
|
||||
},
|
||||
"0x5A61": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N8"
|
||||
},
|
||||
"0x5A62": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_N9"
|
||||
},
|
||||
"0x5A63": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_NA"
|
||||
},
|
||||
"0x5A64": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_NB"
|
||||
},
|
||||
"0x5A65": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_NC"
|
||||
},
|
||||
"0x5A66": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X1"
|
||||
},
|
||||
"0x5A67": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X2"
|
||||
},
|
||||
"0x5A68": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X3"
|
||||
},
|
||||
"0x5A69": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X4"
|
||||
},
|
||||
"0x5A6A": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X5"
|
||||
},
|
||||
"0x5A6B": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X6"
|
||||
},
|
||||
"0x5A6C": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X7"
|
||||
},
|
||||
"0x5A6D": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X8"
|
||||
},
|
||||
"0x5A6E": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X9"
|
||||
},
|
||||
"0x5A6F": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X10"
|
||||
},
|
||||
"0x5A70": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X11"
|
||||
},
|
||||
"0x5A71": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X12"
|
||||
},
|
||||
"0x5A72": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X13"
|
||||
},
|
||||
"0x5A73": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X14"
|
||||
},
|
||||
"0x5A74": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X15"
|
||||
},
|
||||
"0x5A75": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X16"
|
||||
},
|
||||
"0x5A76": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X17"
|
||||
},
|
||||
"0x5A77": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X18"
|
||||
},
|
||||
"0x5A78": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X19"
|
||||
},
|
||||
"0x5A79": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X20"
|
||||
},
|
||||
"0x5A7A": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X21"
|
||||
},
|
||||
"0x5A7B": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X22"
|
||||
},
|
||||
"0x5A7C": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X23"
|
||||
},
|
||||
"0x5A7D": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X24"
|
||||
},
|
||||
"0x5A7E": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X25"
|
||||
},
|
||||
"0x5A7F": {
|
||||
"group": "plover_hid",
|
||||
"key": "PLV_X26"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,12 @@ The [Open Steno Project](https://www.openstenoproject.org/) has built an open-so
|
||||
|
||||
## Steno Support in QMK
|
||||
|
||||
There are three ways that QMK keyboards can support steno, with varying degrees of configuration required:
|
||||
There are four ways that QMK keyboards can support steno, with varying degrees of configuration required:
|
||||
|
||||
1. Plover with [Arpeggiation](https://plover.wiki/index.php/Glossary#Arpeggiate) requires no changes to any keyboard and is supported by QMK as well as any other QWERTY keyboard.
|
||||
2. Plover with [NKRO](https://plover.wiki/index.php/Using_a_standard_keyboard_with_Plover#NKRO). If your keyboard supports NKRO in hardware and you have NKRO enabled as a USB endpoint, you can chord with the keyboard. Many devices will arrive stock like this and will require no changes.
|
||||
3. Steno Machine Protocols. This requires the most configuration, but this has the advantage of allowing you to use your keyboard keys normally (either on another layer or another piece of hardware) without enabling and disabling your steno software.
|
||||
4. Plover HID Protocol. This is a custom HID protocol that Plover can understand, but does not require a COM port. It is robust to device disconnects and saves an interface over the COM-based alternatives.
|
||||
|
||||
## Plover with QWERTY Keyboard {#plover-with-qwerty-keyboard}
|
||||
|
||||
@@ -92,6 +93,22 @@ Examples of steno strokes and the associated packet:
|
||||
- `WAZ` = `10000000 00000010 00100000 00000000 00000000 00000001`
|
||||
- `PHAPBGS` = `10000000 00000101 00100000 00000000 01101010 00000000`
|
||||
|
||||
## Plover HID Protocol {#plover-hid-protocol}
|
||||
|
||||
This mode operates independently of the other Steno "official" machine protocols. Like any other mouse or keyboard, it uses the USB HID protocol to communicate with Plover by sending an 8 byte (64 bit) packet representing a bitfield for all the possible keys on a steno machine plus a number of additional general purpose keys for custom use. This protocol is only understood by Plover as of [5.1.0](https://github.com/opensteno/plover/releases/tag/v5.1.0).
|
||||
|
||||
Add
|
||||
|
||||
```make
|
||||
PLOVER_HID_ENABLE = yes
|
||||
```
|
||||
|
||||
to your `rules.mk` file. This does **not** require `STENO_ENABLE` to be set.
|
||||
|
||||
All of the possible keycodes are defined with the `PLV_` prefix and are available without any additional includes.
|
||||
|
||||
More details can be found here: https://github.com/dnaq/plover-machine-hid
|
||||
|
||||
### Switching protocols on the fly {#switching-protocols-on-the-fly}
|
||||
|
||||
If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press the `QK_STENO_BOLT` and `QK_STENO_GEMINI` keycodes in order to switch protocols on the fly.
|
||||
|
||||
@@ -354,7 +354,7 @@ bool azoteq_iqs5xx_init(void) {
|
||||
};
|
||||
|
||||
report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report) {
|
||||
report_mouse_t temp_report = {0};
|
||||
report_mouse_t temp_report = {.buttons = mouse_report.buttons};
|
||||
|
||||
azoteq_iqs5xx_base_data_t base_data = {0};
|
||||
i2c_status_t status = azoteq_iqs5xx_get_base_data(&base_data);
|
||||
|
||||
+72
-3
@@ -26,11 +26,11 @@
|
||||
#pragma once
|
||||
// clang-format off
|
||||
|
||||
#define QMK_KEYCODES_VERSION "0.0.8"
|
||||
#define QMK_KEYCODES_VERSION_BCD 0x00000008
|
||||
#define QMK_KEYCODES_VERSION "0.0.9"
|
||||
#define QMK_KEYCODES_VERSION_BCD 0x00000009
|
||||
#define QMK_KEYCODES_VERSION_MAJOR 0
|
||||
#define QMK_KEYCODES_VERSION_MINOR 0
|
||||
#define QMK_KEYCODES_VERSION_PATCH 8
|
||||
#define QMK_KEYCODES_VERSION_PATCH 9
|
||||
|
||||
enum qk_keycode_ranges {
|
||||
// Ranges
|
||||
@@ -64,6 +64,8 @@ enum qk_keycode_ranges {
|
||||
QK_SWAP_HANDS_MAX = 0x56FF,
|
||||
QK_TAP_DANCE = 0x5700,
|
||||
QK_TAP_DANCE_MAX = 0x57FF,
|
||||
QK_PLOVER_HID = 0x5A40,
|
||||
QK_PLOVER_HID_MAX = 0x5A7F,
|
||||
QK_MAGIC = 0x7000,
|
||||
QK_MAGIC_MAX = 0x70FF,
|
||||
QK_MIDI = 0x7100,
|
||||
@@ -329,6 +331,70 @@ enum qk_keycode_defines {
|
||||
QK_SWAP_HANDS_OFF = 0x56F4,
|
||||
QK_SWAP_HANDS_ON = 0x56F5,
|
||||
QK_SWAP_HANDS_ONE_SHOT = 0x56F6,
|
||||
PLV_S1 = 0x5A40,
|
||||
PLV_TL = 0x5A41,
|
||||
PLV_KL = 0x5A42,
|
||||
PLV_PL = 0x5A43,
|
||||
PLV_WL = 0x5A44,
|
||||
PLV_HL = 0x5A45,
|
||||
PLV_RL = 0x5A46,
|
||||
PLV_A = 0x5A47,
|
||||
PLV_O = 0x5A48,
|
||||
PLV_ST1 = 0x5A49,
|
||||
PLV_E = 0x5A4A,
|
||||
PLV_U = 0x5A4B,
|
||||
PLV_FR = 0x5A4C,
|
||||
PLV_RR = 0x5A4D,
|
||||
PLV_PR = 0x5A4E,
|
||||
PLV_BR = 0x5A4F,
|
||||
PLV_LR = 0x5A50,
|
||||
PLV_GR = 0x5A51,
|
||||
PLV_TR = 0x5A52,
|
||||
PLV_SR = 0x5A53,
|
||||
PLV_DR = 0x5A54,
|
||||
PLV_ZR = 0x5A55,
|
||||
PLV_N1 = 0x5A56,
|
||||
PLV_S2 = 0x5A57,
|
||||
PLV_ST2 = 0x5A58,
|
||||
PLV_ST3 = 0x5A59,
|
||||
PLV_ST4 = 0x5A5A,
|
||||
PLV_N2 = 0x5A5B,
|
||||
PLV_N3 = 0x5A5C,
|
||||
PLV_N4 = 0x5A5D,
|
||||
PLV_N5 = 0x5A5E,
|
||||
PLV_N6 = 0x5A5F,
|
||||
PLV_N7 = 0x5A60,
|
||||
PLV_N8 = 0x5A61,
|
||||
PLV_N9 = 0x5A62,
|
||||
PLV_NA = 0x5A63,
|
||||
PLV_NB = 0x5A64,
|
||||
PLV_NC = 0x5A65,
|
||||
PLV_X1 = 0x5A66,
|
||||
PLV_X2 = 0x5A67,
|
||||
PLV_X3 = 0x5A68,
|
||||
PLV_X4 = 0x5A69,
|
||||
PLV_X5 = 0x5A6A,
|
||||
PLV_X6 = 0x5A6B,
|
||||
PLV_X7 = 0x5A6C,
|
||||
PLV_X8 = 0x5A6D,
|
||||
PLV_X9 = 0x5A6E,
|
||||
PLV_X10 = 0x5A6F,
|
||||
PLV_X11 = 0x5A70,
|
||||
PLV_X12 = 0x5A71,
|
||||
PLV_X13 = 0x5A72,
|
||||
PLV_X14 = 0x5A73,
|
||||
PLV_X15 = 0x5A74,
|
||||
PLV_X16 = 0x5A75,
|
||||
PLV_X17 = 0x5A76,
|
||||
PLV_X18 = 0x5A77,
|
||||
PLV_X19 = 0x5A78,
|
||||
PLV_X20 = 0x5A79,
|
||||
PLV_X21 = 0x5A7A,
|
||||
PLV_X22 = 0x5A7B,
|
||||
PLV_X23 = 0x5A7C,
|
||||
PLV_X24 = 0x5A7D,
|
||||
PLV_X25 = 0x5A7E,
|
||||
PLV_X26 = 0x5A7F,
|
||||
QK_MAGIC_SWAP_CONTROL_CAPS_LOCK = 0x7000,
|
||||
QK_MAGIC_UNSWAP_CONTROL_CAPS_LOCK = 0x7001,
|
||||
QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK = 0x7002,
|
||||
@@ -1483,6 +1549,7 @@ enum qk_keycode_defines {
|
||||
#define IS_QK_PERSISTENT_DEF_LAYER(code) ((code) >= QK_PERSISTENT_DEF_LAYER && (code) <= QK_PERSISTENT_DEF_LAYER_MAX)
|
||||
#define IS_QK_SWAP_HANDS(code) ((code) >= QK_SWAP_HANDS && (code) <= QK_SWAP_HANDS_MAX)
|
||||
#define IS_QK_TAP_DANCE(code) ((code) >= QK_TAP_DANCE && (code) <= QK_TAP_DANCE_MAX)
|
||||
#define IS_QK_PLOVER_HID(code) ((code) >= QK_PLOVER_HID && (code) <= QK_PLOVER_HID_MAX)
|
||||
#define IS_QK_MAGIC(code) ((code) >= QK_MAGIC && (code) <= QK_MAGIC_MAX)
|
||||
#define IS_QK_MIDI(code) ((code) >= QK_MIDI && (code) <= QK_MIDI_MAX)
|
||||
#define IS_QK_SEQUENCER(code) ((code) >= QK_SEQUENCER && (code) <= QK_SEQUENCER_MAX)
|
||||
@@ -1509,6 +1576,7 @@ enum qk_keycode_defines {
|
||||
#define IS_MOUSE_KEYCODE(code) ((code) >= QK_MOUSE_CURSOR_UP && (code) <= QK_MOUSE_ACCELERATION_2)
|
||||
#define IS_MODIFIER_KEYCODE(code) ((code) >= KC_LEFT_CTRL && (code) <= KC_RIGHT_GUI)
|
||||
#define IS_SWAP_HANDS_KEYCODE(code) ((code) >= QK_SWAP_HANDS_TOGGLE && (code) <= QK_SWAP_HANDS_ONE_SHOT)
|
||||
#define IS_PLOVER_HID_KEYCODE(code) ((code) >= PLV_S1 && (code) <= PLV_X26)
|
||||
#define IS_MAGIC_KEYCODE(code) ((code) >= QK_MAGIC_SWAP_CONTROL_CAPS_LOCK && (code) <= QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK)
|
||||
#define IS_MIDI_KEYCODE(code) ((code) >= QK_MIDI_ON && (code) <= QK_MIDI_PITCH_BEND_UP)
|
||||
#define IS_SEQUENCER_KEYCODE(code) ((code) >= QK_SEQUENCER_ON && (code) <= QK_SEQUENCER_STEPS_CLEAR)
|
||||
@@ -1535,6 +1603,7 @@ enum qk_keycode_defines {
|
||||
#define MOUSE_KEYCODE_RANGE QK_MOUSE_CURSOR_UP ... QK_MOUSE_ACCELERATION_2
|
||||
#define MODIFIER_KEYCODE_RANGE KC_LEFT_CTRL ... KC_RIGHT_GUI
|
||||
#define SWAP_HANDS_KEYCODE_RANGE QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT
|
||||
#define PLOVER_HID_KEYCODE_RANGE PLV_S1 ... PLV_X26
|
||||
#define MAGIC_KEYCODE_RANGE QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK
|
||||
#define MIDI_KEYCODE_RANGE QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP
|
||||
#define SEQUENCER_KEYCODE_RANGE QK_SEQUENCER_ON ... QK_SEQUENCER_STEPS_CLEAR
|
||||
|
||||
@@ -55,6 +55,11 @@ int main(void) {
|
||||
raw_hid_task();
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
void plover_hid_task(void);
|
||||
plover_hid_task();
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
void console_task(void);
|
||||
console_task();
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Copyright 2021 dnaq
|
||||
*
|
||||
* 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
|
||||
|
||||
void plover_hid_update(uint8_t button, bool pressed);
|
||||
void plover_hid_task(void);
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2021 dnaq
|
||||
*
|
||||
* 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_plover_hid.h"
|
||||
#include "plover_hid.h"
|
||||
|
||||
bool process_plover_hid(uint16_t keycode, keyrecord_t *record) {
|
||||
if (!IS_QK_PLOVER_HID(keycode)) {
|
||||
return true;
|
||||
}
|
||||
plover_hid_update(keycode - QK_PLOVER_HID, record->event.pressed);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* Copyright 2021 dnaq
|
||||
*
|
||||
* 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 "quantum.h"
|
||||
|
||||
bool process_plover_hid(uint16_t keycode, keyrecord_t *record);
|
||||
@@ -374,6 +374,9 @@ bool process_record_quantum(keyrecord_t *record) {
|
||||
#if defined(LED_MATRIX_ENABLE)
|
||||
process_led_matrix(keycode, record) &&
|
||||
#endif
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
process_plover_hid(keycode, record) &&
|
||||
#endif
|
||||
#ifdef STENO_ENABLE
|
||||
process_steno(keycode, record) &&
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,10 @@ extern layer_state_t layer_state;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
# include "process_plover_hid.h"
|
||||
#endif
|
||||
|
||||
#ifdef STENO_ENABLE
|
||||
# include "process_steno.h"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "azoteq_iqs5xx.h"
|
||||
|
||||
static azoteq_iqs5xx_base_data_t mock_base_data;
|
||||
static i2c_status_t mock_read_status = I2C_STATUS_SUCCESS;
|
||||
|
||||
void azoteq_iqs5xx_mock_reset(void) {
|
||||
memset(&mock_base_data, 0, sizeof(mock_base_data));
|
||||
mock_read_status = I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void azoteq_iqs5xx_mock_set_base_data(azoteq_iqs5xx_base_data_t base_data) {
|
||||
mock_base_data = base_data;
|
||||
mock_read_status = I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void i2c_init(void) {}
|
||||
|
||||
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
|
||||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t *data, uint16_t length, uint16_t timeout) {
|
||||
if (mock_read_status == I2C_STATUS_SUCCESS && data != NULL) {
|
||||
memcpy(data, &mock_base_data, MIN(length, sizeof(mock_base_data)));
|
||||
}
|
||||
return mock_read_status;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t *data, uint16_t length, uint16_t timeout) {
|
||||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
|
||||
if (pressed) {
|
||||
buttons |= 1 << button;
|
||||
} else {
|
||||
buttons &= ~(1 << button);
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#define AZOTEQ_IQS5XX_TPS43
|
||||
@@ -0,0 +1,8 @@
|
||||
# Copyright 2026 QMK
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
SRC += drivers/sensors/azoteq_iqs5xx.c
|
||||
SRC += tests/pointing/azoteq_iqs5xx/azoteq_iqs5xx_mock.c
|
||||
|
||||
VPATH += $(QUANTUM_DIR)/pointing_device
|
||||
VPATH += drivers/sensors
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2026 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
extern "C" {
|
||||
#include "azoteq_iqs5xx.h"
|
||||
|
||||
void azoteq_iqs5xx_mock_reset(void);
|
||||
void azoteq_iqs5xx_mock_set_base_data(azoteq_iqs5xx_base_data_t base_data);
|
||||
}
|
||||
|
||||
class AzoteqIqs5xx : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
azoteq_iqs5xx_mock_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AzoteqIqs5xx, PreservesIncomingButtonsWhenReportingMovement) {
|
||||
azoteq_iqs5xx_base_data_t base_data = {0};
|
||||
base_data.number_of_fingers = 1;
|
||||
base_data.x.l = 12;
|
||||
base_data.y.l = 34;
|
||||
azoteq_iqs5xx_mock_set_base_data(base_data);
|
||||
|
||||
report_mouse_t input_report = {0};
|
||||
input_report.buttons = (1 << POINTING_DEVICE_BUTTON1) | (1 << POINTING_DEVICE_BUTTON2);
|
||||
|
||||
report_mouse_t report = azoteq_iqs5xx_get_report(input_report);
|
||||
|
||||
EXPECT_EQ(report.x, 12);
|
||||
EXPECT_EQ(report.y, 34);
|
||||
EXPECT_EQ(report.h, 0);
|
||||
EXPECT_EQ(report.v, 0);
|
||||
EXPECT_EQ(report.buttons, input_report.buttons);
|
||||
}
|
||||
|
||||
TEST_F(AzoteqIqs5xx, CombinesGestureButtonWithIncomingButtons) {
|
||||
azoteq_iqs5xx_base_data_t base_data = {0};
|
||||
base_data.gesture_events_1.two_finger_tap = true;
|
||||
azoteq_iqs5xx_mock_set_base_data(base_data);
|
||||
|
||||
report_mouse_t input_report = {0};
|
||||
input_report.buttons = 1 << POINTING_DEVICE_BUTTON1;
|
||||
|
||||
report_mouse_t report = azoteq_iqs5xx_get_report(input_report);
|
||||
|
||||
EXPECT_EQ(report.x, 0);
|
||||
EXPECT_EQ(report.y, 0);
|
||||
EXPECT_EQ(report.h, 0);
|
||||
EXPECT_EQ(report.v, 0);
|
||||
EXPECT_EQ(report.buttons, input_report.buttons | (1 << POINTING_DEVICE_BUTTON2));
|
||||
}
|
||||
@@ -80,6 +80,14 @@ usb_endpoint_in_t usb_endpoints_in[USB_ENDPOINT_IN_COUNT] = {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(PLOVER_HID_ENABLE)
|
||||
# if defined(USB_ENDPOINTS_ARE_REORDERABLE)
|
||||
[USB_ENDPOINT_IN_PLOVER_HID] = QMK_USB_ENDPOINT_IN_SHARED(USB_EP_MODE_TYPE_INTR, PLOVER_HID_EPSIZE, PLOVER_HID_IN_EPNUM, PLOVER_HID_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(PLOVER_HID_EPSIZE)),
|
||||
# else
|
||||
[USB_ENDPOINT_IN_PLOVER_HID] = QMK_USB_ENDPOINT_IN(USB_EP_MODE_TYPE_INTR, PLOVER_HID_EPSIZE, PLOVER_HID_IN_EPNUM, PLOVER_HID_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(PLOVER_HID_EPSIZE)),
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MIDI_ENABLE)
|
||||
# if defined(USB_ENDPOINTS_ARE_REORDERABLE)
|
||||
[USB_ENDPOINT_IN_MIDI] = QMK_USB_ENDPOINT_IN_SHARED(USB_EP_MODE_TYPE_BULK, MIDI_STREAM_EPSIZE, MIDI_STREAM_IN_EPNUM, MIDI_STREAM_IN_CAPACITY, NULL, NULL),
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
# define RAW_OUT_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
|
||||
#endif
|
||||
|
||||
#if !defined(PLOVER_HID_IN_CAPACITY)
|
||||
# define PLOVER_HID_IN_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
|
||||
#endif
|
||||
|
||||
#if !defined(MIDI_STREAM_IN_CAPACITY)
|
||||
# define MIDI_STREAM_IN_CAPACITY USB_DEFAULT_BUFFER_CAPACITY
|
||||
#endif
|
||||
@@ -90,6 +94,10 @@ typedef enum {
|
||||
USB_ENDPOINT_IN_RAW,
|
||||
#endif
|
||||
|
||||
#if defined(PLOVER_HID_ENABLE)
|
||||
USB_ENDPOINT_IN_PLOVER_HID,
|
||||
#endif
|
||||
|
||||
#if defined(MIDI_ENABLE)
|
||||
USB_ENDPOINT_IN_MIDI,
|
||||
#endif
|
||||
@@ -127,6 +135,7 @@ typedef enum {
|
||||
#if defined(RAW_ENABLE)
|
||||
USB_ENDPOINT_OUT_RAW,
|
||||
#endif
|
||||
|
||||
#if defined(MIDI_ENABLE)
|
||||
USB_ENDPOINT_OUT_MIDI,
|
||||
#endif
|
||||
|
||||
@@ -523,6 +523,28 @@ void raw_hid_task(void) {
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
static bool plover_hid_report_updated = false;
|
||||
static uint8_t plover_hid_current_report[PLOVER_HID_EPSIZE] = {0x50};
|
||||
|
||||
void plover_hid_update(uint8_t button, bool pressed) {
|
||||
if (pressed) {
|
||||
plover_hid_current_report[1 + button / 8] |= (1 << (7 - (button % 8)));
|
||||
} else {
|
||||
plover_hid_current_report[1 + button / 8] &= ~(1 << (7 - (button % 8)));
|
||||
}
|
||||
plover_hid_report_updated = true;
|
||||
}
|
||||
|
||||
void plover_hid_task(void) {
|
||||
if (!plover_hid_report_updated) {
|
||||
return;
|
||||
}
|
||||
send_report(USB_ENDPOINT_IN_PLOVER_HID, plover_hid_current_report, sizeof(plover_hid_current_report));
|
||||
plover_hid_report_updated = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
|
||||
void send_midi_packet(MIDI_EventPacket_t *event) {
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
# include "raw_hid.h"
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
# include "plover_hid.h"
|
||||
#endif
|
||||
|
||||
#ifdef WAIT_FOR_USB
|
||||
// TODO: Remove backwards compatibility with old define
|
||||
# define USB_WAIT_FOR_ENUMERATION
|
||||
@@ -179,6 +183,28 @@ void raw_hid_task(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
static bool plover_hid_report_updated = false;
|
||||
static uint8_t plover_hid_current_report[PLOVER_HID_EPSIZE] = {0x50};
|
||||
|
||||
void plover_hid_update(uint8_t button, bool pressed) {
|
||||
if (pressed) {
|
||||
plover_hid_current_report[1 + button / 8] |= (1 << (7 - (button % 8)));
|
||||
} else {
|
||||
plover_hid_current_report[1 + button / 8] &= ~(1 << (7 - (button % 8)));
|
||||
}
|
||||
plover_hid_report_updated = true;
|
||||
}
|
||||
|
||||
void plover_hid_task(void) {
|
||||
if (!plover_hid_report_updated) {
|
||||
return;
|
||||
}
|
||||
send_report(PLOVER_HID_IN_EPNUM, plover_hid_current_report, sizeof(plover_hid_current_report));
|
||||
plover_hid_report_updated = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Console
|
||||
******************************************************************************/
|
||||
@@ -347,6 +373,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint((RAW_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, RAW_EPSIZE, 1);
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
/* Setup plover HID endpoints */
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint((PLOVER_HID_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, PLOVER_HID_EPSIZE, 1);
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
/* Setup console endpoint */
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint((CONSOLE_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, CONSOLE_EPSIZE, 1);
|
||||
@@ -846,6 +877,10 @@ void protocol_post_task(void) {
|
||||
MIDI_Device_USBTask(&USB_MIDI_Interface);
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
plover_hid_task();
|
||||
#endif
|
||||
|
||||
#ifdef VIRTSER_ENABLE
|
||||
virtser_task();
|
||||
CDC_Device_USBTask(&cdc_device);
|
||||
|
||||
@@ -478,6 +478,24 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM PloverReport[] = {
|
||||
HID_RI_USAGE_PAGE(16, 0xff50), //
|
||||
HID_RI_USAGE(16, 0x4c56), // Vendor Defined (0xff P L V)
|
||||
HID_RI_COLLECTION(8, 0x01), // Application
|
||||
HID_RI_REPORT_ID(8, 80),
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 1),
|
||||
HID_RI_REPORT_SIZE(8, 1),
|
||||
HID_RI_REPORT_COUNT(8, 64),
|
||||
HID_RI_USAGE_PAGE(8, 0x0a), // Usage Page: Ordinal
|
||||
HID_RI_USAGE_MINIMUM(8, 0),
|
||||
HID_RI_USAGE_MAXIMUM(8, 63),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
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)
|
||||
@@ -643,6 +661,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
/*
|
||||
* Plover HID
|
||||
*/
|
||||
.Plover_Interface = {
|
||||
.Header = {
|
||||
.Size = sizeof(USB_Descriptor_Interface_t),
|
||||
.Type = DTYPE_Interface
|
||||
},
|
||||
.InterfaceNumber = PLOVER_HID_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
.TotalEndpoints = 1,
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
.Plover_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(PloverReport)
|
||||
},
|
||||
.Plover_INEndpoint = {
|
||||
.Header = {
|
||||
.Size = sizeof(USB_Descriptor_Endpoint_t),
|
||||
.Type = DTYPE_Endpoint
|
||||
},
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | PLOVER_HID_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = PLOVER_HID_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
/*
|
||||
* Mouse
|
||||
@@ -1285,6 +1343,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
case PLOVER_HID_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Plover_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
case CONSOLE_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Console_HID;
|
||||
@@ -1342,6 +1408,14 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
case PLOVER_HID_INTERFACE:
|
||||
Address = &PloverReport;
|
||||
Size = sizeof(PloverReport);
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
case CONSOLE_INTERFACE:
|
||||
Address = &ConsoleReport;
|
||||
|
||||
@@ -78,6 +78,13 @@ typedef struct {
|
||||
USB_Descriptor_Endpoint_t Raw_OUTEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
// Plover HID Interface
|
||||
USB_Descriptor_Interface_t Plover_Interface;
|
||||
USB_HID_Descriptor_HID_t Plover_HID;
|
||||
USB_Descriptor_Endpoint_t Plover_INEndpoint;
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
// Mouse HID Interface
|
||||
USB_Descriptor_Interface_t Mouse_Interface;
|
||||
@@ -164,6 +171,10 @@ enum usb_interfaces {
|
||||
RAW_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
PLOVER_HID_INTERFACE,
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
MOUSE_INTERFACE,
|
||||
#endif
|
||||
@@ -227,6 +238,10 @@ enum usb_endpoints {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PLOVER_HID_ENABLE
|
||||
PLOVER_HID_IN_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
SHARED_IN_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
@@ -287,6 +302,7 @@ enum usb_endpoints {
|
||||
#define SHARED_EPSIZE 32
|
||||
#define MOUSE_EPSIZE 16
|
||||
#define RAW_EPSIZE 32
|
||||
#define PLOVER_HID_EPSIZE 9
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define MIDI_STREAM_EPSIZE 64
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
|
||||
Reference in New Issue
Block a user