mirror of
https://github.com/zmkfirmware/zmk.git
synced 2026-03-26 07:55:17 -05:00
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:
@@ -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"};
|
||||
|
||||
Reference in New Issue
Block a user