From be53560b77b1144953cfb57202c463495da6c4e7 Mon Sep 17 00:00:00 2001 From: Pete Johanson Date: Tue, 12 May 2020 13:22:07 -0400 Subject: [PATCH] Full NKRO support, fixes for keymap key selection. --- Kconfig | 10 ++ include/dt-bindings/zmk/keys.h | 2 + prj.conf | 3 + src/keymap.c | 4 +- src/usb_hid.c | 171 ++++++++++++++++++++++++++++----- 5 files changed, 163 insertions(+), 27 deletions(-) diff --git a/Kconfig b/Kconfig index 89dc9116..d92a1a48 100644 --- a/Kconfig +++ b/Kconfig @@ -4,4 +4,14 @@ config ZMK_KSCAN_EVENT_QUEUE_SIZE int "Size of the event queue for KSCAN events to buffer events" default 4 + +module = ZMK_KSCAN +module-str = zmk_kscan +source "subsys/logging/Kconfig.template.log_config" + +module = ZMK_USB_HID +module-str = zmk_usb_hid +source "subsys/logging/Kconfig.template.log_config" + + source "Kconfig.zephyr" diff --git a/include/dt-bindings/zmk/keys.h b/include/dt-bindings/zmk/keys.h index 1d5beb80..bf3fcc08 100644 --- a/include/dt-bindings/zmk/keys.h +++ b/include/dt-bindings/zmk/keys.h @@ -60,6 +60,8 @@ #define KC_APP 0x65 +#define KC_RGUI 0xE7 + #define MD_SHFT 0x01 #define KC_ALT 0x02 #define KC_CTRL 0x03 diff --git a/prj.conf b/prj.conf index 572f2e40..1e7300a0 100644 --- a/prj.conf +++ b/prj.conf @@ -1,5 +1,8 @@ CONFIG_KSCAN=y CONFIG_KSCAN_GPIO=y +# CONFIG_LOG=y +# CONFIG_ZMK_KSCAN_LOG_LEVEL_DBG=y +# CONFIG_ZMK_USB_HID_LOG_LEVEL_DBG=y CONFIG_USB=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_HID=y diff --git a/src/keymap.c b/src/keymap.c index 1bb624d6..1f55b1f5 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2,7 +2,7 @@ #include "keymap.h" static u32_t zmk_keymap_layer_state = 0; -static u32_t zmk_keymap_layer_default = 0; +static u8_t zmk_keymap_layer_default = 0; static zmk_key zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_MATRIX_ROWS * ZMK_MATRIX_COLS] = { #if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0) @@ -53,7 +53,7 @@ zmk_key zmk_keymap_keycode_from_position(u32_t row, u32_t column) { for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) { - if ((zmk_keymap_layer_state & BIT(layer)) == BIT(layer)) + if ((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default) { zmk_key key = zmk_keymap[layer][(row * ZMK_MATRIX_ROWS) + column]; if (key == ZC_TRNS) diff --git a/src/usb_hid.c b/src/usb_hid.c index 688b31c5..e155536b 100644 --- a/src/usb_hid.c +++ b/src/usb_hid.c @@ -3,50 +3,169 @@ #include #include +#include + +#include "keymap.h" LOG_MODULE_REGISTER(zmk_usb_hid, CONFIG_ZMK_USB_HID_LOG_LEVEL); -static const u8_t hid_report_desc[] = HID_KEYBOARD_REPORT_DESC(); +#define MAX_KEYCODE KC_APP + +static const u8_t hid_report_desc[] = { + /* USAGE_PAGE (Generic Desktop) */ + HID_GI_USAGE_PAGE, + USAGE_GEN_DESKTOP, + /* USAGE (Keyboard) */ + HID_LI_USAGE, + USAGE_GEN_DESKTOP_KEYBOARD, + /* COLLECTION (Application) */ + HID_MI_COLLECTION, + COLLECTION_APPLICATION, + /* USAGE_PAGE (Keypad) */ + HID_GI_USAGE_PAGE, + USAGE_GEN_DESKTOP_KEYPAD, + /* USAGE_MINIMUM (Keyboard LeftControl) */ + HID_LI_USAGE_MIN(1), + 0xE0, + /* USAGE_MAXIMUM (Keyboard Right GUI) */ + HID_LI_USAGE_MAX(1), + 0xE7, + /* LOGICAL_MINIMUM (0) */ + HID_GI_LOGICAL_MIN(1), + 0x00, + /* LOGICAL_MAXIMUM (1) */ + HID_GI_LOGICAL_MAX(1), + 0x01, + /* REPORT_SIZE (1) */ + HID_GI_REPORT_SIZE, + 0x01, + /* REPORT_COUNT (8) */ + HID_GI_REPORT_COUNT, + 0x08, + /* INPUT (Data,Var,Abs) */ + HID_MI_INPUT, + 0x02, + /* USAGE_PAGE (Keypad) */ + HID_GI_USAGE_PAGE, + USAGE_GEN_DESKTOP_KEYPAD, + /* REPORT_SIZE (8) */ + HID_GI_REPORT_SIZE, + 0x08, + /* REPORT_COUNT (1) */ + HID_GI_REPORT_COUNT, + 0x07, + /* INPUT (Cnst,Var,Abs) */ + HID_MI_INPUT, + 0x03, + + /* USAGE_PAGE (Keypad) */ + HID_GI_USAGE_PAGE, + USAGE_GEN_DESKTOP_KEYPAD, + /* LOGICAL_MINIMUM (0) */ + HID_GI_LOGICAL_MIN(1), + 0x00, + /* LOGICAL_MAXIMUM (101) */ + HID_GI_LOGICAL_MAX(1), + 0x01, + /* USAGE_MINIMUM (Reserved) */ + HID_LI_USAGE_MIN(1), + 0x00, + /* USAGE_MAXIMUM (Keyboard Application) */ + HID_LI_USAGE_MAX(1), + MAX_KEYCODE, + /* REPORT_SIZE (8) */ + HID_GI_REPORT_SIZE, + 0x01, + /* REPORT_COUNT (6) */ + HID_GI_REPORT_COUNT, + MAX_KEYCODE + 1, + /* INPUT (Data,Ary,Abs) */ + HID_MI_INPUT, + 0x02, + /* USAGE_PAGE (Keypad) */ + HID_GI_USAGE_PAGE, + USAGE_GEN_DESKTOP_KEYPAD, + /* REPORT_SIZE (8) */ + HID_GI_REPORT_SIZE, + 0x02, + /* REPORT_COUNT (6) */ + HID_GI_REPORT_COUNT, + 0x01, + /* INPUT (Cnst,Var,Abs) */ + HID_MI_INPUT, + 0x03, + /* END_COLLECTION */ + HID_MI_COLLECTION_END, +}; + static enum usb_dc_status_code usb_status; static struct device *hid_dev; -static u8_t report[8] = { 0x00, 0x00 }; +struct boot_report +{ + u8_t modifiers; + u8_t _unused; + u8_t keys[6]; +} __packed; + +struct extended_report +{ + u8_t keys[13]; +} __packed; + +struct hid_report +{ + struct boot_report boot; + struct extended_report extended; +} __packed report; #define KEY_OFFSET 0x02 #define MAX_KEYS 6 -int zmk_usb_hid_press_key(enum hid_kbd_code code) +#define TOGGLE_BOOT_KEY(match, val) \ + for (int idx = 0; idx < MAX_KEYS; idx++) \ + { \ + if (report.boot.keys[idx + KEY_OFFSET] != match) \ + { \ + continue; \ + } \ + report.boot.keys[idx + KEY_OFFSET] = val; \ + break; \ + } + +#define TOGGLE_EXT_KEY(code, val) WRITE_BIT(report.extended.keys[code / 8], code % 8, val) + +int zmk_usb_hid_press_key(zmk_key code) { - if (usb_status == USB_DC_SUSPEND) { + if (usb_status == USB_DC_SUSPEND) + { return usb_wakeup_request(); } - for (int idx = 0; idx < MAX_KEYS; idx++) { - if (report[idx + KEY_OFFSET] != 0U) { - continue; - } + if (code > MAX_KEYCODE) + { + return -EINVAL; + } - report[idx + KEY_OFFSET] = code; + TOGGLE_BOOT_KEY(0U, code); - return hid_int_ep_write(hid_dev, report, sizeof(report), NULL); - } + TOGGLE_EXT_KEY(code, true); - return -EINVAL; + return hid_int_ep_write(hid_dev, (u8_t *)&report, sizeof(report), NULL); } -int zmk_usb_hid_release_key(enum hid_kbd_code code) +int zmk_usb_hid_release_key(zmk_key code) { - for (int idx = 0; idx < MAX_KEYS; idx++) { - if (report[idx + KEY_OFFSET] != code) { - continue; - } + if (code > MAX_KEYCODE) + { + return -EINVAL; + } - report[idx + KEY_OFFSET] = 0U; + TOGGLE_BOOT_KEY(code, 0U); - return hid_int_ep_write(hid_dev, report, sizeof(report), NULL); - } + TOGGLE_EXT_KEY(code, false); - return -EINVAL; + return hid_int_ep_write(hid_dev, (u8_t *)&report, sizeof(report), NULL); } void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params) @@ -59,20 +178,22 @@ int zmk_usb_hid_init() int usb_enable_ret; hid_dev = device_get_binding("HID_0"); - if (hid_dev == NULL) { + if (hid_dev == NULL) + { LOG_ERR("Unable to locate HID device"); return -EINVAL; } usb_hid_register_device(hid_dev, - hid_report_desc, sizeof(hid_report_desc), - NULL); + hid_report_desc, sizeof(hid_report_desc), + NULL); usb_hid_init(hid_dev); usb_enable_ret = usb_enable(usb_hid_status_cb); - if (usb_enable_ret != 0) { + if (usb_enable_ret != 0) + { LOG_ERR("Unable to enable USB"); return -EINVAL; }