feat(mouse): Add mouse move and scroll support (#2477)

* feat(mouse): Add mouse move and scroll support

    * Use Zephyr input subsystem for all pointers.
    * Input processors for modifying events, e.g. scaling, swapping
      codes, temporary (mouse) layers, etc.
    * Mouse move/scroll behaviors.
    * Infrastructure in place for physical pointer input devices.

* feat: Add input split support.

* docs: Add initial pointer docs.

---------

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
Co-authored-by: Alexander Krikun <krikun98@gmail.com>
Co-authored-by: Robert U <urob@users.noreply.github.com>
Co-authored-by: Shawn Meier <ftc@users.noreply.github.com>
Co-authored-by: Chris Andreae <chris@andreae.gen.nz>
Co-authored-by: Anant Thazhemadam <47104651+thazhemadam@users.noreply.github.com>
Co-authored-by: Erik Tollerud <erik.tollerud@gmail.com>
Co-authored-by: Nicolas Munnich <98408764+Nick-Munnich@users.noreply.github.com>
This commit is contained in:
Pete Johanson
2024-12-09 17:45:41 -07:00
committed by GitHub
parent 7e8c542c94
commit 6b40bfda53
119 changed files with 4223 additions and 229 deletions

View File

@@ -18,6 +18,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/endpoints_types.h>
#include <zmk/hog.h>
#include <zmk/hid.h>
#if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
#include <zmk/pointing/resolution_multipliers.h>
#endif // IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
#include <zmk/hid_indicators.h>
#endif // IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
@@ -69,14 +72,23 @@ static struct hids_report consumer_input = {
.type = HIDS_INPUT,
};
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING)
static struct hids_report mouse_input = {
.id = ZMK_HID_REPORT_ID_MOUSE,
.type = HIDS_INPUT,
};
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
static struct hids_report mouse_feature = {
.id = ZMK_HID_REPORT_ID_MOUSE,
.type = HIDS_FEATURE,
};
#endif // IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
#endif // IS_ENABLED(CONFIG_ZMK_POINTING)
static bool host_requests_notification = false;
static uint8_t ctrl_point;
@@ -143,14 +155,53 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
sizeof(struct zmk_hid_consumer_report_body));
}
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING)
static ssize_t read_hids_mouse_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset) {
struct zmk_hid_mouse_report_body *report_body = &zmk_hid_get_mouse_report()->body;
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
sizeof(struct zmk_hid_mouse_report_body));
}
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
static ssize_t read_hids_mouse_feature_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset) {
struct zmk_hid_mouse_report_body *report_body = &zmk_hid_get_mouse_report()->body;
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
sizeof(struct zmk_hid_mouse_report_body));
}
static ssize_t write_hids_mouse_feature_report(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const void *buf,
uint16_t len, uint16_t offset, uint8_t flags) {
if (offset != 0) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (len != sizeof(struct zmk_hid_mouse_resolution_feature_report_body)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
struct zmk_hid_mouse_resolution_feature_report_body *report =
(struct zmk_hid_mouse_resolution_feature_report_body *)buf;
int profile = zmk_ble_profile_index(bt_conn_get_dst(conn));
if (profile < 0) {
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
}
struct zmk_endpoint_instance endpoint = {.transport = ZMK_TRANSPORT_BLE,
.ble = {
.profile_index = profile,
}};
zmk_pointing_resolution_multipliers_process_report(report, endpoint);
return len;
}
#endif // IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
#endif // IS_ENABLED(CONFIG_ZMK_POINTING)
// static ssize_t write_proto_mode(struct bt_conn *conn,
// const struct bt_gatt_attr *attr,
@@ -200,13 +251,23 @@ BT_GATT_SERVICE_DEFINE(
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &consumer_input),
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING)
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT, read_hids_mouse_input_report, NULL, NULL),
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &mouse_input),
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
read_hids_mouse_feature_report, write_hids_mouse_feature_report, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &mouse_feature),
#endif // IS_ENABLED(CONFIG_ZMK_POINTING_SMOOTH_SCROLLING)
#endif // IS_ENABLED(CONFIG_ZMK_POINTING)
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
@@ -328,7 +389,7 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
return 0;
};
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
#if IS_ENABLED(CONFIG_ZMK_POINTING)
K_MSGQ_DEFINE(zmk_hog_mouse_msgq, sizeof(struct zmk_hid_mouse_report_body),
CONFIG_ZMK_BLE_MOUSE_REPORT_QUEUE_SIZE, 4);
@@ -380,8 +441,7 @@ int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) {
return 0;
};
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
#endif // IS_ENABLED(CONFIG_ZMK_POINTING)
static int zmk_hog_init(void) {
static const struct k_work_queue_config queue_config = {.name = "HID Over GATT Send Work"};