summaryrefslogtreecommitdiff
path: root/src/usb_hid.c
diff options
context:
space:
mode:
authorPete Johanson <peter@peterjohanson.com>2020-05-12 13:22:07 -0400
committerPete Johanson <peter@peterjohanson.com>2020-05-12 13:22:07 -0400
commitbe53560b77b1144953cfb57202c463495da6c4e7 (patch)
tree843d936463e91a796e16f32e5f278bd9ee442d55 /src/usb_hid.c
parent02bffb009f0c5815209e6a477777d95d72574df2 (diff)
Full NKRO support, fixes for keymap key selection.
Diffstat (limited to 'src/usb_hid.c')
-rw-r--r--src/usb_hid.c171
1 files changed, 146 insertions, 25 deletions
diff --git a/src/usb_hid.c b/src/usb_hid.c
index 688b31c..e155536 100644
--- a/src/usb_hid.c
+++ b/src/usb_hid.c
@@ -3,50 +3,169 @@
#include <usb/usb_device.h>
#include <usb/class/usb_hid.h>
+#include <dt-bindings/zmk/keys.h>
+
+#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;
}