aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPete Johanson <[email protected]>2021-03-15 00:40:09 -0400
committerPete Johanson <[email protected]>2021-10-04 23:01:39 -0400
commit91ba034896c3b1668b88286e18d8f38314ec39c3 (patch)
tree1a4999351ee331d9d8f205b539c7c5604d9ef39f
parent063b496c26316026e95cf7cdb0ba6c343b6c6efb (diff)
downloadzmk-91ba034896c3b1668b88286e18d8f38314ec39c3.tar.gz
zmk-91ba034896c3b1668b88286e18d8f38314ec39c3.zip
feat(hid): Configurable NKRO HID report support.
* Add Kconfig settings for NKRO or HKRO (boot compatible), HID report types for keyboard page. * Updated report storage and set/unset for each config.
-rw-r--r--app/Kconfig40
-rw-r--r--app/include/zmk/hid.h49
-rw-r--r--app/src/hid.c44
3 files changed, 117 insertions, 16 deletions
diff --git a/app/Kconfig b/app/Kconfig
index f23930b4ff..629dfa7007 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -25,7 +25,40 @@ config USB_DEVICE_PID
config USB_DEVICE_MANUFACTURER
default "ZMK Project"
-menu "HID Output Types"
+menu "HID"
+
+choice ZMK_HID_REPORT_TYPE
+ prompt "HID Report Type"
+
+config ZMK_HID_REPORT_TYPE_HKRO
+ bool "#-Key Roll Over (HKRO) HID Report"
+ help
+ Enable # key roll over for HID report. This selection is "boot keyboard" compatible
+ but limits the total number of possible keys to report as held to #.
+
+config ZMK_HID_REPORT_TYPE_NKRO
+ bool "Full N-Key Roll Over (NKRO) HID Report"
+ help
+ Enable full N-Key Roll Over for HID output. This selection will prevent the keyboard
+ from working with some BIOS/UEFI versions that only support "boot keyboard" support.
+ This option also prevents using some infrequently used higher range HID usages.
+
+endchoice
+
+if ZMK_HID_REPORT_TYPE_HKRO
+
+config ZMK_HID_KEYBOARD_REPORT_SIZE
+ int "# Keyboard Keys Reportable"
+ default 6
+
+
+endif
+
+config ZMK_HID_CONSUMER_REPORT_SIZE
+ int "# Consumer Keys Reportable"
+ default 6
+
+menu "Output Types"
config ZMK_USB
bool "USB"
@@ -92,7 +125,10 @@ config ZMK_BLE_PASSKEY_ENTRY
#ZMK_BLE
endif
-#HID Output Types
+#Output Types
+endmenu
+
+# HID
endmenu
menu "Split Support"
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
index 5aa004c2d2..be88c1753b 100644
--- a/app/include/zmk/hid.h
+++ b/app/include/zmk/hid.h
@@ -13,11 +13,9 @@
#include <dt-bindings/zmk/hid_usage.h>
#include <dt-bindings/zmk/hid_usage_pages.h>
-#define COLLECTION_REPORT 0x03
-
-#define ZMK_HID_KEYBOARD_NKRO_SIZE 6
+#define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL
-#define ZMK_HID_CONSUMER_NKRO_SIZE 6
+#define COLLECTION_REPORT 0x03
static const uint8_t zmk_hid_report_desc[] = {
/* USAGE_PAGE (Generic Desktop) */
@@ -74,6 +72,30 @@ static const uint8_t zmk_hid_report_desc[] = {
/* USAGE_PAGE (Keyboard/Keypad) */
HID_GI_USAGE_PAGE,
HID_USAGE_KEY,
+
+#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
+ /* LOGICAL_MINIMUM (0) */
+ HID_GI_LOGICAL_MIN(1),
+ 0x00,
+ /* LOGICAL_MAXIMUM (1) */
+ HID_GI_LOGICAL_MAX(1),
+ 0x01,
+ /* USAGE_MINIMUM (Reserved) */
+ HID_LI_USAGE_MIN(1),
+ 0x00,
+ /* USAGE_MAXIMUM (Keyboard Application) */
+ HID_LI_USAGE_MAX(1),
+ ZMK_HID_KEYBOARD_NKRO_MAX_USAGE,
+ /* REPORT_SIZE (8) */
+ HID_GI_REPORT_SIZE,
+ 0x01,
+ /* REPORT_COUNT (6) */
+ HID_GI_REPORT_COUNT,
+ ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1,
+ /* INPUT (Data,Ary,Abs) */
+ HID_MI_INPUT,
+ 0x02,
+#elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO)
/* LOGICAL_MINIMUM (0) */
HID_GI_LOGICAL_MIN(1),
0x00,
@@ -89,12 +111,15 @@ static const uint8_t zmk_hid_report_desc[] = {
/* REPORT_SIZE (1) */
HID_GI_REPORT_SIZE,
0x08,
- /* REPORT_COUNT (ZMK_HID_KEYBOARD_NKRO_SIZE) */
+ /* REPORT_COUNT (CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE) */
HID_GI_REPORT_COUNT,
- ZMK_HID_KEYBOARD_NKRO_SIZE,
+ CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE,
/* INPUT (Data,Ary,Abs) */
HID_MI_INPUT,
0x00,
+#else
+#error "A proper HID report type must be selected"
+#endif
/* END_COLLECTION */
HID_MI_COLLECTION_END,
@@ -130,9 +155,9 @@ static const uint8_t zmk_hid_report_desc[] = {
/* REPORT_SIZE (16) */
HID_GI_REPORT_SIZE,
0x10,
- /* REPORT_COUNT (ZMK_HID_CONSUMER_NKRO_SIZE) */
+ /* REPORT_COUNT (CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE) */
HID_GI_REPORT_COUNT,
- ZMK_HID_CONSUMER_NKRO_SIZE,
+ CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE,
HID_MI_INPUT,
0x00,
/* END COLLECTION */
@@ -149,7 +174,11 @@ static const uint8_t zmk_hid_report_desc[] = {
struct zmk_hid_keyboard_report_body {
zmk_mod_flags_t modifiers;
uint8_t _reserved;
- uint8_t keys[ZMK_HID_KEYBOARD_NKRO_SIZE];
+#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
+ uint8_t keys[(ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1) / 8];
+#elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO)
+ uint8_t keys[CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE];
+#endif
} __packed;
struct zmk_hid_keyboard_report {
@@ -158,7 +187,7 @@ struct zmk_hid_keyboard_report {
} __packed;
struct zmk_hid_consumer_report_body {
- uint16_t keys[ZMK_HID_CONSUMER_NKRO_SIZE];
+ uint16_t keys[CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE];
} __packed;
struct zmk_hid_consumer_report {
diff --git a/app/src/hid.c b/app/src/hid.c
index 7ab080e578..756ed9005e 100644
--- a/app/src/hid.c
+++ b/app/src/hid.c
@@ -69,8 +69,30 @@ int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) {
return 0;
}
+#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
+
+#define TOGGLE_KEYBOARD(code, val) WRITE_BIT(keyboard_report.body.keys[code / 8], code % 8, val)
+
+static inline int select_keyboard_usage(zmk_key_t usage) {
+ if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
+ return -EINVAL;
+ }
+ TOGGLE_KEYBOARD(usage, 1);
+ return 0;
+}
+
+static inline int deselect_keyboard_usage(zmk_key_t usage) {
+ if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
+ return -EINVAL;
+ }
+ TOGGLE_KEYBOARD(usage, 0);
+ return 0;
+}
+
+#elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO)
+
#define TOGGLE_KEYBOARD(match, val) \
- for (int idx = 0; idx < ZMK_HID_KEYBOARD_NKRO_SIZE; idx++) { \
+ for (int idx = 0; idx < CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE; idx++) { \
if (keyboard_report.body.keys[idx] != match) { \
continue; \
} \
@@ -80,8 +102,22 @@ int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) {
} \
}
+static inline int select_keyboard_usage(zmk_key_t usage) {
+ TOGGLE_KEYBOARD(0U, usage);
+ return 0;
+}
+
+static inline int deselect_keyboard_usage(zmk_key_t usage) {
+ TOGGLE_KEYBOARD(usage, 0U);
+ return 0;
+}
+
+#else
+#error "A proper HID report type must be selected"
+#endif
+
#define TOGGLE_CONSUMER(match, val) \
- for (int idx = 0; idx < ZMK_HID_CONSUMER_NKRO_SIZE; idx++) { \
+ for (int idx = 0; idx < CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE; idx++) { \
if (consumer_report.body.keys[idx] != match) { \
continue; \
} \
@@ -105,7 +141,7 @@ int zmk_hid_keyboard_press(zmk_key_t code) {
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
return zmk_hid_register_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
}
- TOGGLE_KEYBOARD(0U, code);
+ select_keyboard_usage(code);
return 0;
};
@@ -113,7 +149,7 @@ int zmk_hid_keyboard_release(zmk_key_t code) {
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
return zmk_hid_unregister_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
}
- TOGGLE_KEYBOARD(code, 0U);
+ deselect_keyboard_usage(code);
return 0;
};