You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.2 KiB

/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zmk/ble.h>
#include <zmk/endpoints.h>
#include <zmk/hid.h>
#include <zmk/usb.h>
#include <zmk/hog.h>
#include <zmk/event-manager.h>
#include <zmk/events/ble-active-profile-changed.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,
};
#define DEFAULT_ENDPOINT COND_CODE_1(IS_ENABLED(CONFIG_ZMK_BLE), (ENDPOINT_BLE), (ENDPOINT_USB))
static enum endpoint current_endpoint = DEFAULT_ENDPOINT;
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) {
LOG_DBG("usage page 0x%02X", usage_page);
switch (usage_page) {
case USAGE_KEYPAD:
return send_keypad_report();
case USAGE_CONSUMER:
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 are ready.");
// TODO: add user setting to control this
return ENDPOINT_USB;
}
LOG_DBG("Only BLE is ready.");
return ENDPOINT_BLE;
}
if (is_usb_ready()) {
LOG_DBG("Only USB is ready.");
return ENDPOINT_USB;
}
LOG_DBG("No endpoints are ready.");
return DEFAULT_ENDPOINT;
}
static void disconnect_current_endpoint() {
zmk_hid_keypad_clear();
zmk_hid_consumer_clear();
zmk_endpoints_send_report(USAGE_KEYPAD);
zmk_endpoints_send_report(USAGE_CONSUMER);
}
static int endpoint_listener(const struct zmk_event_header *eh) {
enum endpoint new_endpoint = get_selected_endpoint();
if (new_endpoint != current_endpoint) {
/* Cancel all current keypresses so keys don't stay held on the old endpoint. */
disconnect_current_endpoint();
current_endpoint = new_endpoint;
LOG_INF("Endpoint changed: %d", current_endpoint);
}
return 0;
}
ZMK_LISTENER(endpoint_listener, endpoint_listener);
#if IS_ENABLED(CONFIG_ZMK_USB)
ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed);
#endif
#if IS_ENABLED(CONFIG_ZMK_BLE)
ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed);
#endif