Boot protocol support
This commit is contained in:
parent
7430750428
commit
d91926211a
8 changed files with 218 additions and 34 deletions
14
app/Kconfig
14
app/Kconfig
|
@ -82,12 +82,26 @@ config ZMK_USB
|
||||||
select USB
|
select USB
|
||||||
select USB_DEVICE_STACK
|
select USB_DEVICE_STACK
|
||||||
select USB_DEVICE_HID
|
select USB_DEVICE_HID
|
||||||
|
select USB_DEVICE_SOF
|
||||||
|
select USB_HID_BOOT_PROTOCOL
|
||||||
|
|
||||||
if ZMK_USB
|
if ZMK_USB
|
||||||
|
|
||||||
config USB_NUMOF_EP_WRITE_RETRIES
|
config USB_NUMOF_EP_WRITE_RETRIES
|
||||||
default 10
|
default 10
|
||||||
|
|
||||||
|
config ZMK_USB_BOOT
|
||||||
|
bool "USB Boot Protocol Support"
|
||||||
|
|
||||||
|
if ZMK_USB_BOOT
|
||||||
|
|
||||||
|
# Declare boot keyboard interface
|
||||||
|
config USB_HID_PROTOCOL_CODE
|
||||||
|
default 1
|
||||||
|
|
||||||
|
#ZMK_USB_BOOT
|
||||||
|
endif
|
||||||
|
|
||||||
#ZMK_USB
|
#ZMK_USB
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
#define COLLECTION_REPORT 0x03
|
#define COLLECTION_REPORT 0x03
|
||||||
|
|
||||||
|
#define HID_REPORT_ID_KEYBOARD 0x01
|
||||||
|
#define HID_REPORT_ID_CONSUMER 0x02
|
||||||
|
|
||||||
static const uint8_t zmk_hid_report_desc[] = {
|
static const uint8_t zmk_hid_report_desc[] = {
|
||||||
/* USAGE_PAGE (Generic Desktop) */
|
/* USAGE_PAGE (Generic Desktop) */
|
||||||
HID_GI_USAGE_PAGE,
|
HID_GI_USAGE_PAGE,
|
||||||
|
@ -29,7 +32,7 @@ static const uint8_t zmk_hid_report_desc[] = {
|
||||||
COLLECTION_APPLICATION,
|
COLLECTION_APPLICATION,
|
||||||
/* REPORT ID (1) */
|
/* REPORT ID (1) */
|
||||||
HID_GI_REPORT_ID,
|
HID_GI_REPORT_ID,
|
||||||
0x01,
|
HID_REPORT_ID_KEYBOARD,
|
||||||
/* USAGE_PAGE (Keyboard/Keypad) */
|
/* USAGE_PAGE (Keyboard/Keypad) */
|
||||||
HID_GI_USAGE_PAGE,
|
HID_GI_USAGE_PAGE,
|
||||||
HID_USAGE_KEY,
|
HID_USAGE_KEY,
|
||||||
|
@ -134,7 +137,7 @@ static const uint8_t zmk_hid_report_desc[] = {
|
||||||
COLLECTION_APPLICATION,
|
COLLECTION_APPLICATION,
|
||||||
/* REPORT ID (1) */
|
/* REPORT ID (1) */
|
||||||
HID_GI_REPORT_ID,
|
HID_GI_REPORT_ID,
|
||||||
0x02,
|
HID_REPORT_ID_CONSUMER,
|
||||||
/* USAGE_PAGE (Consumer) */
|
/* USAGE_PAGE (Consumer) */
|
||||||
HID_GI_USAGE_PAGE,
|
HID_GI_USAGE_PAGE,
|
||||||
HID_USAGE_CONSUMER,
|
HID_USAGE_CONSUMER,
|
||||||
|
@ -187,12 +190,27 @@ static const uint8_t zmk_hid_report_desc[] = {
|
||||||
HID_MI_COLLECTION_END,
|
HID_MI_COLLECTION_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
// struct zmk_hid_boot_report
|
typedef enum {
|
||||||
// {
|
HID_REPORT_FULL,
|
||||||
// uint8_t modifiers;
|
HID_REPORT_BODY
|
||||||
// uint8_t _unused;
|
} zmk_hid_report_request_t;
|
||||||
// uint8_t keys[6];
|
|
||||||
// } __packed;
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
|
||||||
|
#define HID_ERROR_ROLLOVER 0x1
|
||||||
|
#define HID_BOOT_KEY_LEN 6
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO) && CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE == HID_BOOT_KEY_LEN
|
||||||
|
typedef struct zmk_hid_keyboard_report_body zmk_hid_boot_report_t;
|
||||||
|
#else
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
zmk_mod_flags_t modifiers;
|
||||||
|
uint8_t _reserved;
|
||||||
|
uint8_t keys[6];
|
||||||
|
} __packed zmk_hid_boot_report_t;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
struct zmk_hid_keyboard_report_body {
|
struct zmk_hid_keyboard_report_body {
|
||||||
zmk_mod_flags_t modifiers;
|
zmk_mod_flags_t modifiers;
|
||||||
|
@ -237,5 +255,5 @@ int zmk_hid_consumer_press(zmk_key_t key);
|
||||||
int zmk_hid_consumer_release(zmk_key_t key);
|
int zmk_hid_consumer_release(zmk_key_t key);
|
||||||
void zmk_hid_consumer_clear();
|
void zmk_hid_consumer_clear();
|
||||||
|
|
||||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
uint8_t *zmk_hid_get_keyboard_report(zmk_hid_report_request_t req_t, uint8_t proto);
|
||||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
uint8_t *zmk_hid_get_consumer_report(zmk_hid_report_request_t req_t);
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
|
|
||||||
int zmk_hog_init();
|
int zmk_hog_init();
|
||||||
|
|
||||||
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *body);
|
int zmk_hog_send_keyboard_report();
|
||||||
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *body);
|
int zmk_hog_send_consumer_report();
|
||||||
|
|
|
@ -25,5 +25,5 @@ static inline bool zmk_usb_is_powered() { return zmk_usb_get_conn_state() != ZMK
|
||||||
static inline bool zmk_usb_is_hid_ready() { return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID; }
|
static inline bool zmk_usb_is_hid_ready() { return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID; }
|
||||||
|
|
||||||
#ifdef CONFIG_ZMK_USB
|
#ifdef CONFIG_ZMK_USB
|
||||||
int zmk_usb_hid_send_report(const uint8_t *report, size_t len);
|
int zmk_usb_hid_send_report(uint8_t report_id);
|
||||||
#endif /* CONFIG_ZMK_USB */
|
#endif /* CONFIG_ZMK_USB */
|
|
@ -72,12 +72,10 @@ int zmk_endpoints_toggle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_keyboard_report() {
|
static int send_keyboard_report() {
|
||||||
struct zmk_hid_keyboard_report *keyboard_report = zmk_hid_get_keyboard_report();
|
|
||||||
|
|
||||||
switch (current_endpoint) {
|
switch (current_endpoint) {
|
||||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||||
case ZMK_ENDPOINT_USB: {
|
case ZMK_ENDPOINT_USB: {
|
||||||
int err = zmk_usb_hid_send_report((uint8_t *)keyboard_report, sizeof(*keyboard_report));
|
int err = zmk_usb_hid_send_report(HID_REPORT_ID_KEYBOARD);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +85,7 @@ static int send_keyboard_report() {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||||
case ZMK_ENDPOINT_BLE: {
|
case ZMK_ENDPOINT_BLE: {
|
||||||
int err = zmk_hog_send_keyboard_report(&keyboard_report->body);
|
int err = zmk_hog_send_keyboard_report();
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -102,12 +100,10 @@ static int send_keyboard_report() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_consumer_report() {
|
static int send_consumer_report() {
|
||||||
struct zmk_hid_consumer_report *consumer_report = zmk_hid_get_consumer_report();
|
|
||||||
|
|
||||||
switch (current_endpoint) {
|
switch (current_endpoint) {
|
||||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||||
case ZMK_ENDPOINT_USB: {
|
case ZMK_ENDPOINT_USB: {
|
||||||
int err = zmk_usb_hid_send_report((uint8_t *)consumer_report, sizeof(*consumer_report));
|
int err = zmk_usb_hid_send_report(HID_REPORT_ID_CONSUMER);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +113,7 @@ static int send_consumer_report() {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||||
case ZMK_ENDPOINT_BLE: {
|
case ZMK_ENDPOINT_BLE: {
|
||||||
int err = zmk_hog_send_consumer_report(&consumer_report->body);
|
int err = zmk_hog_send_consumer_report();
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,20 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <dt-bindings/zmk/modifiers.h>
|
#include <dt-bindings/zmk/modifiers.h>
|
||||||
|
|
||||||
static struct zmk_hid_keyboard_report keyboard_report = {
|
static struct zmk_hid_keyboard_report keyboard_report = {
|
||||||
.report_id = 1, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
|
.report_id = HID_REPORT_ID_KEYBOARD, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
|
||||||
|
|
||||||
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};
|
static struct zmk_hid_consumer_report consumer_report = {.report_id = HID_REPORT_ID_CONSUMER, .body = {.keys = {0}}};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
#if !IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO) || CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE != HID_BOOT_KEY_LEN
|
||||||
|
static zmk_hid_boot_report_t boot_report = {
|
||||||
|
.modifiers = 0,
|
||||||
|
._reserved = 0,
|
||||||
|
.keys = {0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
static uint8_t keys_held = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Keep track of how often a modifier was pressed.
|
// Keep track of how often a modifier was pressed.
|
||||||
// Only release the modifier if the count is 0.
|
// Only release the modifier if the count is 0.
|
||||||
|
@ -76,15 +87,58 @@ int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
|
||||||
|
static zmk_hid_boot_report_t error_report = {
|
||||||
|
.modifiers = 0,
|
||||||
|
._reserved = 0,
|
||||||
|
.keys = {
|
||||||
|
HID_ERROR_ROLLOVER, HID_ERROR_ROLLOVER, HID_ERROR_ROLLOVER,
|
||||||
|
HID_ERROR_ROLLOVER, HID_ERROR_ROLLOVER, HID_ERROR_ROLLOVER
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HID_CHECK_ROLLOVER_ERROR() \
|
||||||
|
if (keys_held >= HID_BOOT_KEY_LEN) { \
|
||||||
|
error_report.modifiers = keyboard_report.body.modifiers; \
|
||||||
|
return &error_report; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_NKRO)
|
#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)
|
#define TOGGLE_KEYBOARD(code, val) WRITE_BIT(keyboard_report.body.keys[code / 8], code % 8, val)
|
||||||
|
|
||||||
|
static zmk_hid_boot_report_t *get_boot_report() {
|
||||||
|
HID_CHECK_ROLLOVER_ERROR();
|
||||||
|
|
||||||
|
boot_report.modifiers = keyboard_report.body.modifiers;
|
||||||
|
memset(&boot_report.keys, 0, HID_BOOT_KEY_LEN);
|
||||||
|
int ix = 0;
|
||||||
|
uint8_t base_code = 0;
|
||||||
|
for (int i = 0; i < (ZMK_HID_KEYBOARD_NKRO_MAX_USAGE + 1) / 8; ++i) {
|
||||||
|
if (!keyboard_report.body.keys[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
base_code = i * 8;
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
if (keyboard_report.body.keys[i] & BIT(j)) {
|
||||||
|
boot_report.keys[ix++] = base_code + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &boot_report;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int select_keyboard_usage(zmk_key_t usage) {
|
static inline int select_keyboard_usage(zmk_key_t usage) {
|
||||||
if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
|
if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
TOGGLE_KEYBOARD(usage, 1);
|
TOGGLE_KEYBOARD(usage, 1);
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
++keys_held;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +147,9 @@ static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
TOGGLE_KEYBOARD(usage, 0);
|
TOGGLE_KEYBOARD(usage, 0);
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
--keys_held;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +166,31 @@ static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static zmk_hid_boot_report_t *get_boot_report() {
|
||||||
|
HID_CHECK_ROLLOVER_ERROR();
|
||||||
|
#if CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE != HID_BOOT_KEY_LEN
|
||||||
|
boot_report.modifiers = keyboard_report.body.modifiers;
|
||||||
|
int len = CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE < HID_BOOT_KEY_LEN ? CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE : HID_BOOT_KEY_LEN;
|
||||||
|
memcpy(&boot_report.keys, keyboard_report.body.keys, len);
|
||||||
|
return &boot_report;
|
||||||
|
#else
|
||||||
|
return &keyboard_report.body;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline int select_keyboard_usage(zmk_key_t usage) {
|
static inline int select_keyboard_usage(zmk_key_t usage) {
|
||||||
TOGGLE_KEYBOARD(0U, usage);
|
TOGGLE_KEYBOARD(0U, usage);
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
++keys_held;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
||||||
TOGGLE_KEYBOARD(usage, 0U);
|
TOGGLE_KEYBOARD(usage, 0U);
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
--keys_held;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,10 +253,17 @@ int zmk_hid_consumer_release(zmk_key_t code) {
|
||||||
|
|
||||||
void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); }
|
void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); }
|
||||||
|
|
||||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
uint8_t *zmk_hid_get_keyboard_report(zmk_hid_report_request_t req_t, uint8_t proto) {
|
||||||
return &keyboard_report;
|
if (proto == HID_PROTOCOL_REPORT) {
|
||||||
|
return req_t == HID_REPORT_FULL ? (uint8_t*)&keyboard_report : (uint8_t*)&keyboard_report.body;
|
||||||
|
}
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
return (uint8_t*)get_boot_report();
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
|
uint8_t *zmk_hid_get_consumer_report(zmk_hid_report_request_t req_t) {
|
||||||
return &consumer_report;
|
return req_t == HID_REPORT_FULL ? (uint8_t*)&consumer_report : (uint8_t*)&consumer_report.body;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,12 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hids_report input = {
|
static struct hids_report input = {
|
||||||
.id = 0x01,
|
.id = HID_REPORT_ID_KEYBOARD,
|
||||||
.type = HIDS_INPUT,
|
.type = HIDS_INPUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hids_report consumer_input = {
|
static struct hids_report consumer_input = {
|
||||||
.id = 0x02,
|
.id = HID_REPORT_ID_CONSUMER,
|
||||||
.type = HIDS_INPUT,
|
.type = HIDS_INPUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_a
|
||||||
|
|
||||||
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||||
void *buf, uint16_t len, uint16_t offset) {
|
void *buf, uint16_t len, uint16_t offset) {
|
||||||
struct zmk_hid_keyboard_report_body *report_body = &zmk_hid_get_keyboard_report()->body;
|
uint8_t *report_body = zmk_hid_get_keyboard_report(HID_REPORT_BODY, HID_PROTOCOL_REPORT);
|
||||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
||||||
sizeof(struct zmk_hid_keyboard_report_body));
|
sizeof(struct zmk_hid_keyboard_report_body));
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt
|
||||||
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
||||||
const struct bt_gatt_attr *attr, void *buf,
|
const struct bt_gatt_attr *attr, void *buf,
|
||||||
uint16_t len, uint16_t offset) {
|
uint16_t len, uint16_t offset) {
|
||||||
struct zmk_hid_consumer_report_body *report_body = &zmk_hid_get_consumer_report()->body;
|
uint8_t *report_body = zmk_hid_get_consumer_report(HID_REPORT_BODY);
|
||||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
||||||
sizeof(struct zmk_hid_consumer_report_body));
|
sizeof(struct zmk_hid_consumer_report_body));
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,8 @@ void send_keyboard_report_callback(struct k_work *work) {
|
||||||
|
|
||||||
K_WORK_DEFINE(hog_keyboard_work, send_keyboard_report_callback);
|
K_WORK_DEFINE(hog_keyboard_work, send_keyboard_report_callback);
|
||||||
|
|
||||||
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) {
|
int zmk_hog_send_keyboard_report() {
|
||||||
|
uint8_t *report = zmk_hid_get_keyboard_report(HID_REPORT_BODY, HID_PROTOCOL_REPORT);
|
||||||
int err = k_msgq_put(&zmk_hog_keyboard_msgq, report, K_MSEC(100));
|
int err = k_msgq_put(&zmk_hog_keyboard_msgq, report, K_MSEC(100));
|
||||||
if (err) {
|
if (err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
@ -240,7 +241,8 @@ void send_consumer_report_callback(struct k_work *work) {
|
||||||
|
|
||||||
K_WORK_DEFINE(hog_consumer_work, send_consumer_report_callback);
|
K_WORK_DEFINE(hog_consumer_work, send_consumer_report_callback);
|
||||||
|
|
||||||
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
|
int zmk_hog_send_consumer_report() {
|
||||||
|
uint8_t *report = zmk_hid_get_consumer_report(HID_REPORT_BODY);
|
||||||
int err = k_msgq_put(&zmk_hog_consumer_msgq, report, K_MSEC(100));
|
int err = k_msgq_put(&zmk_hog_consumer_msgq, report, K_MSEC(100));
|
||||||
if (err) {
|
if (err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
|
@ -34,11 +34,57 @@ static K_SEM_DEFINE(hid_sem, 1, 1);
|
||||||
|
|
||||||
static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); }
|
static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); }
|
||||||
|
|
||||||
|
#define HID_GET_REPORT_TYPE_MASK 0xff00
|
||||||
|
#define HID_GET_REPORT_ID_MASK 0x00ff
|
||||||
|
|
||||||
|
#define HID_REPORT_TYPE_INPUT 0x100
|
||||||
|
#define HID_REPORT_TYPE_OUTPUT 0x200
|
||||||
|
#define HID_REPORT_TYPE_FEATURE 0x300
|
||||||
|
|
||||||
|
static int zmk_usb_get_report(const struct device *dev,
|
||||||
|
struct usb_setup_packet *setup, int32_t *len,
|
||||||
|
uint8_t **data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7.2.1 of the HID v1.11 spec is unclear about handling requests for reports that do not exist
|
||||||
|
* For requested reports that aren't input reports, return -ENOTSUP like the Zephyr subsys does
|
||||||
|
*/
|
||||||
|
if ((setup->wValue & HID_GET_REPORT_TYPE_MASK) != HID_REPORT_TYPE_INPUT) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *report = NULL;
|
||||||
|
switch (setup->wValue & HID_GET_REPORT_ID_MASK) {
|
||||||
|
case HID_REPORT_ID_KEYBOARD:
|
||||||
|
report = zmk_hid_get_keyboard_report(HID_REPORT_FULL, HID_PROTOCOL_REPORT);
|
||||||
|
*len = sizeof(struct zmk_hid_keyboard_report);
|
||||||
|
break;
|
||||||
|
case HID_REPORT_ID_CONSUMER:
|
||||||
|
report = zmk_hid_get_consumer_report(HID_REPORT_FULL);
|
||||||
|
*len = sizeof(struct zmk_hid_consumer_report);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = report;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
static uint8_t hid_protocol = HID_PROTOCOL_REPORT;
|
||||||
|
void zmk_usb_set_proto_cb(const struct device *dev, uint8_t protocol) {
|
||||||
|
hid_protocol = protocol;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct hid_ops ops = {
|
static const struct hid_ops ops = {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
.protocol_change = zmk_usb_set_proto_cb,
|
||||||
|
#endif
|
||||||
.int_in_ready = in_ready_cb,
|
.int_in_ready = in_ready_cb,
|
||||||
|
.get_report = zmk_usb_get_report
|
||||||
};
|
};
|
||||||
|
|
||||||
int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
|
int zmk_usb_hid_send_report(uint8_t report_id) {
|
||||||
switch (usb_status) {
|
switch (usb_status) {
|
||||||
case USB_DC_SUSPEND:
|
case USB_DC_SUSPEND:
|
||||||
return usb_wakeup_request();
|
return usb_wakeup_request();
|
||||||
|
@ -49,6 +95,27 @@ int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
default:
|
default:
|
||||||
k_sem_take(&hid_sem, K_MSEC(30));
|
k_sem_take(&hid_sem, K_MSEC(30));
|
||||||
|
uint8_t *report;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (report_id == HID_REPORT_ID_KEYBOARD) {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
report = zmk_hid_get_keyboard_report(HID_REPORT_FULL, hid_protocol);
|
||||||
|
len = hid_protocol == HID_PROTOCOL_BOOT ? sizeof(zmk_hid_boot_report_t) : sizeof(struct zmk_hid_keyboard_report);
|
||||||
|
#else
|
||||||
|
report = zmk_hid_get_keyboard_report(HID_REPORT_FULL, hid_protocol);
|
||||||
|
len = sizeof(struct zmk_hid_keyboard_report);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_USB_BOOT)
|
||||||
|
if (hid_protocol == HID_PROTOCOL_BOOT) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
report = zmk_hid_get_consumer_report(HID_REPORT_FULL);
|
||||||
|
len = sizeof(struct zmk_hid_consumer_report);
|
||||||
|
}
|
||||||
|
|
||||||
int err = hid_int_ep_write(hid_dev, report, len, NULL);
|
int err = hid_int_ep_write(hid_dev, report, len, NULL);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -80,6 +147,11 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) {
|
void usb_status_cb(enum usb_dc_status_code status, const uint8_t *params) {
|
||||||
|
#ifdef CONFIG_ZMK_USB_BOOT
|
||||||
|
if (status == USB_DC_RESET) {
|
||||||
|
hid_protocol = HID_PROTOCOL_REPORT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
usb_status = status;
|
usb_status = status;
|
||||||
k_work_submit(&usb_status_notifier_work);
|
k_work_submit(&usb_status_notifier_work);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue