Compare commits

...

2 Commits

Author SHA1 Message Date
Graham Held b64014d5df Custom plover HID report type (#26018)
Co-authored-by: Nick Brassel <nick@tzarc.org>
Co-authored-by: dnaq <dnaq@users.noreply.github.com>
2026-06-14 12:38:34 +10:00
Puneet Dixit 0d401d1182 Preserve Azoteq mouse buttons (#26248)
Co-authored-by: Deepak kudi <deepakkudi23@adsl-172-10-9-116.dsl.sndg02.sbcglobal.net>
2026-06-14 09:04:01 +10:00
23 changed files with 721 additions and 5 deletions
+6
View File
@@ -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)
+1
View File
@@ -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"
}
}
}
+18 -1
View File
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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
+5
View File
@@ -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();
+20
View File
@@ -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);
+3
View File
@@ -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
+4
View File
@@ -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;
}
+8
View File
@@ -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
+8
View File
@@ -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
+22
View File
@@ -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) {
+35
View File
@@ -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);
+74
View File
@@ -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;
+16
View File
@@ -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