feat: only send HID reports to one endpoint
Added some utility functions and an event for tracking the state of the USB connection. Updated endpoints.c to select a single endpoint to send HID reports to based on the status of the USB and BLE connections. Partially fixes #206. Future commits will add a user setting to control which endpoint is used if both USB and BLE are ready.
This commit is contained in:
parent
dfb69d8727
commit
1d369ffa73
7 changed files with 190 additions and 45 deletions
|
@ -37,6 +37,7 @@ target_sources(app PRIVATE src/events/keycode_state_changed.c)
|
|||
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/sensor_event.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
|
||||
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
|
||||
if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
|
|
20
app/include/zmk/events/usb-conn-state-changed.h
Normal file
20
app/include/zmk/events/usb-conn-state-changed.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <usb/usb_device.h>
|
||||
|
||||
#include <zmk/event-manager.h>
|
||||
#include <zmk/usb.h>
|
||||
|
||||
struct usb_conn_state_changed {
|
||||
struct zmk_event_header header;
|
||||
enum zmk_usb_conn_state conn_state;
|
||||
};
|
||||
|
||||
ZMK_EVENT_DECLARE(usb_conn_state_changed);
|
|
@ -12,8 +12,18 @@
|
|||
#include <zmk/keys.h>
|
||||
#include <zmk/hid.h>
|
||||
|
||||
enum zmk_usb_conn_state {
|
||||
ZMK_USB_CONN_NONE,
|
||||
ZMK_USB_CONN_POWERED,
|
||||
ZMK_USB_CONN_HID,
|
||||
};
|
||||
|
||||
enum usb_dc_status_code zmk_usb_get_status();
|
||||
enum zmk_usb_conn_state zmk_usb_get_conn_state();
|
||||
|
||||
static inline bool zmk_usb_is_powered() { return zmk_usb_get_conn_state() != ZMK_USB_CONN_NONE; }
|
||||
static inline bool zmk_usb_is_hid_ready() { return zmk_usb_get_conn_state() == ZMK_USB_CONN_HID; }
|
||||
|
||||
#ifdef CONFIG_ZMK_USB
|
||||
int zmk_usb_hid_send_report(u8_t *report, size_t len);
|
||||
int zmk_usb_hid_send_report(const u8_t *report, size_t len);
|
||||
#endif /* CONFIG_ZMK_USB */
|
|
@ -8,54 +8,138 @@
|
|||
#include <zmk/hid.h>
|
||||
#include <zmk/usb.h>
|
||||
#include <zmk/hog.h>
|
||||
#include <zmk/event-manager.h>
|
||||
#include <zmk/events/usb-conn-state-changed.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
enum endpoint {
|
||||
ENDPOINT_USB,
|
||||
ENDPOINT_BLE,
|
||||
};
|
||||
|
||||
static enum endpoint current_endpoint =
|
||||
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB));
|
||||
|
||||
static int send_keypad_report() {
|
||||
struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report();
|
||||
|
||||
switch (current_endpoint) {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||
case ENDPOINT_USB: {
|
||||
int err = zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(*keypad_report));
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
case ENDPOINT_BLE: {
|
||||
int err = zmk_hog_send_keypad_report(&keypad_report->body);
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */
|
||||
|
||||
default:
|
||||
LOG_ERR("Unsupported endpoint %d", current_endpoint);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int send_consumer_report() {
|
||||
struct zmk_hid_consumer_report *consumer_report = zmk_hid_get_consumer_report();
|
||||
|
||||
switch (current_endpoint) {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||
case ENDPOINT_USB: {
|
||||
int err = zmk_usb_hid_send_report((u8_t *)consumer_report, sizeof(*consumer_report));
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_USB) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
case ENDPOINT_BLE: {
|
||||
int err = zmk_hog_send_consumer_report(&consumer_report->body);
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_BLE) */
|
||||
|
||||
default:
|
||||
LOG_ERR("Unsupported endpoint %d", current_endpoint);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
int zmk_endpoints_send_report(u8_t usage_page) {
|
||||
int err;
|
||||
struct zmk_hid_keypad_report *keypad_report;
|
||||
struct zmk_hid_consumer_report *consumer_report;
|
||||
|
||||
LOG_DBG("usage page 0x%02X", usage_page);
|
||||
switch (usage_page) {
|
||||
case USAGE_KEYPAD:
|
||||
keypad_report = zmk_hid_get_keypad_report();
|
||||
#ifdef CONFIG_ZMK_USB
|
||||
if (zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(struct zmk_hid_keypad_report)) !=
|
||||
0) {
|
||||
LOG_DBG("USB Send Failed");
|
||||
}
|
||||
#endif /* CONFIG_ZMK_USB */
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE
|
||||
err = zmk_hog_send_keypad_report(&keypad_report->body);
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
#endif /* CONFIG_ZMK_BLE */
|
||||
|
||||
break;
|
||||
return send_keypad_report();
|
||||
case USAGE_CONSUMER:
|
||||
consumer_report = zmk_hid_get_consumer_report();
|
||||
#ifdef CONFIG_ZMK_USB
|
||||
if (zmk_usb_hid_send_report((u8_t *)consumer_report,
|
||||
sizeof(struct zmk_hid_consumer_report)) != 0) {
|
||||
LOG_DBG("USB Send Failed");
|
||||
}
|
||||
#endif /* CONFIG_ZMK_USB */
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE
|
||||
err = zmk_hog_send_consumer_report(&consumer_report->body);
|
||||
if (err) {
|
||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||
}
|
||||
#endif /* CONFIG_ZMK_BLE */
|
||||
|
||||
break;
|
||||
return send_consumer_report();
|
||||
default:
|
||||
LOG_ERR("Unsupported usage page %d", usage_page);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_usb_ready() {
|
||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||
return zmk_usb_is_hid_ready();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_ble_ready() {
|
||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||
return zmk_ble_active_profile_is_connected();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum endpoint get_selected_endpoint() {
|
||||
if (is_ble_ready()) {
|
||||
if (is_usb_ready()) {
|
||||
LOG_DBG("Both endpoints ready. Selecting USB");
|
||||
// TODO: add user setting to control this
|
||||
return ENDPOINT_USB;
|
||||
}
|
||||
|
||||
return ENDPOINT_BLE;
|
||||
}
|
||||
|
||||
return ENDPOINT_USB;
|
||||
}
|
||||
|
||||
static int endpoint_listener(const struct zmk_event_header *eh) {
|
||||
enum endpoint new_endpoint = get_selected_endpoint();
|
||||
|
||||
if (new_endpoint != current_endpoint) {
|
||||
// TODO: send null report on previous endpoint
|
||||
current_endpoint = new_endpoint;
|
||||
LOG_INF("Endpoint changed: %d", current_endpoint);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(endpoint_listener, endpoint_listener);
|
||||
#if IS_ENABLED(CONFIG_USB)
|
||||
ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed);
|
||||
#endif
|
||||
// TODO: add BLE state subscription
|
10
app/src/events/usb_conn_state_changed.c
Normal file
10
app/src/events/usb_conn_state_changed.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <zmk/events/usb-conn-state-changed.h>
|
||||
|
||||
ZMK_EVENT_IMPL(usb_conn_state_changed);
|
|
@ -23,14 +23,7 @@ static u32_t power_last_uptime;
|
|||
|
||||
bool is_usb_power_present() {
|
||||
#ifdef CONFIG_USB
|
||||
enum usb_dc_status_code usb_status = zmk_usb_get_status();
|
||||
switch (usb_status) {
|
||||
case USB_DC_DISCONNECTED:
|
||||
case USB_DC_UNKNOWN:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return zmk_usb_is_powered();
|
||||
#else
|
||||
return false;
|
||||
#endif /* CONFIG_USB */
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/keymap.h>
|
||||
#include <zmk/event-manager.h>
|
||||
#include <zmk/events/usb-conn-state-changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
|
@ -53,9 +55,34 @@ int zmk_usb_hid_send_report(const u8_t *report, size_t len) {
|
|||
|
||||
#endif /* CONFIG_ZMK_USB */
|
||||
|
||||
static void raise_usb_status_changed_event() {
|
||||
struct usb_conn_state_changed *ev = new_usb_conn_state_changed();
|
||||
ev->conn_state = zmk_usb_get_conn_state();
|
||||
|
||||
ZMK_EVENT_RAISE(ev);
|
||||
}
|
||||
|
||||
enum usb_dc_status_code zmk_usb_get_status() { return usb_status; }
|
||||
|
||||
void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) { usb_status = status; };
|
||||
enum zmk_usb_conn_state zmk_usb_get_conn_state() {
|
||||
switch (usb_status) {
|
||||
case USB_DC_DISCONNECTED:
|
||||
case USB_DC_UNKNOWN:
|
||||
return ZMK_USB_CONN_NONE;
|
||||
|
||||
case USB_DC_ERROR:
|
||||
case USB_DC_RESET:
|
||||
return ZMK_USB_CONN_POWERED;
|
||||
|
||||
default:
|
||||
return ZMK_USB_CONN_HID;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_status_cb(enum usb_dc_status_code status, const u8_t *params) {
|
||||
usb_status = status;
|
||||
raise_usb_status_changed_event();
|
||||
};
|
||||
|
||||
static int zmk_usb_init(struct device *_arg) {
|
||||
int usb_enable_ret;
|
||||
|
|
Loading…
Reference in a new issue