3336 lines
110 KiB
Diff
3336 lines
110 KiB
Diff
From b1deea5cc281d226e603f4b44462b9c661432816 Mon Sep 17 00:00:00 2001
|
|
From: Alexander Krikun <krikun98@gmail.com>
|
|
Date: Tue, 27 Apr 2021 18:24:11 +0300
|
|
Subject: [PATCH 1/2] The original changes from #778
|
|
|
|
A squashed version of the original changeset from
|
|
https://github.com/zmkfirmware/zmk/pull/778 rebased on main
|
|
---
|
|
app/CMakeLists.txt | 10 ++
|
|
app/Kconfig | 11 ++
|
|
app/dts/behaviors.dtsi | 5 +-
|
|
app/dts/behaviors/mouse_key_press.dtsi | 9 +
|
|
app/dts/behaviors/mouse_move.dtsi | 12 ++
|
|
app/dts/behaviors/mouse_scroll.dtsi | 12 ++
|
|
.../zmk,behavior-mouse-key-press.yaml | 5 +
|
|
.../behaviors/zmk,behavior-mouse-move.yaml | 13 ++
|
|
.../behaviors/zmk,behavior-mouse-scroll.yaml | 13 ++
|
|
app/include/dt-bindings/zmk/hid_usage_pages.h | 1 +
|
|
app/include/dt-bindings/zmk/mouse.h | 55 ++++++
|
|
app/include/zmk/endpoints.h | 1 +
|
|
.../zmk/events/mouse_button_state_changed.h | 27 +++
|
|
.../zmk/events/mouse_move_state_changed.h | 33 ++++
|
|
.../zmk/events/mouse_scroll_state_changed.h | 34 ++++
|
|
app/include/zmk/events/mouse_tick.h | 39 +++++
|
|
app/include/zmk/hid.h | 137 ++++++++++++++-
|
|
app/include/zmk/hog.h | 1 +
|
|
app/include/zmk/mouse.h | 30 ++++
|
|
app/src/behaviors/behavior_mouse_key_press.c | 48 ++++++
|
|
app/src/behaviors/behavior_mouse_move.c | 57 +++++++
|
|
app/src/behaviors/behavior_mouse_scroll.c | 58 +++++++
|
|
app/src/endpoints.c | 35 ++++
|
|
app/src/events/mouse_button_state_changed.c | 10 ++
|
|
app/src/events/mouse_move_state_changed.c | 10 ++
|
|
app/src/events/mouse_scroll_state_changed.c | 10 ++
|
|
app/src/events/mouse_tick.c | 10 ++
|
|
app/src/hid.c | 86 ++++++++++
|
|
app/src/hid_listener.c | 12 +-
|
|
app/src/hog.c | 89 ++++++++++
|
|
app/src/main.c | 8 +
|
|
app/src/mouse/Kconfig | 38 +++++
|
|
app/src/mouse/key_listener.c | 160 ++++++++++++++++++
|
|
app/src/mouse/main.c | 30 ++++
|
|
app/src/mouse/tick_listener.c | 102 +++++++++++
|
|
app/tests/mouse-keys/mmv/events.patterns | 1 +
|
|
.../mouse-keys/mmv/keycode_events.snapshot | 2 +
|
|
app/tests/mouse-keys/mmv/native_posix.keymap | 26 +++
|
|
docs/docs/behaviors/mouse-emulation.md | 110 ++++++++++++
|
|
docs/sidebars.js | 1 +
|
|
40 files changed, 1342 insertions(+), 9 deletions(-)
|
|
create mode 100644 app/dts/behaviors/mouse_key_press.dtsi
|
|
create mode 100644 app/dts/behaviors/mouse_move.dtsi
|
|
create mode 100644 app/dts/behaviors/mouse_scroll.dtsi
|
|
create mode 100644 app/dts/bindings/behaviors/zmk,behavior-mouse-key-press.yaml
|
|
create mode 100644 app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
create mode 100644 app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
create mode 100644 app/include/dt-bindings/zmk/mouse.h
|
|
create mode 100644 app/include/zmk/events/mouse_button_state_changed.h
|
|
create mode 100644 app/include/zmk/events/mouse_move_state_changed.h
|
|
create mode 100644 app/include/zmk/events/mouse_scroll_state_changed.h
|
|
create mode 100644 app/include/zmk/events/mouse_tick.h
|
|
create mode 100644 app/include/zmk/mouse.h
|
|
create mode 100644 app/src/behaviors/behavior_mouse_key_press.c
|
|
create mode 100644 app/src/behaviors/behavior_mouse_move.c
|
|
create mode 100644 app/src/behaviors/behavior_mouse_scroll.c
|
|
create mode 100644 app/src/events/mouse_button_state_changed.c
|
|
create mode 100644 app/src/events/mouse_move_state_changed.c
|
|
create mode 100644 app/src/events/mouse_scroll_state_changed.c
|
|
create mode 100644 app/src/events/mouse_tick.c
|
|
create mode 100644 app/src/mouse/Kconfig
|
|
create mode 100644 app/src/mouse/key_listener.c
|
|
create mode 100644 app/src/mouse/main.c
|
|
create mode 100644 app/src/mouse/tick_listener.c
|
|
create mode 100644 app/tests/mouse-keys/mmv/events.patterns
|
|
create mode 100644 app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
create mode 100644 app/tests/mouse-keys/mmv/native_posix.keymap
|
|
create mode 100644 docs/docs/behaviors/mouse-emulation.md
|
|
|
|
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
|
|
index 4b61fc7217..351505ad77 100644
|
|
--- a/app/CMakeLists.txt
|
|
+++ b/app/CMakeLists.txt
|
|
@@ -24,6 +24,9 @@ target_sources(app PRIVATE src/stdlib.c)
|
|
target_sources(app PRIVATE src/activity.c)
|
|
target_sources(app PRIVATE src/kscan.c)
|
|
target_sources(app PRIVATE src/matrix_transform.c)
|
|
+target_sources(app PRIVATE src/mouse/key_listener.c)
|
|
+target_sources(app PRIVATE src/mouse/main.c)
|
|
+target_sources(app PRIVATE src/mouse/tick_listener.c)
|
|
target_sources(app PRIVATE src/sensors.c)
|
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c)
|
|
target_sources(app PRIVATE src/event_manager.c)
|
|
@@ -31,6 +34,10 @@ target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
|
|
target_sources(app PRIVATE src/events/activity_state_changed.c)
|
|
target_sources(app PRIVATE src/events/position_state_changed.c)
|
|
target_sources(app PRIVATE src/events/sensor_event.c)
|
|
+target_sources(app PRIVATE src/events/mouse_button_state_changed.c)
|
|
+target_sources(app PRIVATE src/events/mouse_move_state_changed.c)
|
|
+target_sources(app PRIVATE src/events/mouse_tick.c)
|
|
+target_sources(app PRIVATE src/events/mouse_scroll_state_changed.c)
|
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
|
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
|
@@ -53,6 +60,9 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
|
|
+ target_sources(app PRIVATE src/behaviors/behavior_mouse_key_press.c)
|
|
+ target_sources(app PRIVATE src/behaviors/behavior_mouse_move.c)
|
|
+ target_sources(app PRIVATE src/behaviors/behavior_mouse_scroll.c)
|
|
target_sources(app PRIVATE src/combo.c)
|
|
target_sources(app PRIVATE src/behavior_queue.c)
|
|
target_sources(app PRIVATE src/conditional_layer.c)
|
|
diff --git a/app/Kconfig b/app/Kconfig
|
|
index f89d3279d1..3c59605814 100644
|
|
--- a/app/Kconfig
|
|
+++ b/app/Kconfig
|
|
@@ -127,6 +127,10 @@ config ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE
|
|
int "Max number of consumer HID reports to queue for sending over BLE"
|
|
default 5
|
|
|
|
+config ZMK_BLE_MOUSE_REPORT_QUEUE_SIZE
|
|
+ int "Max number of mouse HID reports to queue for sending over BLE"
|
|
+ default 20
|
|
+
|
|
config ZMK_BLE_CLEAR_BONDS_ON_START
|
|
bool "Configuration that clears all bond information from the keyboard on startup."
|
|
default n
|
|
@@ -285,6 +289,13 @@ endif
|
|
#Display/LED Options
|
|
endmenu
|
|
|
|
+menu "Mouse Options"
|
|
+
|
|
+rsource "src/mouse/Kconfig"
|
|
+
|
|
+#Mouse Options
|
|
+endmenu
|
|
+
|
|
menu "Power Management"
|
|
|
|
config ZMK_IDLE_TIMEOUT
|
|
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
|
|
index b3502cbbc1..77eccf912f 100644
|
|
--- a/app/dts/behaviors.dtsi
|
|
+++ b/app/dts/behaviors.dtsi
|
|
@@ -18,4 +18,7 @@
|
|
#include <behaviors/caps_word.dtsi>
|
|
#include <behaviors/key_repeat.dtsi>
|
|
#include <behaviors/backlight.dtsi>
|
|
-#include <behaviors/macros.dtsi>
|
|
\ No newline at end of file
|
|
+#include <behaviors/macros.dtsi>
|
|
+#include <behaviors/mouse_key_press.dtsi>
|
|
+#include <behaviors/mouse_move.dtsi>
|
|
+#include <behaviors/mouse_scroll.dtsi>
|
|
diff --git a/app/dts/behaviors/mouse_key_press.dtsi b/app/dts/behaviors/mouse_key_press.dtsi
|
|
new file mode 100644
|
|
index 0000000000..8b2aacb366
|
|
--- /dev/null
|
|
+++ b/app/dts/behaviors/mouse_key_press.dtsi
|
|
@@ -0,0 +1,9 @@
|
|
+/ {
|
|
+ behaviors {
|
|
+ /omit-if-no-ref/ mkp: behavior_mouse_key_press {
|
|
+ compatible = "zmk,behavior-mouse-key-press";
|
|
+ label = "MOUSE_KEY_PRESS";
|
|
+ #binding-cells = <1>;
|
|
+ };
|
|
+ };
|
|
+};
|
|
diff --git a/app/dts/behaviors/mouse_move.dtsi b/app/dts/behaviors/mouse_move.dtsi
|
|
new file mode 100644
|
|
index 0000000000..d34329c806
|
|
--- /dev/null
|
|
+++ b/app/dts/behaviors/mouse_move.dtsi
|
|
@@ -0,0 +1,12 @@
|
|
+/ {
|
|
+ behaviors {
|
|
+ /omit-if-no-ref/ mmv: behavior_mouse_move {
|
|
+ compatible = "zmk,behavior-mouse-move";
|
|
+ label = "MOUSE_MOVE";
|
|
+ #binding-cells = <1>;
|
|
+ delay-ms = <0>;
|
|
+ time-to-max-speed-ms = <300>;
|
|
+ acceleration-exponent = <1>;
|
|
+ };
|
|
+ };
|
|
+};
|
|
diff --git a/app/dts/behaviors/mouse_scroll.dtsi b/app/dts/behaviors/mouse_scroll.dtsi
|
|
new file mode 100644
|
|
index 0000000000..fb54886dcb
|
|
--- /dev/null
|
|
+++ b/app/dts/behaviors/mouse_scroll.dtsi
|
|
@@ -0,0 +1,12 @@
|
|
+/ {
|
|
+ behaviors {
|
|
+ /omit-if-no-ref/ mwh: msc: behavior_mouse_scroll {
|
|
+ compatible = "zmk,behavior-mouse-scroll";
|
|
+ label = "MOUSE_SCROLL";
|
|
+ #binding-cells = <1>;
|
|
+ delay-ms = <0>;
|
|
+ time-to-max-speed-ms = <300>;
|
|
+ acceleration-exponent = <0>;
|
|
+ };
|
|
+ };
|
|
+};
|
|
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mouse-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-mouse-key-press.yaml
|
|
new file mode 100644
|
|
index 0000000000..8540916b72
|
|
--- /dev/null
|
|
+++ b/app/dts/bindings/behaviors/zmk,behavior-mouse-key-press.yaml
|
|
@@ -0,0 +1,5 @@
|
|
+description: Mouse key press/release behavior
|
|
+
|
|
+compatible: "zmk,behavior-mouse-key-press"
|
|
+
|
|
+include: one_param.yaml
|
|
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml b/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
new file mode 100644
|
|
index 0000000000..73ec34ec2d
|
|
--- /dev/null
|
|
+++ b/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
@@ -0,0 +1,13 @@
|
|
+description: Mouse move
|
|
+
|
|
+compatible: "zmk,behavior-mouse-move"
|
|
+
|
|
+include: one_param.yaml
|
|
+
|
|
+properties:
|
|
+ delay-ms:
|
|
+ type: int
|
|
+ time-to-max-speed-ms:
|
|
+ type: int
|
|
+ acceleration-exponent:
|
|
+ type: int
|
|
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml b/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
new file mode 100644
|
|
index 0000000000..5a932bc590
|
|
--- /dev/null
|
|
+++ b/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
@@ -0,0 +1,13 @@
|
|
+description: Mouse scroll
|
|
+
|
|
+compatible: "zmk,behavior-mouse-scroll"
|
|
+
|
|
+include: one_param.yaml
|
|
+
|
|
+properties:
|
|
+ delay-ms:
|
|
+ type: int
|
|
+ time-to-max-speed-ms:
|
|
+ type: int
|
|
+ acceleration-exponent:
|
|
+ type: int
|
|
diff --git a/app/include/dt-bindings/zmk/hid_usage_pages.h b/app/include/dt-bindings/zmk/hid_usage_pages.h
|
|
index 2ccdba5540..7fa54fd88b 100644
|
|
--- a/app/include/dt-bindings/zmk/hid_usage_pages.h
|
|
+++ b/app/include/dt-bindings/zmk/hid_usage_pages.h
|
|
@@ -26,6 +26,7 @@
|
|
#define HID_USAGE_GDV (0x06) // Generic Device Controls
|
|
#define HID_USAGE_KEY (0x07) // Keyboard/Keypad
|
|
#define HID_USAGE_LED (0x08) // LED
|
|
+#define HID_USAGE_BUTTON (0x09) // Button
|
|
#define HID_USAGE_TELEPHONY (0x0B) // Telephony Device
|
|
#define HID_USAGE_CONSUMER (0x0C) // Consumer
|
|
#define HID_USAGE_DIGITIZERS (0x0D) // Digitizers
|
|
diff --git a/app/include/dt-bindings/zmk/mouse.h b/app/include/dt-bindings/zmk/mouse.h
|
|
new file mode 100644
|
|
index 0000000000..cf0415c9b2
|
|
--- /dev/null
|
|
+++ b/app/include/dt-bindings/zmk/mouse.h
|
|
@@ -0,0 +1,55 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+#pragma once
|
|
+
|
|
+/* Mouse press behavior */
|
|
+/* Left click */
|
|
+#define MB1 (0x01)
|
|
+#define LCLK (MB1)
|
|
+
|
|
+/* Right click */
|
|
+#define MB2 (0x02)
|
|
+#define RCLK (MB2)
|
|
+
|
|
+/* Middle click */
|
|
+#define MB3 (0x04)
|
|
+#define MCLK (MB3)
|
|
+
|
|
+#define MB4 (0x08)
|
|
+
|
|
+#define MB5 (0x10)
|
|
+
|
|
+#define MB6 (0x20)
|
|
+
|
|
+#define MB7 (0x40)
|
|
+
|
|
+#define MB8 (0x80)
|
|
+
|
|
+/* Mouse move behavior */
|
|
+#define MOVE_VERT(vert) ((vert)&0xFFFF)
|
|
+#define MOVE_VERT_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
|
|
+#define MOVE_HOR(hor) (((hor)&0xFFFF) << 16)
|
|
+#define MOVE_HOR_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)
|
|
+
|
|
+#define MOVE(hor, vert) (MOVE_HOR(hor) + MOVE_VERT(vert))
|
|
+
|
|
+#define MOVE_UP MOVE_VERT(-600)
|
|
+#define MOVE_DOWN MOVE_VERT(600)
|
|
+#define MOVE_LEFT MOVE_HOR(-600)
|
|
+#define MOVE_RIGHT MOVE_HOR(600)
|
|
+
|
|
+/* Mouse scroll behavior */
|
|
+#define SCROLL_VERT(vert) ((vert)&0xFFFF)
|
|
+#define SCROLL_VERT_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
|
|
+#define SCROLL_HOR(hor) (((hor)&0xFFFF) << 16)
|
|
+#define SCROLL_HOR_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)
|
|
+
|
|
+#define SCROLL(hor, vert) (SCROLL_HOR(hor) + SCROLL_VERT(vert))
|
|
+
|
|
+#define SCROLL_UP SCROLL_VERT(10)
|
|
+#define SCROLL_DOWN SCROLL_VERT(-10)
|
|
+#define SCROLL_LEFT SCROLL_HOR(-10)
|
|
+#define SCROLL_RIGHT SCROLL_HOR(10)
|
|
diff --git a/app/include/zmk/endpoints.h b/app/include/zmk/endpoints.h
|
|
index c8860533e1..450d7ea370 100644
|
|
--- a/app/include/zmk/endpoints.h
|
|
+++ b/app/include/zmk/endpoints.h
|
|
@@ -13,3 +13,4 @@ int zmk_endpoints_toggle();
|
|
enum zmk_endpoint zmk_endpoints_selected();
|
|
|
|
int zmk_endpoints_send_report(uint16_t usage_page);
|
|
+int zmk_endpoints_send_mouse_report();
|
|
diff --git a/app/include/zmk/events/mouse_button_state_changed.h b/app/include/zmk/events/mouse_button_state_changed.h
|
|
new file mode 100644
|
|
index 0000000000..7ec4d2087c
|
|
--- /dev/null
|
|
+++ b/app/include/zmk/events/mouse_button_state_changed.h
|
|
@@ -0,0 +1,27 @@
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <zephyr.h>
|
|
+#include <zmk/hid.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+struct zmk_mouse_button_state_changed {
|
|
+ zmk_mouse_button_t buttons;
|
|
+ bool state;
|
|
+ int64_t timestamp;
|
|
+};
|
|
+
|
|
+ZMK_EVENT_DECLARE(zmk_mouse_button_state_changed);
|
|
+
|
|
+static inline struct zmk_mouse_button_state_changed_event *
|
|
+zmk_mouse_button_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
|
+ return new_zmk_mouse_button_state_changed((struct zmk_mouse_button_state_changed){
|
|
+ .buttons = HID_USAGE_ID(encoded), .state = pressed, .timestamp = timestamp});
|
|
+}
|
|
diff --git a/app/include/zmk/events/mouse_move_state_changed.h b/app/include/zmk/events/mouse_move_state_changed.h
|
|
new file mode 100644
|
|
index 0000000000..8866f81d4e
|
|
--- /dev/null
|
|
+++ b/app/include/zmk/events/mouse_move_state_changed.h
|
|
@@ -0,0 +1,33 @@
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <zephyr.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+struct zmk_mouse_move_state_changed {
|
|
+ struct vector2d max_speed;
|
|
+ struct mouse_config config;
|
|
+ bool state;
|
|
+ int64_t timestamp;
|
|
+};
|
|
+
|
|
+ZMK_EVENT_DECLARE(zmk_mouse_move_state_changed);
|
|
+
|
|
+static inline struct zmk_mouse_move_state_changed_event *
|
|
+zmk_mouse_move_state_changed_from_encoded(uint32_t encoded, struct mouse_config config,
|
|
+ bool pressed, int64_t timestamp) {
|
|
+ struct vector2d max_speed = (struct vector2d){
|
|
+ .x = MOVE_HOR_DECODE(encoded),
|
|
+ .y = MOVE_VERT_DECODE(encoded),
|
|
+ };
|
|
+
|
|
+ return new_zmk_mouse_move_state_changed((struct zmk_mouse_move_state_changed){
|
|
+ .max_speed = max_speed, .config = config, .state = pressed, .timestamp = timestamp});
|
|
+}
|
|
diff --git a/app/include/zmk/events/mouse_scroll_state_changed.h b/app/include/zmk/events/mouse_scroll_state_changed.h
|
|
new file mode 100644
|
|
index 0000000000..fa60e8a742
|
|
--- /dev/null
|
|
+++ b/app/include/zmk/events/mouse_scroll_state_changed.h
|
|
@@ -0,0 +1,34 @@
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <zephyr.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/mouse.h>
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+
|
|
+struct zmk_mouse_scroll_state_changed {
|
|
+ struct vector2d max_speed;
|
|
+ struct mouse_config config;
|
|
+ bool state;
|
|
+ int64_t timestamp;
|
|
+};
|
|
+
|
|
+ZMK_EVENT_DECLARE(zmk_mouse_scroll_state_changed);
|
|
+
|
|
+static inline struct zmk_mouse_scroll_state_changed_event *
|
|
+zmk_mouse_scroll_state_changed_from_encoded(uint32_t encoded, struct mouse_config config,
|
|
+ bool pressed, int64_t timestamp) {
|
|
+ struct vector2d max_speed = (struct vector2d){
|
|
+ .x = SCROLL_HOR_DECODE(encoded),
|
|
+ .y = SCROLL_VERT_DECODE(encoded),
|
|
+ };
|
|
+
|
|
+ return new_zmk_mouse_scroll_state_changed((struct zmk_mouse_scroll_state_changed){
|
|
+ .max_speed = max_speed, .config = config, .state = pressed, .timestamp = timestamp});
|
|
+}
|
|
diff --git a/app/include/zmk/events/mouse_tick.h b/app/include/zmk/events/mouse_tick.h
|
|
new file mode 100644
|
|
index 0000000000..c75b9b4f86
|
|
--- /dev/null
|
|
+++ b/app/include/zmk/events/mouse_tick.h
|
|
@@ -0,0 +1,39 @@
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+#include <zephyr.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+struct zmk_mouse_tick {
|
|
+ struct vector2d max_move;
|
|
+ struct vector2d max_scroll;
|
|
+ struct mouse_config move_config;
|
|
+ struct mouse_config scroll_config;
|
|
+ int64_t *start_time;
|
|
+ int64_t timestamp;
|
|
+};
|
|
+
|
|
+ZMK_EVENT_DECLARE(zmk_mouse_tick);
|
|
+
|
|
+static inline struct zmk_mouse_tick_event *zmk_mouse_tick(struct vector2d max_move,
|
|
+ struct vector2d max_scroll,
|
|
+ struct mouse_config move_config,
|
|
+ struct mouse_config scroll_config,
|
|
+ int64_t *movement_start) {
|
|
+ return new_zmk_mouse_tick((struct zmk_mouse_tick){
|
|
+ .max_move = max_move,
|
|
+ .max_scroll = max_scroll,
|
|
+ .move_config = move_config,
|
|
+ .scroll_config = scroll_config,
|
|
+ .start_time = movement_start,
|
|
+ .timestamp = k_uptime_get(),
|
|
+ });
|
|
+}
|
|
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
|
|
index 902b76d15a..aa26cd3a54 100644
|
|
--- a/app/include/zmk/hid.h
|
|
+++ b/app/include/zmk/hid.h
|
|
@@ -10,11 +10,10 @@
|
|
#include <usb/class/usb_hid.h>
|
|
|
|
#include <zmk/keys.h>
|
|
+#include <zmk/mouse.h>
|
|
#include <dt-bindings/zmk/hid_usage.h>
|
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
|
|
-#define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL
|
|
-
|
|
#define COLLECTION_REPORT 0x03
|
|
|
|
static const uint8_t zmk_hid_report_desc[] = {
|
|
@@ -89,6 +88,116 @@ static const uint8_t zmk_hid_report_desc[] = {
|
|
/* INPUT (Data,Ary,Abs) */
|
|
HID_INPUT(0x00),
|
|
HID_END_COLLECTION,
|
|
+
|
|
+ /* USAGE_PAGE (Generic Desktop) */
|
|
+ HID_GI_USAGE_PAGE,
|
|
+ HID_USAGE_GD,
|
|
+ /* USAGE (Mouse) */
|
|
+ HID_LI_USAGE,
|
|
+ HID_USAGE_GD_MOUSE,
|
|
+ /* COLLECTION (Application) */
|
|
+ HID_MI_COLLECTION,
|
|
+ COLLECTION_APPLICATION,
|
|
+ /* REPORT ID (4) */
|
|
+ HID_GI_REPORT_ID,
|
|
+ 0x04,
|
|
+ /* USAGE (Pointer) */
|
|
+ HID_LI_USAGE,
|
|
+ HID_USAGE_GD_POINTER,
|
|
+ /* COLLECTION (Physical) */
|
|
+ HID_MI_COLLECTION,
|
|
+ COLLECTION_PHYSICAL,
|
|
+ /* USAGE_PAGE (Button) */
|
|
+ HID_GI_USAGE_PAGE,
|
|
+ HID_USAGE_BUTTON,
|
|
+ /* USAGE_MINIMUM (0x1) (button 1?) */
|
|
+ HID_LI_USAGE_MIN(1),
|
|
+ 0x1,
|
|
+ /* USAGE_MAXIMUM (0x10) (button 5? Buttons up to 8 still work) */
|
|
+ HID_LI_USAGE_MAX(1),
|
|
+ 0x10,
|
|
+ /* LOGICAL_MINIMUM (0) */
|
|
+ HID_GI_LOGICAL_MIN(1),
|
|
+ 0x00,
|
|
+ /* LOGICAL_MAXIMUM (1) */
|
|
+ HID_GI_LOGICAL_MAX(1),
|
|
+ 0x01,
|
|
+ /* REPORT_SIZE (1) */
|
|
+ HID_GI_REPORT_SIZE,
|
|
+ 0x01,
|
|
+ /* REPORT_COUNT (16) */
|
|
+ HID_GI_REPORT_COUNT,
|
|
+ 0x10,
|
|
+ /* INPUT (Data,Var,Abs) */
|
|
+ HID_MI_INPUT,
|
|
+ 0x02,
|
|
+ /* USAGE_PAGE (Generic Desktop) */
|
|
+ HID_GI_USAGE_PAGE,
|
|
+ HID_USAGE_GD,
|
|
+ /* LOGICAL_MINIMUM (-32767) */
|
|
+ HID_GI_LOGICAL_MIN(2),
|
|
+ 0x01,
|
|
+ 0x80,
|
|
+ /* LOGICAL_MAXIMUM (32767) */
|
|
+ HID_GI_LOGICAL_MAX(2),
|
|
+ 0xFF,
|
|
+ 0x7F,
|
|
+ /* REPORT_SIZE (16) */
|
|
+ HID_GI_REPORT_SIZE,
|
|
+ 0x10,
|
|
+ /* REPORT_COUNT (2) */
|
|
+ HID_GI_REPORT_COUNT,
|
|
+ 0x02,
|
|
+ /* USAGE (X) */ // Vertical scroll
|
|
+ HID_LI_USAGE,
|
|
+ HID_USAGE_GD_X,
|
|
+ /* USAGE (Y) */
|
|
+ HID_LI_USAGE,
|
|
+ HID_USAGE_GD_Y,
|
|
+ /* Input (Data,Var,Rel) */
|
|
+ HID_MI_INPUT,
|
|
+ 0x06,
|
|
+ /* LOGICAL_MINIMUM (-127) */
|
|
+ HID_GI_LOGICAL_MIN(1),
|
|
+ 0x81,
|
|
+ /* LOGICAL_MAXIMUM (127) */
|
|
+ HID_GI_LOGICAL_MAX(1),
|
|
+ 0x7F,
|
|
+ /* REPORT_SIZE (8) */
|
|
+ HID_GI_REPORT_SIZE,
|
|
+ 0x08,
|
|
+ /* REPORT_COUNT (1) */
|
|
+ HID_GI_REPORT_COUNT,
|
|
+ 0x01,
|
|
+ /* USAGE (Wheel) */
|
|
+ HID_LI_USAGE,
|
|
+ HID_USAGE_GD_WHEEL,
|
|
+ /* Input (Data,Var,Rel) */
|
|
+ HID_MI_INPUT,
|
|
+ 0x06,
|
|
+ /* USAGE_PAGE (Consumer) */ // Horizontal scroll
|
|
+ HID_GI_USAGE_PAGE,
|
|
+ HID_USAGE_CONSUMER,
|
|
+ /* USAGE (AC Pan) */
|
|
+ 0x0A,
|
|
+ 0x38,
|
|
+ 0x02,
|
|
+ /* LOGICAL_MINIMUM (-127) */
|
|
+ HID_GI_LOGICAL_MIN(1),
|
|
+ 0x81,
|
|
+ /* LOGICAL_MAXIMUM (127) */
|
|
+ HID_GI_LOGICAL_MAX(1),
|
|
+ 0x7F,
|
|
+ /* REPORT_COUNT (1) */
|
|
+ HID_GI_REPORT_COUNT,
|
|
+ 0x01,
|
|
+ /* Input (Data,Var,Rel) */
|
|
+ HID_MI_INPUT,
|
|
+ 0x06,
|
|
+ /* END COLLECTION */
|
|
+ HID_MI_COLLECTION_END,
|
|
+ /* END COLLECTION */
|
|
+ HID_MI_COLLECTION_END,
|
|
};
|
|
|
|
// struct zmk_hid_boot_report
|
|
@@ -126,6 +235,19 @@ struct zmk_hid_consumer_report {
|
|
struct zmk_hid_consumer_report_body body;
|
|
} __packed;
|
|
|
|
+struct zmk_hid_mouse_report_body {
|
|
+ zmk_mouse_button_flags_t buttons;
|
|
+ int16_t x;
|
|
+ int16_t y;
|
|
+ int8_t scroll_y;
|
|
+ int8_t scroll_x;
|
|
+} __packed;
|
|
+
|
|
+struct zmk_hid_mouse_report {
|
|
+ uint8_t report_id;
|
|
+ struct zmk_hid_mouse_report_body body;
|
|
+} __packed;
|
|
+
|
|
zmk_mod_flags_t zmk_hid_get_explicit_mods();
|
|
int zmk_hid_register_mod(zmk_mod_t modifier);
|
|
int zmk_hid_unregister_mod(zmk_mod_t modifier);
|
|
@@ -150,5 +272,16 @@ int zmk_hid_press(uint32_t usage);
|
|
int zmk_hid_release(uint32_t usage);
|
|
bool zmk_hid_is_pressed(uint32_t usage);
|
|
|
|
+int zmk_hid_mouse_button_press(zmk_mouse_button_t button);
|
|
+int zmk_hid_mouse_button_release(zmk_mouse_button_t button);
|
|
+int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons);
|
|
+int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons);
|
|
+void zmk_hid_mouse_movement_set(int16_t x, int16_t y);
|
|
+void zmk_hid_mouse_scroll_set(int8_t x, int8_t y);
|
|
+void zmk_hid_mouse_movement_update(int16_t x, int16_t y);
|
|
+void zmk_hid_mouse_scroll_update(int8_t x, int8_t y);
|
|
+void zmk_hid_mouse_clear();
|
|
+
|
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
|
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
|
+struct zmk_hid_mouse_report *zmk_hid_get_mouse_report();
|
|
diff --git a/app/include/zmk/hog.h b/app/include/zmk/hog.h
|
|
index 7523fb661a..9debc3ff31 100644
|
|
--- a/app/include/zmk/hog.h
|
|
+++ b/app/include/zmk/hog.h
|
|
@@ -13,3 +13,4 @@ int zmk_hog_init();
|
|
|
|
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *body);
|
|
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *body);
|
|
+int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *body);
|
|
diff --git a/app/include/zmk/mouse.h b/app/include/zmk/mouse.h
|
|
new file mode 100644
|
|
index 0000000000..f8f857441e
|
|
--- /dev/null
|
|
+++ b/app/include/zmk/mouse.h
|
|
@@ -0,0 +1,30 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include <zephyr.h>
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+
|
|
+typedef uint16_t zmk_mouse_button_flags_t;
|
|
+typedef uint16_t zmk_mouse_button_t;
|
|
+
|
|
+struct mouse_config {
|
|
+ int delay_ms;
|
|
+ int time_to_max_speed_ms;
|
|
+ // acceleration exponent 0: uniform speed
|
|
+ // acceleration exponent 1: uniform acceleration
|
|
+ // acceleration exponent 2: uniform jerk
|
|
+ int acceleration_exponent;
|
|
+};
|
|
+
|
|
+struct vector2d {
|
|
+ float x;
|
|
+ float y;
|
|
+};
|
|
+
|
|
+struct k_work_q *zmk_mouse_work_q();
|
|
+int zmk_mouse_init();
|
|
\ No newline at end of file
|
|
diff --git a/app/src/behaviors/behavior_mouse_key_press.c b/app/src/behaviors/behavior_mouse_key_press.c
|
|
new file mode 100644
|
|
index 0000000000..e5f2709cbf
|
|
--- /dev/null
|
|
+++ b/app/src/behaviors/behavior_mouse_key_press.c
|
|
@@ -0,0 +1,48 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#define DT_DRV_COMPAT zmk_behavior_mouse_key_press
|
|
+
|
|
+#include <device.h>
|
|
+#include <drivers/behavior.h>
|
|
+#include <logging/log.h>
|
|
+
|
|
+#include <zmk/behavior.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/events/mouse_button_state_changed.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
|
+
|
|
+static int behavior_mouse_key_press_init(const struct device *dev) { return 0; };
|
|
+
|
|
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+
|
|
+ return ZMK_EVENT_RAISE(
|
|
+ zmk_mouse_button_state_changed_from_encoded(binding->param1, true, event.timestamp));
|
|
+}
|
|
+
|
|
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+ return ZMK_EVENT_RAISE(
|
|
+ zmk_mouse_button_state_changed_from_encoded(binding->param1, false, event.timestamp));
|
|
+}
|
|
+
|
|
+static const struct behavior_driver_api behavior_mouse_key_press_driver_api = {
|
|
+ .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
|
+
|
|
+#define KP_INST(n) \
|
|
+ DEVICE_DT_INST_DEFINE(n, behavior_mouse_key_press_init, device_pm_control_nop, NULL, NULL, \
|
|
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
|
+ &behavior_mouse_key_press_driver_api);
|
|
+
|
|
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
+
|
|
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
\ No newline at end of file
|
|
diff --git a/app/src/behaviors/behavior_mouse_move.c b/app/src/behaviors/behavior_mouse_move.c
|
|
new file mode 100644
|
|
index 0000000000..5977a039d1
|
|
--- /dev/null
|
|
+++ b/app/src/behaviors/behavior_mouse_move.c
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#define DT_DRV_COMPAT zmk_behavior_mouse_move
|
|
+
|
|
+#include <device.h>
|
|
+#include <drivers/behavior.h>
|
|
+#include <logging/log.h>
|
|
+
|
|
+#include <zmk/behavior.h>
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/events/mouse_move_state_changed.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
|
+
|
|
+static int behavior_mouse_move_init(const struct device *dev) { return 0; };
|
|
+
|
|
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+ const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
+ const struct mouse_config *config = dev->config;
|
|
+ return ZMK_EVENT_RAISE(
|
|
+ zmk_mouse_move_state_changed_from_encoded(binding->param1, *config, true, event.timestamp));
|
|
+}
|
|
+
|
|
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+ const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
+ const struct mouse_config *config = dev->config;
|
|
+ return ZMK_EVENT_RAISE(zmk_mouse_move_state_changed_from_encoded(binding->param1, *config,
|
|
+ false, event.timestamp));
|
|
+}
|
|
+
|
|
+static const struct behavior_driver_api behavior_mouse_move_driver_api = {
|
|
+ .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
|
+
|
|
+#define KP_INST(n) \
|
|
+ static struct mouse_config behavior_mouse_move_config_##n = { \
|
|
+ .delay_ms = DT_INST_PROP(n, delay_ms), \
|
|
+ .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
|
|
+ .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \
|
|
+ }; \
|
|
+ DEVICE_DT_INST_DEFINE(n, behavior_mouse_move_init, device_pm_control_nop, NULL, \
|
|
+ &behavior_mouse_move_config_##n, APPLICATION, \
|
|
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_move_driver_api);
|
|
+
|
|
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
+
|
|
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
diff --git a/app/src/behaviors/behavior_mouse_scroll.c b/app/src/behaviors/behavior_mouse_scroll.c
|
|
new file mode 100644
|
|
index 0000000000..6416235265
|
|
--- /dev/null
|
|
+++ b/app/src/behaviors/behavior_mouse_scroll.c
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#define DT_DRV_COMPAT zmk_behavior_mouse_scroll
|
|
+
|
|
+#include <device.h>
|
|
+#include <drivers/behavior.h>
|
|
+#include <logging/log.h>
|
|
+
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/events/mouse_scroll_state_changed.h>
|
|
+#include <zmk/behavior.h>
|
|
+#include <zmk/hid.h>
|
|
+#include <zmk/endpoints.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
|
+
|
|
+static int behavior_mouse_scroll_init(const struct device *dev) { return 0; };
|
|
+
|
|
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+ const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
+ const struct mouse_config *config = dev->config;
|
|
+ return ZMK_EVENT_RAISE(zmk_mouse_scroll_state_changed_from_encoded(binding->param1, *config,
|
|
+ true, event.timestamp));
|
|
+}
|
|
+
|
|
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
|
+ struct zmk_behavior_binding_event event) {
|
|
+ LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
+ const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
+ const struct mouse_config *config = dev->config;
|
|
+ return ZMK_EVENT_RAISE(zmk_mouse_scroll_state_changed_from_encoded(binding->param1, *config,
|
|
+ false, event.timestamp));
|
|
+}
|
|
+
|
|
+static const struct behavior_driver_api behavior_mouse_scroll_driver_api = {
|
|
+ .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
|
+
|
|
+#define KP_INST(n) \
|
|
+ static struct mouse_config behavior_mouse_scroll_config_##n = { \
|
|
+ .delay_ms = DT_INST_PROP(n, delay_ms), \
|
|
+ .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
|
|
+ .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \
|
|
+ }; \
|
|
+ DEVICE_DT_INST_DEFINE(n, behavior_mouse_scroll_init, device_pm_control_nop, NULL, \
|
|
+ &behavior_mouse_scroll_config_##n, APPLICATION, \
|
|
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_scroll_driver_api);
|
|
+
|
|
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
+
|
|
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
|
|
index 3376001060..0728fff3bd 100644
|
|
--- a/app/src/endpoints.c
|
|
+++ b/app/src/endpoints.c
|
|
@@ -144,6 +144,40 @@ int zmk_endpoints_send_report(uint16_t usage_page) {
|
|
}
|
|
}
|
|
|
|
+int zmk_endpoints_send_mouse_report() {
|
|
+ struct zmk_hid_mouse_report *mouse_report = zmk_hid_get_mouse_report();
|
|
+
|
|
+ switch (current_endpoint) {
|
|
+#if IS_ENABLED(CONFIG_ZMK_USB)
|
|
+ case ZMK_ENDPOINT_USB: {
|
|
+ int err = zmk_usb_hid_send_report((uint8_t *)mouse_report, sizeof(*mouse_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 ZMK_ENDPOINT_BLE: {
|
|
+#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
+ int err = zmk_hog_send_mouse_report_direct(&mouse_report->body);
|
|
+#else
|
|
+ int err = zmk_hog_send_mouse_report(&mouse_report->body);
|
|
+#endif
|
|
+ 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;
|
|
+ }
|
|
+}
|
|
+
|
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
|
|
|
static int endpoints_handle_set(const char *name, size_t len, settings_read_cb read_cb,
|
|
@@ -228,6 +262,7 @@ static enum zmk_endpoint get_selected_endpoint() {
|
|
static void disconnect_current_endpoint() {
|
|
zmk_hid_keyboard_clear();
|
|
zmk_hid_consumer_clear();
|
|
+ zmk_hid_mouse_clear();
|
|
|
|
zmk_endpoints_send_report(HID_USAGE_KEY);
|
|
zmk_endpoints_send_report(HID_USAGE_CONSUMER);
|
|
diff --git a/app/src/events/mouse_button_state_changed.c b/app/src/events/mouse_button_state_changed.c
|
|
new file mode 100644
|
|
index 0000000000..e1ede41421
|
|
--- /dev/null
|
|
+++ b/app/src/events/mouse_button_state_changed.c
|
|
@@ -0,0 +1,10 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <kernel.h>
|
|
+#include <zmk/events/mouse_button_state_changed.h>
|
|
+
|
|
+ZMK_EVENT_IMPL(zmk_mouse_button_state_changed);
|
|
diff --git a/app/src/events/mouse_move_state_changed.c b/app/src/events/mouse_move_state_changed.c
|
|
new file mode 100644
|
|
index 0000000000..faf89cb8ab
|
|
--- /dev/null
|
|
+++ b/app/src/events/mouse_move_state_changed.c
|
|
@@ -0,0 +1,10 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <kernel.h>
|
|
+#include <zmk/events/mouse_move_state_changed.h>
|
|
+
|
|
+ZMK_EVENT_IMPL(zmk_mouse_move_state_changed);
|
|
diff --git a/app/src/events/mouse_scroll_state_changed.c b/app/src/events/mouse_scroll_state_changed.c
|
|
new file mode 100644
|
|
index 0000000000..4b4170fe00
|
|
--- /dev/null
|
|
+++ b/app/src/events/mouse_scroll_state_changed.c
|
|
@@ -0,0 +1,10 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <kernel.h>
|
|
+#include <zmk/events/mouse_scroll_state_changed.h>
|
|
+
|
|
+ZMK_EVENT_IMPL(zmk_mouse_scroll_state_changed);
|
|
diff --git a/app/src/events/mouse_tick.c b/app/src/events/mouse_tick.c
|
|
new file mode 100644
|
|
index 0000000000..0930b9fb90
|
|
--- /dev/null
|
|
+++ b/app/src/events/mouse_tick.c
|
|
@@ -0,0 +1,10 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <kernel.h>
|
|
+#include <zmk/events/mouse_tick.h>
|
|
+
|
|
+ZMK_EVENT_IMPL(zmk_mouse_tick);
|
|
diff --git a/app/src/hid.c b/app/src/hid.c
|
|
index c3462ddeb7..9e7451b7f4 100644
|
|
--- a/app/src/hid.c
|
|
+++ b/app/src/hid.c
|
|
@@ -16,6 +16,9 @@ static struct zmk_hid_keyboard_report keyboard_report = {
|
|
|
|
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};
|
|
|
|
+static struct zmk_hid_mouse_report mouse_report = {
|
|
+ .report_id = 4, .body = {.buttons = 0, .x = 0, .y = 0, .scroll_x = 0, .scroll_y = 0}};
|
|
+
|
|
// Keep track of how often a modifier was pressed.
|
|
// Only release the modifier if the count is 0.
|
|
static int explicit_modifier_counts[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
@@ -246,6 +249,85 @@ bool zmk_hid_is_pressed(uint32_t usage) {
|
|
return false;
|
|
}
|
|
|
|
+// Keep track of how often a button was pressed.
|
|
+// Only release the button if the count is 0.
|
|
+static int explicit_button_counts[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
+static zmk_mod_flags_t explicit_buttons = 0;
|
|
+
|
|
+#define SET_MOUSE_BUTTONS(btns) \
|
|
+ { \
|
|
+ mouse_report.body.buttons = btns; \
|
|
+ LOG_DBG("Mouse buttons set to 0x%02X", mouse_report.body.buttons); \
|
|
+ }
|
|
+
|
|
+int zmk_hid_mouse_button_press(zmk_mouse_button_t button) {
|
|
+ explicit_button_counts[button]++;
|
|
+ LOG_DBG("Button %d count %d", button, explicit_button_counts[button]);
|
|
+ WRITE_BIT(explicit_buttons, button, true);
|
|
+ SET_MOUSE_BUTTONS(explicit_buttons);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int zmk_hid_mouse_button_release(zmk_mouse_button_t button) {
|
|
+ if (explicit_button_counts[button] <= 0) {
|
|
+ LOG_ERR("Tried to release button %d too often", button);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ explicit_button_counts[button]--;
|
|
+ LOG_DBG("Button %d count: %d", button, explicit_button_counts[button]);
|
|
+ if (explicit_button_counts[button] == 0) {
|
|
+ LOG_DBG("Button %d released", button);
|
|
+ WRITE_BIT(explicit_buttons, button, false);
|
|
+ }
|
|
+ SET_MOUSE_BUTTONS(explicit_buttons);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons) {
|
|
+ for (zmk_mod_t i = 0; i < 16; i++) {
|
|
+ if (buttons & (1 << i)) {
|
|
+ zmk_hid_mouse_button_press(i);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons) {
|
|
+ for (zmk_mod_t i = 0; i < 16; i++) {
|
|
+ if (buttons & (1 << i)) {
|
|
+ zmk_hid_mouse_button_release(i);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void zmk_hid_mouse_movement_set(int16_t x, int16_t y) {
|
|
+ mouse_report.body.x = x;
|
|
+ mouse_report.body.y = y;
|
|
+ LOG_DBG("Mouse movement set to 0x%02X 0x%02X ", mouse_report.body.x, mouse_report.body.y);
|
|
+}
|
|
+
|
|
+void zmk_hid_mouse_movement_update(int16_t x, int16_t y) {
|
|
+ mouse_report.body.x += x;
|
|
+ mouse_report.body.y += y;
|
|
+ LOG_DBG("Mouse movement updated to 0x%02X 0x%02X ", mouse_report.body.x, mouse_report.body.y);
|
|
+}
|
|
+
|
|
+void zmk_hid_mouse_scroll_set(int8_t x, int8_t y) {
|
|
+ mouse_report.body.scroll_x = x;
|
|
+ mouse_report.body.scroll_y = y;
|
|
+ LOG_DBG("Mouse scroll set to 0x%02X 0x%02X ", mouse_report.body.scroll_x,
|
|
+ mouse_report.body.scroll_y);
|
|
+}
|
|
+
|
|
+void zmk_hid_mouse_scroll_update(int8_t x, int8_t y) {
|
|
+ mouse_report.body.scroll_x += x;
|
|
+ mouse_report.body.scroll_y += y;
|
|
+ LOG_DBG("Mouse scroll updated to 0x%02X 0x%02X ", mouse_report.body.scroll_x,
|
|
+ mouse_report.body.scroll_y);
|
|
+}
|
|
+void zmk_hid_mouse_clear() { memset(&mouse_report.body, 0, sizeof(mouse_report.body)); }
|
|
+
|
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
|
return &keyboard_report;
|
|
}
|
|
@@ -253,3 +335,7 @@ struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
|
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
|
|
return &consumer_report;
|
|
}
|
|
+
|
|
+struct zmk_hid_mouse_report *zmk_hid_get_mouse_report() {
|
|
+ return &mouse_report;
|
|
+}
|
|
diff --git a/app/src/hid_listener.c b/app/src/hid_listener.c
|
|
index e233b0b8ed..8cde3a4323 100644
|
|
--- a/app/src/hid_listener.c
|
|
+++ b/app/src/hid_listener.c
|
|
@@ -11,7 +11,6 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
|
|
#include <zmk/event_manager.h>
|
|
#include <zmk/events/keycode_state_changed.h>
|
|
-#include <zmk/events/modifiers_state_changed.h>
|
|
#include <zmk/hid.h>
|
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
#include <zmk/endpoints.h>
|
|
@@ -71,13 +70,14 @@ static int hid_listener_keycode_released(const struct zmk_keycode_state_changed
|
|
}
|
|
|
|
int hid_listener(const zmk_event_t *eh) {
|
|
- const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
|
- if (ev) {
|
|
- if (ev->state) {
|
|
- hid_listener_keycode_pressed(ev);
|
|
+ const struct zmk_keycode_state_changed *kc_ev = as_zmk_keycode_state_changed(eh);
|
|
+ if (kc_ev) {
|
|
+ if (kc_ev->state) {
|
|
+ hid_listener_keycode_pressed(kc_ev);
|
|
} else {
|
|
- hid_listener_keycode_released(ev);
|
|
+ hid_listener_keycode_released(kc_ev);
|
|
}
|
|
+ return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/app/src/hog.c b/app/src/hog.c
|
|
index 3dd3e874a5..f915d27a91 100644
|
|
--- a/app/src/hog.c
|
|
+++ b/app/src/hog.c
|
|
@@ -56,6 +56,11 @@ static struct hids_report consumer_input = {
|
|
.type = HIDS_INPUT,
|
|
};
|
|
|
|
+static struct hids_report mouse_input = {
|
|
+ .id = 0x04,
|
|
+ .type = HIDS_INPUT,
|
|
+};
|
|
+
|
|
static bool host_requests_notification = false;
|
|
static uint8_t ctrl_point;
|
|
// static uint8_t proto_mode;
|
|
@@ -93,6 +98,13 @@ static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
|
sizeof(struct zmk_hid_consumer_report_body));
|
|
}
|
|
|
|
+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));
|
|
+}
|
|
+
|
|
// static ssize_t write_proto_mode(struct bt_conn *conn,
|
|
// const struct bt_gatt_attr *attr,
|
|
// const void *buf, uint16_t len, uint16_t offset,
|
|
@@ -139,6 +151,13 @@ BT_GATT_SERVICE_DEFINE(
|
|
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, &consumer_input),
|
|
+
|
|
+ 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),
|
|
+
|
|
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
|
|
BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point));
|
|
|
|
@@ -261,6 +280,76 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
|
|
return 0;
|
|
};
|
|
|
|
+K_MSGQ_DEFINE(zmk_hog_mouse_msgq, sizeof(struct zmk_hid_mouse_report_body),
|
|
+ CONFIG_ZMK_BLE_MOUSE_REPORT_QUEUE_SIZE, 4);
|
|
+
|
|
+void send_mouse_report_callback(struct k_work *work) {
|
|
+ struct zmk_hid_mouse_report_body report;
|
|
+ while (k_msgq_get(&zmk_hog_mouse_msgq, &report, K_NO_WAIT) == 0) {
|
|
+ struct bt_conn *conn = destination_connection();
|
|
+ if (conn == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ struct bt_gatt_notify_params notify_params = {
|
|
+ .attr = &hog_svc.attrs[13],
|
|
+ .data = &report,
|
|
+ .len = sizeof(report),
|
|
+ };
|
|
+
|
|
+ int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
|
+ if (err) {
|
|
+ LOG_DBG("Error notifying %d", err);
|
|
+ }
|
|
+
|
|
+ bt_conn_unref(conn);
|
|
+ }
|
|
+};
|
|
+
|
|
+K_WORK_DEFINE(hog_mouse_work, send_mouse_report_callback);
|
|
+
|
|
+int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) {
|
|
+ int err = k_msgq_put(&zmk_hog_mouse_msgq, report, K_NO_WAIT);
|
|
+ if (err) {
|
|
+ switch (err) {
|
|
+ case -EAGAIN: {
|
|
+ LOG_WRN("Mouse message queue full, dropping report");
|
|
+ return err;
|
|
+ }
|
|
+ default:
|
|
+ LOG_WRN("Failed to queue mouse report to send (%d)", err);
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ k_work_submit_to_queue(&hog_work_q, &hog_mouse_work);
|
|
+
|
|
+ return 0;
|
|
+};
|
|
+
|
|
+int zmk_hog_send_mouse_report_direct(struct zmk_hid_mouse_report_body *report) {
|
|
+ struct bt_conn *conn = destination_connection();
|
|
+ if (conn == NULL) {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ struct bt_gatt_notify_params notify_params = {
|
|
+ .attr = &hog_svc.attrs[13],
|
|
+ .data = report,
|
|
+ .len = sizeof(*report),
|
|
+ };
|
|
+
|
|
+ int err = bt_gatt_notify_cb(conn, ¬ify_params);
|
|
+ if (err) {
|
|
+ LOG_DBG("Error notifying %d", err);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ bt_conn_unref(conn);
|
|
+
|
|
+ return 0;
|
|
+};
|
|
+
|
|
int zmk_hog_init(const struct device *_arg) {
|
|
static const struct k_work_queue_config queue_config = {.name = "HID Over GATT Send Work"};
|
|
k_work_queue_start(&hog_work_q, hog_q_stack, K_THREAD_STACK_SIZEOF(hog_q_stack),
|
|
diff --git a/app/src/main.c b/app/src/main.c
|
|
index ae604a7b9e..d3b3e578b3 100644
|
|
--- a/app/src/main.c
|
|
+++ b/app/src/main.c
|
|
@@ -17,6 +17,10 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
#include <zmk/display.h>
|
|
#include <drivers/ext_power.h>
|
|
|
|
+#ifdef CONFIG_ZMK_MOUSE
|
|
+#include <zmk/mouse.h>
|
|
+#endif /* CONFIG_ZMK_MOUSE */
|
|
+
|
|
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
|
|
|
|
void main(void) {
|
|
@@ -29,4 +33,8 @@ void main(void) {
|
|
#ifdef CONFIG_ZMK_DISPLAY
|
|
zmk_display_init();
|
|
#endif /* CONFIG_ZMK_DISPLAY */
|
|
+
|
|
+#ifdef CONFIG_ZMK_MOUSE
|
|
+ zmk_mouse_init();
|
|
+#endif /* CONFIG_ZMK_MOUSE */
|
|
}
|
|
diff --git a/app/src/mouse/Kconfig b/app/src/mouse/Kconfig
|
|
new file mode 100644
|
|
index 0000000000..1161b86b42
|
|
--- /dev/null
|
|
+++ b/app/src/mouse/Kconfig
|
|
@@ -0,0 +1,38 @@
|
|
+# Copyright (c) 2021 The ZMK Contributors
|
|
+# SPDX-License-Identifier: MIT
|
|
+
|
|
+menuconfig ZMK_MOUSE
|
|
+ bool "Enable ZMK mouse emulation"
|
|
+ default n
|
|
+
|
|
+config ZMK_MOUSE_TICK_DURATION
|
|
+ int "Mouse tick duration in ms"
|
|
+ default 8
|
|
+
|
|
+if ZMK_MOUSE
|
|
+
|
|
+choice ZMK_MOUSE_WORK_QUEUE
|
|
+ prompt "Work queue selection for mouse events"
|
|
+ default ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
+
|
|
+config ZMK_MOUSE_WORK_QUEUE_SYSTEM
|
|
+ bool "Use default system work queue for mouse events"
|
|
+
|
|
+config ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
+ bool "Use dedicated work queue for mouse events"
|
|
+
|
|
+endchoice
|
|
+
|
|
+if ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
+
|
|
+config ZMK_MOUSE_DEDICATED_THREAD_STACK_SIZE
|
|
+ int "Stack size for dedicated mouse thread/queue"
|
|
+ default 2048
|
|
+
|
|
+config ZMK_MOUSE_DEDICATED_THREAD_PRIORITY
|
|
+ int "Thread priority for dedicated mouse thread/queue"
|
|
+ default 3
|
|
+
|
|
+endif # ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
+
|
|
+endif
|
|
diff --git a/app/src/mouse/key_listener.c b/app/src/mouse/key_listener.c
|
|
new file mode 100644
|
|
index 0000000000..713d032352
|
|
--- /dev/null
|
|
+++ b/app/src/mouse/key_listener.c
|
|
@@ -0,0 +1,160 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <drivers/behavior.h>
|
|
+#include <logging/log.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/events/mouse_button_state_changed.h>
|
|
+#include <zmk/events/mouse_move_state_changed.h>
|
|
+#include <zmk/events/mouse_scroll_state_changed.h>
|
|
+#include <zmk/events/mouse_tick.h>
|
|
+#include <zmk/hid.h>
|
|
+#include <zmk/endpoints.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+static struct vector2d move_speed = {0};
|
|
+static struct vector2d scroll_speed = {0};
|
|
+static struct mouse_config move_config = (struct mouse_config){0};
|
|
+static struct mouse_config scroll_config = (struct mouse_config){0};
|
|
+static int64_t start_time = 0;
|
|
+
|
|
+bool equals(const struct mouse_config *one, const struct mouse_config *other) {
|
|
+ return one->delay_ms == other->delay_ms &&
|
|
+ one->time_to_max_speed_ms == other->time_to_max_speed_ms &&
|
|
+ one->acceleration_exponent == other->acceleration_exponent;
|
|
+}
|
|
+
|
|
+static void clear_mouse_state(struct k_work *work) {
|
|
+ move_speed = (struct vector2d){0};
|
|
+ scroll_speed = (struct vector2d){0};
|
|
+ start_time = 0;
|
|
+ zmk_hid_mouse_movement_set(0, 0);
|
|
+ zmk_hid_mouse_scroll_set(0, 0);
|
|
+ LOG_DBG("Clearing state");
|
|
+}
|
|
+
|
|
+K_WORK_DEFINE(mouse_clear, &clear_mouse_state);
|
|
+
|
|
+void mouse_clear_cb(struct k_timer *dummy) {
|
|
+ k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_clear);
|
|
+}
|
|
+
|
|
+static void mouse_tick_timer_handler(struct k_work *work) {
|
|
+ zmk_hid_mouse_movement_set(0, 0);
|
|
+ zmk_hid_mouse_scroll_set(0, 0);
|
|
+ LOG_DBG("Raising mouse tick event");
|
|
+ ZMK_EVENT_RAISE(
|
|
+ zmk_mouse_tick(move_speed, scroll_speed, move_config, scroll_config, &start_time));
|
|
+ zmk_endpoints_send_mouse_report();
|
|
+}
|
|
+
|
|
+K_WORK_DEFINE(mouse_tick, &mouse_tick_timer_handler);
|
|
+
|
|
+void mouse_timer_cb(struct k_timer *dummy) {
|
|
+ LOG_DBG("Submitting mouse work to queue");
|
|
+ k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_tick);
|
|
+}
|
|
+
|
|
+K_TIMER_DEFINE(mouse_timer, mouse_timer_cb, mouse_clear_cb);
|
|
+
|
|
+static int mouse_timer_ref_count = 0;
|
|
+
|
|
+void mouse_timer_ref() {
|
|
+ if (mouse_timer_ref_count == 0) {
|
|
+ start_time = k_uptime_get();
|
|
+ k_timer_start(&mouse_timer, K_NO_WAIT, K_MSEC(CONFIG_ZMK_MOUSE_TICK_DURATION));
|
|
+ }
|
|
+ mouse_timer_ref_count += 1;
|
|
+}
|
|
+
|
|
+void mouse_timer_unref() {
|
|
+ if (mouse_timer_ref_count > 0) {
|
|
+ mouse_timer_ref_count--;
|
|
+ }
|
|
+ if (mouse_timer_ref_count == 0) {
|
|
+ k_timer_stop(&mouse_timer);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void listener_mouse_move_pressed(const struct zmk_mouse_move_state_changed *ev) {
|
|
+ move_speed.x += ev->max_speed.x;
|
|
+ move_speed.y += ev->max_speed.y;
|
|
+ mouse_timer_ref();
|
|
+}
|
|
+
|
|
+static void listener_mouse_move_released(const struct zmk_mouse_move_state_changed *ev) {
|
|
+ move_speed.x -= ev->max_speed.x;
|
|
+ move_speed.y -= ev->max_speed.y;
|
|
+ mouse_timer_unref();
|
|
+}
|
|
+
|
|
+static void listener_mouse_scroll_pressed(const struct zmk_mouse_scroll_state_changed *ev) {
|
|
+ scroll_speed.x += ev->max_speed.x;
|
|
+ scroll_speed.y += ev->max_speed.y;
|
|
+ mouse_timer_ref();
|
|
+}
|
|
+
|
|
+static void listener_mouse_scroll_released(const struct zmk_mouse_scroll_state_changed *ev) {
|
|
+ scroll_speed.x -= ev->max_speed.x;
|
|
+ scroll_speed.y -= ev->max_speed.y;
|
|
+ mouse_timer_unref();
|
|
+}
|
|
+
|
|
+static void listener_mouse_button_pressed(const struct zmk_mouse_button_state_changed *ev) {
|
|
+ LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
+ zmk_hid_mouse_buttons_press(ev->buttons);
|
|
+ zmk_endpoints_send_mouse_report();
|
|
+}
|
|
+
|
|
+static void listener_mouse_button_released(const struct zmk_mouse_button_state_changed *ev) {
|
|
+ LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
+ zmk_hid_mouse_buttons_release(ev->buttons);
|
|
+ zmk_endpoints_send_mouse_report();
|
|
+}
|
|
+
|
|
+int mouse_listener(const zmk_event_t *eh) {
|
|
+ const struct zmk_mouse_move_state_changed *mmv_ev = as_zmk_mouse_move_state_changed(eh);
|
|
+ if (mmv_ev) {
|
|
+ if (!equals(&move_config, &(mmv_ev->config)))
|
|
+ move_config = mmv_ev->config;
|
|
+
|
|
+ if (mmv_ev->state) {
|
|
+ listener_mouse_move_pressed(mmv_ev);
|
|
+ } else {
|
|
+ listener_mouse_move_released(mmv_ev);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ const struct zmk_mouse_scroll_state_changed *msc_ev = as_zmk_mouse_scroll_state_changed(eh);
|
|
+ if (msc_ev) {
|
|
+ if (!equals(&scroll_config, &(msc_ev->config)))
|
|
+ scroll_config = msc_ev->config;
|
|
+ if (msc_ev->state) {
|
|
+ listener_mouse_scroll_pressed(msc_ev);
|
|
+ } else {
|
|
+ listener_mouse_scroll_released(msc_ev);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ const struct zmk_mouse_button_state_changed *mbt_ev = as_zmk_mouse_button_state_changed(eh);
|
|
+ if (mbt_ev) {
|
|
+ if (mbt_ev->state) {
|
|
+ listener_mouse_button_pressed(mbt_ev);
|
|
+ } else {
|
|
+ listener_mouse_button_released(mbt_ev);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ZMK_LISTENER(mouse_listener, mouse_listener);
|
|
+ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_button_state_changed);
|
|
+ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_move_state_changed);
|
|
+ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_scroll_state_changed);
|
|
diff --git a/app/src/mouse/main.c b/app/src/mouse/main.c
|
|
new file mode 100644
|
|
index 0000000000..49208a76ef
|
|
--- /dev/null
|
|
+++ b/app/src/mouse/main.c
|
|
@@ -0,0 +1,30 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <kernel.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
+K_THREAD_STACK_DEFINE(mouse_work_stack_area, CONFIG_ZMK_MOUSE_DEDICATED_THREAD_STACK_SIZE);
|
|
+static struct k_work_q mouse_work_q;
|
|
+#endif
|
|
+
|
|
+struct k_work_q *zmk_mouse_work_q() {
|
|
+#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
+ return &mouse_work_q;
|
|
+#else
|
|
+ return &k_sys_work_q;
|
|
+#endif
|
|
+}
|
|
+
|
|
+int zmk_mouse_init() {
|
|
+#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
+ k_work_q_start(&mouse_work_q, mouse_work_stack_area,
|
|
+ K_THREAD_STACK_SIZEOF(mouse_work_stack_area),
|
|
+ CONFIG_ZMK_MOUSE_DEDICATED_THREAD_PRIORITY);
|
|
+#endif
|
|
+ return 0;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/app/src/mouse/tick_listener.c b/app/src/mouse/tick_listener.c
|
|
new file mode 100644
|
|
index 0000000000..9c76bd5d2a
|
|
--- /dev/null
|
|
+++ b/app/src/mouse/tick_listener.c
|
|
@@ -0,0 +1,102 @@
|
|
+/*
|
|
+ * Copyright (c) 2020 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <logging/log.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#include <zmk/event_manager.h>
|
|
+#include <zmk/events/mouse_tick.h>
|
|
+#include <zmk/endpoints.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+#include <sys/util.h> // CLAMP
|
|
+
|
|
+#if CONFIG_MINIMAL_LIBC
|
|
+static float powf(float base, float exponent) {
|
|
+ // poor man's power implementation rounds the exponent down to the nearest integer.
|
|
+ float power = 1.0f;
|
|
+ for (; exponent >= 1.0f; exponent--) {
|
|
+ power = power * base;
|
|
+ }
|
|
+ return power;
|
|
+}
|
|
+#else
|
|
+#include <math.h>
|
|
+#endif
|
|
+
|
|
+struct vector2d move_remainder = {0};
|
|
+struct vector2d scroll_remainder = {0};
|
|
+
|
|
+static int64_t ms_since_start(int64_t start, int64_t now, int64_t delay) {
|
|
+ int64_t move_duration = now - (start + delay);
|
|
+ // start can be in the future if there's a delay
|
|
+ if (move_duration < 0) {
|
|
+ move_duration = 0;
|
|
+ }
|
|
+ return move_duration;
|
|
+}
|
|
+
|
|
+static float speed(const struct mouse_config *config, float max_speed, int64_t duration_ms) {
|
|
+ // Calculate the speed based on MouseKeysAccel
|
|
+ // See https://en.wikipedia.org/wiki/Mouse_keys
|
|
+ if (duration_ms > config->time_to_max_speed_ms || config->time_to_max_speed_ms == 0 ||
|
|
+ config->acceleration_exponent == 0) {
|
|
+ return max_speed;
|
|
+ }
|
|
+ float time_fraction = (float)duration_ms / config->time_to_max_speed_ms;
|
|
+ return max_speed * powf(time_fraction, config->acceleration_exponent);
|
|
+}
|
|
+
|
|
+static void track_remainder(float *move, float *remainder) {
|
|
+ float new_move = *move + *remainder;
|
|
+ *remainder = new_move - (int)new_move;
|
|
+ *move = (int)new_move;
|
|
+}
|
|
+
|
|
+static struct vector2d update_movement(struct vector2d *remainder,
|
|
+ const struct mouse_config *config, struct vector2d max_speed,
|
|
+ int64_t now, int64_t *start_time) {
|
|
+ struct vector2d move = {0};
|
|
+ if (max_speed.x == 0 && max_speed.y == 0) {
|
|
+ *remainder = (struct vector2d){0};
|
|
+ return move;
|
|
+ }
|
|
+
|
|
+ int64_t move_duration = ms_since_start(*start_time, now, config->delay_ms);
|
|
+ move = (struct vector2d){
|
|
+ .x = speed(config, max_speed.x, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000,
|
|
+ .y = speed(config, max_speed.y, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000,
|
|
+ };
|
|
+
|
|
+ track_remainder(&(move.x), &(remainder->x));
|
|
+ track_remainder(&(move.y), &(remainder->y));
|
|
+
|
|
+ return move;
|
|
+}
|
|
+
|
|
+static void mouse_tick_handler(const struct zmk_mouse_tick *tick) {
|
|
+ struct vector2d move = update_movement(&move_remainder, &(tick->move_config), tick->max_move,
|
|
+ tick->timestamp, tick->start_time);
|
|
+ zmk_hid_mouse_movement_update((int16_t)CLAMP(move.x, INT16_MIN, INT16_MAX),
|
|
+ (int16_t)CLAMP(move.y, INT16_MIN, INT16_MAX));
|
|
+ struct vector2d scroll = update_movement(&scroll_remainder, &(tick->scroll_config),
|
|
+ tick->max_scroll, tick->timestamp, tick->start_time);
|
|
+ zmk_hid_mouse_scroll_update((int8_t)CLAMP(scroll.x, INT8_MIN, INT8_MAX),
|
|
+ (int8_t)CLAMP(scroll.y, INT8_MIN, INT8_MAX));
|
|
+}
|
|
+
|
|
+int zmk_mouse_tick_listener(const zmk_event_t *eh) {
|
|
+ const struct zmk_mouse_tick *tick = as_zmk_mouse_tick(eh);
|
|
+ if (tick) {
|
|
+ mouse_tick_handler(tick);
|
|
+ return 0;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ZMK_LISTENER(zmk_mouse_tick_listener, zmk_mouse_tick_listener);
|
|
+ZMK_SUBSCRIPTION(zmk_mouse_tick_listener, zmk_mouse_tick);
|
|
\ No newline at end of file
|
|
diff --git a/app/tests/mouse-keys/mmv/events.patterns b/app/tests/mouse-keys/mmv/events.patterns
|
|
new file mode 100644
|
|
index 0000000000..833100f6ac
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mmv/events.patterns
|
|
@@ -0,0 +1 @@
|
|
+s/.*hid_listener_keycode_//p
|
|
\ No newline at end of file
|
|
diff --git a/app/tests/mouse-keys/mmv/keycode_events.snapshot b/app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
new file mode 100644
|
|
index 0000000000..259501ba3d
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
@@ -0,0 +1,2 @@
|
|
+pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
|
+released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
|
diff --git a/app/tests/mouse-keys/mmv/native_posix.keymap b/app/tests/mouse-keys/mmv/native_posix.keymap
|
|
new file mode 100644
|
|
index 0000000000..ecf06601c0
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mmv/native_posix.keymap
|
|
@@ -0,0 +1,26 @@
|
|
+#include <behaviors.dtsi>
|
|
+#include <dt-bindings/zmk/keys.h>
|
|
+#include <dt-bindings/zmk/kscan_mock.h>
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+
|
|
+/ {
|
|
+ keymap {
|
|
+ compatible = "zmk,keymap";
|
|
+ label ="Default keymap";
|
|
+
|
|
+ default_layer {
|
|
+ bindings = <
|
|
+ &mmv MOVE_LEFT &none
|
|
+ &none &none
|
|
+ >;
|
|
+ };
|
|
+ };
|
|
+};
|
|
+
|
|
+
|
|
+&kscan {
|
|
+ events = <
|
|
+ ZMK_MOCK_PRESS(0,0,100)
|
|
+ ZMK_MOCK_RELEASE(0,0,10)
|
|
+ >;
|
|
+};
|
|
\ No newline at end of file
|
|
diff --git a/docs/docs/behaviors/mouse-emulation.md b/docs/docs/behaviors/mouse-emulation.md
|
|
new file mode 100644
|
|
index 0000000000..efe095e7a0
|
|
--- /dev/null
|
|
+++ b/docs/docs/behaviors/mouse-emulation.md
|
|
@@ -0,0 +1,110 @@
|
|
+---
|
|
+title: Mouse Emulation Behaviors
|
|
+sidebar_label: Mouse Emulation
|
|
+---
|
|
+
|
|
+## Summary
|
|
+
|
|
+Mouse emulation behaviors send mouse movements, button presses or scroll actions.
|
|
+
|
|
+Please view [`dt-bindings/zmk/mouse.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/mouse.h) for a comprehensive list of signals.
|
|
+
|
|
+## Configuration options
|
|
+
|
|
+This feature should be enabled via a config option:
|
|
+
|
|
+```
|
|
+CONFIG_ZMK_MOUSE=y
|
|
+```
|
|
+
|
|
+This option enables several others.
|
|
+
|
|
+### Dedicated thread processing
|
|
+
|
|
+`CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED` is enabled by default and separates the processing of mouse signals into a dedicated thread, significantly improving performance.
|
|
+
|
|
+### Tick rate configuration
|
|
+
|
|
+`CONFIG_ZMK_MOUSE_TICK_DURATION` sets the tick rate for mouse polling. It is set to 8 ms. by default.
|
|
+
|
|
+## Keycode Defines
|
|
+
|
|
+To make it easier to encode the HID keycode numeric values, most keymaps include
|
|
+the [`dt-bindings/zmk/mouse.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/mouse.h) header
|
|
+provided by ZMK near the top:
|
|
+
|
|
+```
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+```
|
|
+
|
|
+Doing so allows using a set of defines such as `MOVE_UP`, `MOVE_DOWN`, `LCLK` and `SCROLL_UP` with these behaviors.
|
|
+
|
|
+## Mouse Button Press
|
|
+
|
|
+This behavior can press/release up to 16 mouse buttons.
|
|
+
|
|
+### Behavior Binding
|
|
+
|
|
+- Reference: `&mkp`
|
|
+- Parameter: A `uint16` with each bit referring to a button.
|
|
+
|
|
+Example:
|
|
+
|
|
+```
|
|
+&mkp LCLK
|
|
+```
|
|
+
|
|
+## Mouse Movement
|
|
+
|
|
+This behavior is used to manipulate the cursor.
|
|
+
|
|
+### Behavior Binding
|
|
+
|
|
+- Reference: `&mmv`
|
|
+- Parameter: A `uint32` with the first 16 bits relating to horizontal movement
|
|
+ and the last 16 - to vertical movement.
|
|
+
|
|
+Example:
|
|
+
|
|
+```
|
|
+&mmv MOVE_UP
|
|
+```
|
|
+
|
|
+## Mouse Scrolling
|
|
+
|
|
+This behaviour is used to scroll, both horizontally and vertically.
|
|
+
|
|
+### Behavior Binding
|
|
+
|
|
+- Reference: `&mwh`
|
|
+- Parameter: A `uint16` with the first 8 bits relating to horizontal movement
|
|
+ and the last 8 - to vertical movement.
|
|
+
|
|
+Example:
|
|
+
|
|
+```
|
|
+&mwh SCROLL_UP
|
|
+```
|
|
+
|
|
+## Acceleration
|
|
+
|
|
+Both mouse movement and scrolling have independently configurable acceleration profiles with three parameters: delay before movement, time to max speed and the acceleration exponent.
|
|
+The exponent is usually set to 0 for constant speed, 1 for uniform acceleration or 2 for uniform jerk.
|
|
+
|
|
+These profiles can be configured inside your keymap:
|
|
+
|
|
+```
|
|
+&mmv {
|
|
+ time-to-max-speed-ms = <500>;
|
|
+};
|
|
+
|
|
+&mwh {
|
|
+ acceleration-exponent=<1>;
|
|
+};
|
|
+
|
|
+/ {
|
|
+ keymap {
|
|
+ ...
|
|
+ };
|
|
+};
|
|
+```
|
|
diff --git a/docs/sidebars.js b/docs/sidebars.js
|
|
index 7b445a2901..5e18b05dd0 100644
|
|
--- a/docs/sidebars.js
|
|
+++ b/docs/sidebars.js
|
|
@@ -34,6 +34,7 @@ module.exports = {
|
|
"behaviors/tap-dance",
|
|
"behaviors/caps-word",
|
|
"behaviors/key-repeat",
|
|
+ "behaviors/mouse-emulation",
|
|
"behaviors/reset",
|
|
"behaviors/bluetooth",
|
|
"behaviors/outputs",
|
|
|
|
From f8a0c397e25cb4a4c8c1a2d91da2db0e9401ad73 Mon Sep 17 00:00:00 2001
|
|
From: Jesper Jensen <jesper@jnsn.dev>
|
|
Date: Wed, 17 Aug 2022 23:26:23 +0200
|
|
Subject: [PATCH 2/2] Remove everything not required for buttons
|
|
|
|
I've stripped out everything not strictly required for mouse button HID
|
|
support. This include dropping the worker thread completely, shaving
|
|
down the USB HID descriptor. Flattening the mouse/ source directory
|
|
structure and removing a bunch of event handling.
|
|
|
|
I have kept the mouse event handling separate from the other HID event
|
|
handling since I figured that was a pretty neat split. If that's a bad
|
|
idea, do tell.
|
|
|
|
I've also added a test case for mouse button emulation, since that was
|
|
untested before.
|
|
|
|
The changes have been tested on a corne (split) in usb mode. Bindings on
|
|
both the left and the right side works (with the left side as master).
|
|
---
|
|
app/CMakeLists.txt | 9 +-
|
|
app/Kconfig | 4 +-
|
|
app/dts/behaviors.dtsi | 2 -
|
|
app/dts/behaviors/mouse_move.dtsi | 12 --
|
|
app/dts/behaviors/mouse_scroll.dtsi | 12 --
|
|
.../behaviors/zmk,behavior-mouse-move.yaml | 13 --
|
|
.../behaviors/zmk,behavior-mouse-scroll.yaml | 13 --
|
|
app/include/dt-bindings/zmk/mouse.h | 26 ---
|
|
.../zmk/events/mouse_button_state_changed.h | 2 +-
|
|
.../zmk/events/mouse_move_state_changed.h | 33 ----
|
|
.../zmk/events/mouse_scroll_state_changed.h | 34 ----
|
|
app/include/zmk/events/mouse_tick.h | 39 -----
|
|
app/include/zmk/hid.h | 135 ++-------------
|
|
app/include/zmk/mouse.h | 17 --
|
|
app/src/behaviors/behavior_mouse_move.c | 57 -------
|
|
app/src/behaviors/behavior_mouse_scroll.c | 58 -------
|
|
app/src/endpoints.c | 4 -
|
|
app/src/events/mouse_move_state_changed.c | 10 --
|
|
app/src/events/mouse_scroll_state_changed.c | 10 --
|
|
app/src/events/mouse_tick.c | 10 --
|
|
app/src/hid.c | 28 +--
|
|
app/src/hid_listener.c | 12 +-
|
|
app/src/hog.c | 21 ---
|
|
app/src/main.c | 8 -
|
|
app/src/mouse.c | 43 +++++
|
|
app/src/mouse/Kconfig | 38 -----
|
|
app/src/mouse/key_listener.c | 160 ------------------
|
|
app/src/mouse/main.c | 30 ----
|
|
app/src/mouse/tick_listener.c | 102 -----------
|
|
app/tests/mouse-keys/mkp/events.patterns | 1 +
|
|
.../mouse-keys/mkp/keycode_events.snapshot | 10 ++
|
|
.../{mmv => mkp}/native_posix.keymap | 12 +-
|
|
.../mouse-keys/mkp/native_posix_64.keymap | 28 +++
|
|
app/tests/mouse-keys/mmv/events.patterns | 1 -
|
|
.../mouse-keys/mmv/keycode_events.snapshot | 2 -
|
|
docs/docs/behaviors/mouse-emulation.md | 67 +-------
|
|
36 files changed, 120 insertions(+), 943 deletions(-)
|
|
delete mode 100644 app/dts/behaviors/mouse_move.dtsi
|
|
delete mode 100644 app/dts/behaviors/mouse_scroll.dtsi
|
|
delete mode 100644 app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
delete mode 100644 app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
delete mode 100644 app/include/zmk/events/mouse_move_state_changed.h
|
|
delete mode 100644 app/include/zmk/events/mouse_scroll_state_changed.h
|
|
delete mode 100644 app/include/zmk/events/mouse_tick.h
|
|
delete mode 100644 app/src/behaviors/behavior_mouse_move.c
|
|
delete mode 100644 app/src/behaviors/behavior_mouse_scroll.c
|
|
delete mode 100644 app/src/events/mouse_move_state_changed.c
|
|
delete mode 100644 app/src/events/mouse_scroll_state_changed.c
|
|
delete mode 100644 app/src/events/mouse_tick.c
|
|
create mode 100644 app/src/mouse.c
|
|
delete mode 100644 app/src/mouse/Kconfig
|
|
delete mode 100644 app/src/mouse/key_listener.c
|
|
delete mode 100644 app/src/mouse/main.c
|
|
delete mode 100644 app/src/mouse/tick_listener.c
|
|
create mode 100644 app/tests/mouse-keys/mkp/events.patterns
|
|
create mode 100644 app/tests/mouse-keys/mkp/keycode_events.snapshot
|
|
rename app/tests/mouse-keys/{mmv => mkp}/native_posix.keymap (64%)
|
|
create mode 100644 app/tests/mouse-keys/mkp/native_posix_64.keymap
|
|
delete mode 100644 app/tests/mouse-keys/mmv/events.patterns
|
|
delete mode 100644 app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
|
|
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
|
|
index 351505ad77..cf18f4c029 100644
|
|
--- a/app/CMakeLists.txt
|
|
+++ b/app/CMakeLists.txt
|
|
@@ -24,9 +24,6 @@ target_sources(app PRIVATE src/stdlib.c)
|
|
target_sources(app PRIVATE src/activity.c)
|
|
target_sources(app PRIVATE src/kscan.c)
|
|
target_sources(app PRIVATE src/matrix_transform.c)
|
|
-target_sources(app PRIVATE src/mouse/key_listener.c)
|
|
-target_sources(app PRIVATE src/mouse/main.c)
|
|
-target_sources(app PRIVATE src/mouse/tick_listener.c)
|
|
target_sources(app PRIVATE src/sensors.c)
|
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c)
|
|
target_sources(app PRIVATE src/event_manager.c)
|
|
@@ -35,15 +32,13 @@ target_sources(app PRIVATE src/events/activity_state_changed.c)
|
|
target_sources(app PRIVATE src/events/position_state_changed.c)
|
|
target_sources(app PRIVATE src/events/sensor_event.c)
|
|
target_sources(app PRIVATE src/events/mouse_button_state_changed.c)
|
|
-target_sources(app PRIVATE src/events/mouse_move_state_changed.c)
|
|
-target_sources(app PRIVATE src/events/mouse_tick.c)
|
|
-target_sources(app PRIVATE src/events/mouse_scroll_state_changed.c)
|
|
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
|
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
|
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
|
|
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|
target_sources(app PRIVATE src/hid.c)
|
|
+ target_sources(app PRIVATE src/mouse.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
|
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_KEY_TOGGLE app PRIVATE src/behaviors/behavior_key_toggle.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
|
@@ -61,8 +56,6 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
|
|
target_sources(app PRIVATE src/behaviors/behavior_mouse_key_press.c)
|
|
- target_sources(app PRIVATE src/behaviors/behavior_mouse_move.c)
|
|
- target_sources(app PRIVATE src/behaviors/behavior_mouse_scroll.c)
|
|
target_sources(app PRIVATE src/combo.c)
|
|
target_sources(app PRIVATE src/behavior_queue.c)
|
|
target_sources(app PRIVATE src/conditional_layer.c)
|
|
diff --git a/app/Kconfig b/app/Kconfig
|
|
index 3c59605814..7a422c2b9c 100644
|
|
--- a/app/Kconfig
|
|
+++ b/app/Kconfig
|
|
@@ -291,7 +291,9 @@ endmenu
|
|
|
|
menu "Mouse Options"
|
|
|
|
-rsource "src/mouse/Kconfig"
|
|
+config ZMK_MOUSE
|
|
+ bool "Enable ZMK mouse emulation"
|
|
+ default n
|
|
|
|
#Mouse Options
|
|
endmenu
|
|
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
|
|
index 77eccf912f..23f2fee280 100644
|
|
--- a/app/dts/behaviors.dtsi
|
|
+++ b/app/dts/behaviors.dtsi
|
|
@@ -20,5 +20,3 @@
|
|
#include <behaviors/backlight.dtsi>
|
|
#include <behaviors/macros.dtsi>
|
|
#include <behaviors/mouse_key_press.dtsi>
|
|
-#include <behaviors/mouse_move.dtsi>
|
|
-#include <behaviors/mouse_scroll.dtsi>
|
|
diff --git a/app/dts/behaviors/mouse_move.dtsi b/app/dts/behaviors/mouse_move.dtsi
|
|
deleted file mode 100644
|
|
index d34329c806..0000000000
|
|
--- a/app/dts/behaviors/mouse_move.dtsi
|
|
+++ /dev/null
|
|
@@ -1,12 +0,0 @@
|
|
-/ {
|
|
- behaviors {
|
|
- /omit-if-no-ref/ mmv: behavior_mouse_move {
|
|
- compatible = "zmk,behavior-mouse-move";
|
|
- label = "MOUSE_MOVE";
|
|
- #binding-cells = <1>;
|
|
- delay-ms = <0>;
|
|
- time-to-max-speed-ms = <300>;
|
|
- acceleration-exponent = <1>;
|
|
- };
|
|
- };
|
|
-};
|
|
diff --git a/app/dts/behaviors/mouse_scroll.dtsi b/app/dts/behaviors/mouse_scroll.dtsi
|
|
deleted file mode 100644
|
|
index fb54886dcb..0000000000
|
|
--- a/app/dts/behaviors/mouse_scroll.dtsi
|
|
+++ /dev/null
|
|
@@ -1,12 +0,0 @@
|
|
-/ {
|
|
- behaviors {
|
|
- /omit-if-no-ref/ mwh: msc: behavior_mouse_scroll {
|
|
- compatible = "zmk,behavior-mouse-scroll";
|
|
- label = "MOUSE_SCROLL";
|
|
- #binding-cells = <1>;
|
|
- delay-ms = <0>;
|
|
- time-to-max-speed-ms = <300>;
|
|
- acceleration-exponent = <0>;
|
|
- };
|
|
- };
|
|
-};
|
|
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml b/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
deleted file mode 100644
|
|
index 73ec34ec2d..0000000000
|
|
--- a/app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-description: Mouse move
|
|
-
|
|
-compatible: "zmk,behavior-mouse-move"
|
|
-
|
|
-include: one_param.yaml
|
|
-
|
|
-properties:
|
|
- delay-ms:
|
|
- type: int
|
|
- time-to-max-speed-ms:
|
|
- type: int
|
|
- acceleration-exponent:
|
|
- type: int
|
|
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml b/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
deleted file mode 100644
|
|
index 5a932bc590..0000000000
|
|
--- a/app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
|
|
+++ /dev/null
|
|
@@ -1,13 +0,0 @@
|
|
-description: Mouse scroll
|
|
-
|
|
-compatible: "zmk,behavior-mouse-scroll"
|
|
-
|
|
-include: one_param.yaml
|
|
-
|
|
-properties:
|
|
- delay-ms:
|
|
- type: int
|
|
- time-to-max-speed-ms:
|
|
- type: int
|
|
- acceleration-exponent:
|
|
- type: int
|
|
diff --git a/app/include/dt-bindings/zmk/mouse.h b/app/include/dt-bindings/zmk/mouse.h
|
|
index cf0415c9b2..4bb3064dfc 100644
|
|
--- a/app/include/dt-bindings/zmk/mouse.h
|
|
+++ b/app/include/dt-bindings/zmk/mouse.h
|
|
@@ -27,29 +27,3 @@
|
|
#define MB7 (0x40)
|
|
|
|
#define MB8 (0x80)
|
|
-
|
|
-/* Mouse move behavior */
|
|
-#define MOVE_VERT(vert) ((vert)&0xFFFF)
|
|
-#define MOVE_VERT_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
|
|
-#define MOVE_HOR(hor) (((hor)&0xFFFF) << 16)
|
|
-#define MOVE_HOR_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)
|
|
-
|
|
-#define MOVE(hor, vert) (MOVE_HOR(hor) + MOVE_VERT(vert))
|
|
-
|
|
-#define MOVE_UP MOVE_VERT(-600)
|
|
-#define MOVE_DOWN MOVE_VERT(600)
|
|
-#define MOVE_LEFT MOVE_HOR(-600)
|
|
-#define MOVE_RIGHT MOVE_HOR(600)
|
|
-
|
|
-/* Mouse scroll behavior */
|
|
-#define SCROLL_VERT(vert) ((vert)&0xFFFF)
|
|
-#define SCROLL_VERT_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
|
|
-#define SCROLL_HOR(hor) (((hor)&0xFFFF) << 16)
|
|
-#define SCROLL_HOR_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)
|
|
-
|
|
-#define SCROLL(hor, vert) (SCROLL_HOR(hor) + SCROLL_VERT(vert))
|
|
-
|
|
-#define SCROLL_UP SCROLL_VERT(10)
|
|
-#define SCROLL_DOWN SCROLL_VERT(-10)
|
|
-#define SCROLL_LEFT SCROLL_HOR(-10)
|
|
-#define SCROLL_RIGHT SCROLL_HOR(10)
|
|
diff --git a/app/include/zmk/events/mouse_button_state_changed.h b/app/include/zmk/events/mouse_button_state_changed.h
|
|
index 7ec4d2087c..6c3adae30d 100644
|
|
--- a/app/include/zmk/events/mouse_button_state_changed.h
|
|
+++ b/app/include/zmk/events/mouse_button_state_changed.h
|
|
@@ -23,5 +23,5 @@ ZMK_EVENT_DECLARE(zmk_mouse_button_state_changed);
|
|
static inline struct zmk_mouse_button_state_changed_event *
|
|
zmk_mouse_button_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
|
return new_zmk_mouse_button_state_changed((struct zmk_mouse_button_state_changed){
|
|
- .buttons = HID_USAGE_ID(encoded), .state = pressed, .timestamp = timestamp});
|
|
+ .buttons = ZMK_HID_USAGE_ID(encoded), .state = pressed, .timestamp = timestamp});
|
|
}
|
|
diff --git a/app/include/zmk/events/mouse_move_state_changed.h b/app/include/zmk/events/mouse_move_state_changed.h
|
|
deleted file mode 100644
|
|
index 8866f81d4e..0000000000
|
|
--- a/app/include/zmk/events/mouse_move_state_changed.h
|
|
+++ /dev/null
|
|
@@ -1,33 +0,0 @@
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#pragma once
|
|
-
|
|
-#include <zephyr.h>
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-struct zmk_mouse_move_state_changed {
|
|
- struct vector2d max_speed;
|
|
- struct mouse_config config;
|
|
- bool state;
|
|
- int64_t timestamp;
|
|
-};
|
|
-
|
|
-ZMK_EVENT_DECLARE(zmk_mouse_move_state_changed);
|
|
-
|
|
-static inline struct zmk_mouse_move_state_changed_event *
|
|
-zmk_mouse_move_state_changed_from_encoded(uint32_t encoded, struct mouse_config config,
|
|
- bool pressed, int64_t timestamp) {
|
|
- struct vector2d max_speed = (struct vector2d){
|
|
- .x = MOVE_HOR_DECODE(encoded),
|
|
- .y = MOVE_VERT_DECODE(encoded),
|
|
- };
|
|
-
|
|
- return new_zmk_mouse_move_state_changed((struct zmk_mouse_move_state_changed){
|
|
- .max_speed = max_speed, .config = config, .state = pressed, .timestamp = timestamp});
|
|
-}
|
|
diff --git a/app/include/zmk/events/mouse_scroll_state_changed.h b/app/include/zmk/events/mouse_scroll_state_changed.h
|
|
deleted file mode 100644
|
|
index fa60e8a742..0000000000
|
|
--- a/app/include/zmk/events/mouse_scroll_state_changed.h
|
|
+++ /dev/null
|
|
@@ -1,34 +0,0 @@
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#pragma once
|
|
-
|
|
-#include <zephyr.h>
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/mouse.h>
|
|
-#include <dt-bindings/zmk/mouse.h>
|
|
-
|
|
-struct zmk_mouse_scroll_state_changed {
|
|
- struct vector2d max_speed;
|
|
- struct mouse_config config;
|
|
- bool state;
|
|
- int64_t timestamp;
|
|
-};
|
|
-
|
|
-ZMK_EVENT_DECLARE(zmk_mouse_scroll_state_changed);
|
|
-
|
|
-static inline struct zmk_mouse_scroll_state_changed_event *
|
|
-zmk_mouse_scroll_state_changed_from_encoded(uint32_t encoded, struct mouse_config config,
|
|
- bool pressed, int64_t timestamp) {
|
|
- struct vector2d max_speed = (struct vector2d){
|
|
- .x = SCROLL_HOR_DECODE(encoded),
|
|
- .y = SCROLL_VERT_DECODE(encoded),
|
|
- };
|
|
-
|
|
- return new_zmk_mouse_scroll_state_changed((struct zmk_mouse_scroll_state_changed){
|
|
- .max_speed = max_speed, .config = config, .state = pressed, .timestamp = timestamp});
|
|
-}
|
|
diff --git a/app/include/zmk/events/mouse_tick.h b/app/include/zmk/events/mouse_tick.h
|
|
deleted file mode 100644
|
|
index c75b9b4f86..0000000000
|
|
--- a/app/include/zmk/events/mouse_tick.h
|
|
+++ /dev/null
|
|
@@ -1,39 +0,0 @@
|
|
-
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#pragma once
|
|
-
|
|
-#include <dt-bindings/zmk/mouse.h>
|
|
-#include <zephyr.h>
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-struct zmk_mouse_tick {
|
|
- struct vector2d max_move;
|
|
- struct vector2d max_scroll;
|
|
- struct mouse_config move_config;
|
|
- struct mouse_config scroll_config;
|
|
- int64_t *start_time;
|
|
- int64_t timestamp;
|
|
-};
|
|
-
|
|
-ZMK_EVENT_DECLARE(zmk_mouse_tick);
|
|
-
|
|
-static inline struct zmk_mouse_tick_event *zmk_mouse_tick(struct vector2d max_move,
|
|
- struct vector2d max_scroll,
|
|
- struct mouse_config move_config,
|
|
- struct mouse_config scroll_config,
|
|
- int64_t *movement_start) {
|
|
- return new_zmk_mouse_tick((struct zmk_mouse_tick){
|
|
- .max_move = max_move,
|
|
- .max_scroll = max_scroll,
|
|
- .move_config = move_config,
|
|
- .scroll_config = scroll_config,
|
|
- .start_time = movement_start,
|
|
- .timestamp = k_uptime_get(),
|
|
- });
|
|
-}
|
|
diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h
|
|
index aa26cd3a54..f30db315d9 100644
|
|
--- a/app/include/zmk/hid.h
|
|
+++ b/app/include/zmk/hid.h
|
|
@@ -14,6 +14,8 @@
|
|
#include <dt-bindings/zmk/hid_usage.h>
|
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
|
|
+#define ZMK_HID_KEYBOARD_NKRO_MAX_USAGE HID_USAGE_KEY_KEYPAD_EQUAL
|
|
+
|
|
#define COLLECTION_REPORT 0x03
|
|
|
|
static const uint8_t zmk_hid_report_desc[] = {
|
|
@@ -89,115 +91,22 @@ static const uint8_t zmk_hid_report_desc[] = {
|
|
HID_INPUT(0x00),
|
|
HID_END_COLLECTION,
|
|
|
|
- /* USAGE_PAGE (Generic Desktop) */
|
|
- HID_GI_USAGE_PAGE,
|
|
- HID_USAGE_GD,
|
|
- /* USAGE (Mouse) */
|
|
- HID_LI_USAGE,
|
|
- HID_USAGE_GD_MOUSE,
|
|
- /* COLLECTION (Application) */
|
|
- HID_MI_COLLECTION,
|
|
- COLLECTION_APPLICATION,
|
|
- /* REPORT ID (4) */
|
|
- HID_GI_REPORT_ID,
|
|
- 0x04,
|
|
- /* USAGE (Pointer) */
|
|
- HID_LI_USAGE,
|
|
- HID_USAGE_GD_POINTER,
|
|
- /* COLLECTION (Physical) */
|
|
- HID_MI_COLLECTION,
|
|
- COLLECTION_PHYSICAL,
|
|
- /* USAGE_PAGE (Button) */
|
|
- HID_GI_USAGE_PAGE,
|
|
- HID_USAGE_BUTTON,
|
|
- /* USAGE_MINIMUM (0x1) (button 1?) */
|
|
- HID_LI_USAGE_MIN(1),
|
|
- 0x1,
|
|
- /* USAGE_MAXIMUM (0x10) (button 5? Buttons up to 8 still work) */
|
|
- HID_LI_USAGE_MAX(1),
|
|
- 0x10,
|
|
- /* LOGICAL_MINIMUM (0) */
|
|
- HID_GI_LOGICAL_MIN(1),
|
|
- 0x00,
|
|
- /* LOGICAL_MAXIMUM (1) */
|
|
- HID_GI_LOGICAL_MAX(1),
|
|
- 0x01,
|
|
- /* REPORT_SIZE (1) */
|
|
- HID_GI_REPORT_SIZE,
|
|
- 0x01,
|
|
- /* REPORT_COUNT (16) */
|
|
- HID_GI_REPORT_COUNT,
|
|
- 0x10,
|
|
- /* INPUT (Data,Var,Abs) */
|
|
- HID_MI_INPUT,
|
|
- 0x02,
|
|
- /* USAGE_PAGE (Generic Desktop) */
|
|
- HID_GI_USAGE_PAGE,
|
|
- HID_USAGE_GD,
|
|
- /* LOGICAL_MINIMUM (-32767) */
|
|
- HID_GI_LOGICAL_MIN(2),
|
|
- 0x01,
|
|
- 0x80,
|
|
- /* LOGICAL_MAXIMUM (32767) */
|
|
- HID_GI_LOGICAL_MAX(2),
|
|
- 0xFF,
|
|
- 0x7F,
|
|
- /* REPORT_SIZE (16) */
|
|
- HID_GI_REPORT_SIZE,
|
|
- 0x10,
|
|
- /* REPORT_COUNT (2) */
|
|
- HID_GI_REPORT_COUNT,
|
|
- 0x02,
|
|
- /* USAGE (X) */ // Vertical scroll
|
|
- HID_LI_USAGE,
|
|
- HID_USAGE_GD_X,
|
|
- /* USAGE (Y) */
|
|
- HID_LI_USAGE,
|
|
- HID_USAGE_GD_Y,
|
|
- /* Input (Data,Var,Rel) */
|
|
- HID_MI_INPUT,
|
|
- 0x06,
|
|
- /* LOGICAL_MINIMUM (-127) */
|
|
- HID_GI_LOGICAL_MIN(1),
|
|
- 0x81,
|
|
- /* LOGICAL_MAXIMUM (127) */
|
|
- HID_GI_LOGICAL_MAX(1),
|
|
- 0x7F,
|
|
- /* REPORT_SIZE (8) */
|
|
- HID_GI_REPORT_SIZE,
|
|
- 0x08,
|
|
- /* REPORT_COUNT (1) */
|
|
- HID_GI_REPORT_COUNT,
|
|
- 0x01,
|
|
- /* USAGE (Wheel) */
|
|
- HID_LI_USAGE,
|
|
- HID_USAGE_GD_WHEEL,
|
|
- /* Input (Data,Var,Rel) */
|
|
- HID_MI_INPUT,
|
|
- 0x06,
|
|
- /* USAGE_PAGE (Consumer) */ // Horizontal scroll
|
|
- HID_GI_USAGE_PAGE,
|
|
- HID_USAGE_CONSUMER,
|
|
- /* USAGE (AC Pan) */
|
|
- 0x0A,
|
|
- 0x38,
|
|
- 0x02,
|
|
- /* LOGICAL_MINIMUM (-127) */
|
|
- HID_GI_LOGICAL_MIN(1),
|
|
- 0x81,
|
|
- /* LOGICAL_MAXIMUM (127) */
|
|
- HID_GI_LOGICAL_MAX(1),
|
|
- 0x7F,
|
|
- /* REPORT_COUNT (1) */
|
|
- HID_GI_REPORT_COUNT,
|
|
- 0x01,
|
|
- /* Input (Data,Var,Rel) */
|
|
- HID_MI_INPUT,
|
|
- 0x06,
|
|
- /* END COLLECTION */
|
|
- HID_MI_COLLECTION_END,
|
|
- /* END COLLECTION */
|
|
- HID_MI_COLLECTION_END,
|
|
+ HID_USAGE_PAGE(HID_USAGE_GD),
|
|
+ HID_USAGE(HID_USAGE_GD_MOUSE),
|
|
+ HID_COLLECTION(HID_COLLECTION_APPLICATION),
|
|
+ HID_REPORT_ID(0x04),
|
|
+ HID_USAGE(HID_USAGE_GD_POINTER),
|
|
+ HID_COLLECTION(HID_COLLECTION_PHYSICAL),
|
|
+ HID_USAGE_PAGE(HID_USAGE_BUTTON),
|
|
+ HID_USAGE_MIN8(0x1),
|
|
+ HID_USAGE_MAX8(0x10),
|
|
+ HID_LOGICAL_MIN8(0x00),
|
|
+ HID_LOGICAL_MAX8(0x01),
|
|
+ HID_REPORT_SIZE(0x01),
|
|
+ HID_REPORT_COUNT(0x10),
|
|
+ HID_INPUT(0x02),
|
|
+ HID_END_COLLECTION,
|
|
+ HID_END_COLLECTION,
|
|
};
|
|
|
|
// struct zmk_hid_boot_report
|
|
@@ -237,10 +146,6 @@ struct zmk_hid_consumer_report {
|
|
|
|
struct zmk_hid_mouse_report_body {
|
|
zmk_mouse_button_flags_t buttons;
|
|
- int16_t x;
|
|
- int16_t y;
|
|
- int8_t scroll_y;
|
|
- int8_t scroll_x;
|
|
} __packed;
|
|
|
|
struct zmk_hid_mouse_report {
|
|
@@ -276,10 +181,6 @@ int zmk_hid_mouse_button_press(zmk_mouse_button_t button);
|
|
int zmk_hid_mouse_button_release(zmk_mouse_button_t button);
|
|
int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons);
|
|
int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons);
|
|
-void zmk_hid_mouse_movement_set(int16_t x, int16_t y);
|
|
-void zmk_hid_mouse_scroll_set(int8_t x, int8_t y);
|
|
-void zmk_hid_mouse_movement_update(int16_t x, int16_t y);
|
|
-void zmk_hid_mouse_scroll_update(int8_t x, int8_t y);
|
|
void zmk_hid_mouse_clear();
|
|
|
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
|
diff --git a/app/include/zmk/mouse.h b/app/include/zmk/mouse.h
|
|
index f8f857441e..e749ac5d62 100644
|
|
--- a/app/include/zmk/mouse.h
|
|
+++ b/app/include/zmk/mouse.h
|
|
@@ -11,20 +11,3 @@
|
|
|
|
typedef uint16_t zmk_mouse_button_flags_t;
|
|
typedef uint16_t zmk_mouse_button_t;
|
|
-
|
|
-struct mouse_config {
|
|
- int delay_ms;
|
|
- int time_to_max_speed_ms;
|
|
- // acceleration exponent 0: uniform speed
|
|
- // acceleration exponent 1: uniform acceleration
|
|
- // acceleration exponent 2: uniform jerk
|
|
- int acceleration_exponent;
|
|
-};
|
|
-
|
|
-struct vector2d {
|
|
- float x;
|
|
- float y;
|
|
-};
|
|
-
|
|
-struct k_work_q *zmk_mouse_work_q();
|
|
-int zmk_mouse_init();
|
|
\ No newline at end of file
|
|
diff --git a/app/src/behaviors/behavior_mouse_move.c b/app/src/behaviors/behavior_mouse_move.c
|
|
deleted file mode 100644
|
|
index 5977a039d1..0000000000
|
|
--- a/app/src/behaviors/behavior_mouse_move.c
|
|
+++ /dev/null
|
|
@@ -1,57 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2021 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#define DT_DRV_COMPAT zmk_behavior_mouse_move
|
|
-
|
|
-#include <device.h>
|
|
-#include <drivers/behavior.h>
|
|
-#include <logging/log.h>
|
|
-
|
|
-#include <zmk/behavior.h>
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/events/mouse_move_state_changed.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
-
|
|
-#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
|
-
|
|
-static int behavior_mouse_move_init(const struct device *dev) { return 0; };
|
|
-
|
|
-static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|
- struct zmk_behavior_binding_event event) {
|
|
- LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
- const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
- const struct mouse_config *config = dev->config;
|
|
- return ZMK_EVENT_RAISE(
|
|
- zmk_mouse_move_state_changed_from_encoded(binding->param1, *config, true, event.timestamp));
|
|
-}
|
|
-
|
|
-static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
|
- struct zmk_behavior_binding_event event) {
|
|
- LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
- const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
- const struct mouse_config *config = dev->config;
|
|
- return ZMK_EVENT_RAISE(zmk_mouse_move_state_changed_from_encoded(binding->param1, *config,
|
|
- false, event.timestamp));
|
|
-}
|
|
-
|
|
-static const struct behavior_driver_api behavior_mouse_move_driver_api = {
|
|
- .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
|
-
|
|
-#define KP_INST(n) \
|
|
- static struct mouse_config behavior_mouse_move_config_##n = { \
|
|
- .delay_ms = DT_INST_PROP(n, delay_ms), \
|
|
- .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
|
|
- .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \
|
|
- }; \
|
|
- DEVICE_DT_INST_DEFINE(n, behavior_mouse_move_init, device_pm_control_nop, NULL, \
|
|
- &behavior_mouse_move_config_##n, APPLICATION, \
|
|
- CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_move_driver_api);
|
|
-
|
|
-DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
-
|
|
-#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
diff --git a/app/src/behaviors/behavior_mouse_scroll.c b/app/src/behaviors/behavior_mouse_scroll.c
|
|
deleted file mode 100644
|
|
index 6416235265..0000000000
|
|
--- a/app/src/behaviors/behavior_mouse_scroll.c
|
|
+++ /dev/null
|
|
@@ -1,58 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2021 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#define DT_DRV_COMPAT zmk_behavior_mouse_scroll
|
|
-
|
|
-#include <device.h>
|
|
-#include <drivers/behavior.h>
|
|
-#include <logging/log.h>
|
|
-
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/events/mouse_scroll_state_changed.h>
|
|
-#include <zmk/behavior.h>
|
|
-#include <zmk/hid.h>
|
|
-#include <zmk/endpoints.h>
|
|
-
|
|
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
-
|
|
-#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
|
-
|
|
-static int behavior_mouse_scroll_init(const struct device *dev) { return 0; };
|
|
-
|
|
-static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|
- struct zmk_behavior_binding_event event) {
|
|
- LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
- const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
- const struct mouse_config *config = dev->config;
|
|
- return ZMK_EVENT_RAISE(zmk_mouse_scroll_state_changed_from_encoded(binding->param1, *config,
|
|
- true, event.timestamp));
|
|
-}
|
|
-
|
|
-static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
|
- struct zmk_behavior_binding_event event) {
|
|
- LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
|
- const struct device *dev = device_get_binding(binding->behavior_dev);
|
|
- const struct mouse_config *config = dev->config;
|
|
- return ZMK_EVENT_RAISE(zmk_mouse_scroll_state_changed_from_encoded(binding->param1, *config,
|
|
- false, event.timestamp));
|
|
-}
|
|
-
|
|
-static const struct behavior_driver_api behavior_mouse_scroll_driver_api = {
|
|
- .binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
|
-
|
|
-#define KP_INST(n) \
|
|
- static struct mouse_config behavior_mouse_scroll_config_##n = { \
|
|
- .delay_ms = DT_INST_PROP(n, delay_ms), \
|
|
- .time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
|
|
- .acceleration_exponent = DT_INST_PROP(n, acceleration_exponent), \
|
|
- }; \
|
|
- DEVICE_DT_INST_DEFINE(n, behavior_mouse_scroll_init, device_pm_control_nop, NULL, \
|
|
- &behavior_mouse_scroll_config_##n, APPLICATION, \
|
|
- CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mouse_scroll_driver_api);
|
|
-
|
|
-DT_INST_FOREACH_STATUS_OKAY(KP_INST)
|
|
-
|
|
-#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
diff --git a/app/src/endpoints.c b/app/src/endpoints.c
|
|
index 0728fff3bd..6984faa99f 100644
|
|
--- a/app/src/endpoints.c
|
|
+++ b/app/src/endpoints.c
|
|
@@ -160,11 +160,7 @@ int zmk_endpoints_send_mouse_report() {
|
|
|
|
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
|
case ZMK_ENDPOINT_BLE: {
|
|
-#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
- int err = zmk_hog_send_mouse_report_direct(&mouse_report->body);
|
|
-#else
|
|
int err = zmk_hog_send_mouse_report(&mouse_report->body);
|
|
-#endif
|
|
if (err) {
|
|
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
|
}
|
|
diff --git a/app/src/events/mouse_move_state_changed.c b/app/src/events/mouse_move_state_changed.c
|
|
deleted file mode 100644
|
|
index faf89cb8ab..0000000000
|
|
--- a/app/src/events/mouse_move_state_changed.c
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <kernel.h>
|
|
-#include <zmk/events/mouse_move_state_changed.h>
|
|
-
|
|
-ZMK_EVENT_IMPL(zmk_mouse_move_state_changed);
|
|
diff --git a/app/src/events/mouse_scroll_state_changed.c b/app/src/events/mouse_scroll_state_changed.c
|
|
deleted file mode 100644
|
|
index 4b4170fe00..0000000000
|
|
--- a/app/src/events/mouse_scroll_state_changed.c
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <kernel.h>
|
|
-#include <zmk/events/mouse_scroll_state_changed.h>
|
|
-
|
|
-ZMK_EVENT_IMPL(zmk_mouse_scroll_state_changed);
|
|
diff --git a/app/src/events/mouse_tick.c b/app/src/events/mouse_tick.c
|
|
deleted file mode 100644
|
|
index 0930b9fb90..0000000000
|
|
--- a/app/src/events/mouse_tick.c
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <kernel.h>
|
|
-#include <zmk/events/mouse_tick.h>
|
|
-
|
|
-ZMK_EVENT_IMPL(zmk_mouse_tick);
|
|
diff --git a/app/src/hid.c b/app/src/hid.c
|
|
index 9e7451b7f4..acd0a2b248 100644
|
|
--- a/app/src/hid.c
|
|
+++ b/app/src/hid.c
|
|
@@ -17,7 +17,7 @@ static struct zmk_hid_keyboard_report keyboard_report = {
|
|
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};
|
|
|
|
static struct zmk_hid_mouse_report mouse_report = {
|
|
- .report_id = 4, .body = {.buttons = 0, .x = 0, .y = 0, .scroll_x = 0, .scroll_y = 0}};
|
|
+ .report_id = 4, .body = {.buttons = 0}};
|
|
|
|
// Keep track of how often a modifier was pressed.
|
|
// Only release the modifier if the count is 0.
|
|
@@ -300,32 +300,6 @@ int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons) {
|
|
}
|
|
return 0;
|
|
}
|
|
-
|
|
-void zmk_hid_mouse_movement_set(int16_t x, int16_t y) {
|
|
- mouse_report.body.x = x;
|
|
- mouse_report.body.y = y;
|
|
- LOG_DBG("Mouse movement set to 0x%02X 0x%02X ", mouse_report.body.x, mouse_report.body.y);
|
|
-}
|
|
-
|
|
-void zmk_hid_mouse_movement_update(int16_t x, int16_t y) {
|
|
- mouse_report.body.x += x;
|
|
- mouse_report.body.y += y;
|
|
- LOG_DBG("Mouse movement updated to 0x%02X 0x%02X ", mouse_report.body.x, mouse_report.body.y);
|
|
-}
|
|
-
|
|
-void zmk_hid_mouse_scroll_set(int8_t x, int8_t y) {
|
|
- mouse_report.body.scroll_x = x;
|
|
- mouse_report.body.scroll_y = y;
|
|
- LOG_DBG("Mouse scroll set to 0x%02X 0x%02X ", mouse_report.body.scroll_x,
|
|
- mouse_report.body.scroll_y);
|
|
-}
|
|
-
|
|
-void zmk_hid_mouse_scroll_update(int8_t x, int8_t y) {
|
|
- mouse_report.body.scroll_x += x;
|
|
- mouse_report.body.scroll_y += y;
|
|
- LOG_DBG("Mouse scroll updated to 0x%02X 0x%02X ", mouse_report.body.scroll_x,
|
|
- mouse_report.body.scroll_y);
|
|
-}
|
|
void zmk_hid_mouse_clear() { memset(&mouse_report.body, 0, sizeof(mouse_report.body)); }
|
|
|
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
|
diff --git a/app/src/hid_listener.c b/app/src/hid_listener.c
|
|
index 8cde3a4323..e233b0b8ed 100644
|
|
--- a/app/src/hid_listener.c
|
|
+++ b/app/src/hid_listener.c
|
|
@@ -11,6 +11,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
|
|
#include <zmk/event_manager.h>
|
|
#include <zmk/events/keycode_state_changed.h>
|
|
+#include <zmk/events/modifiers_state_changed.h>
|
|
#include <zmk/hid.h>
|
|
#include <dt-bindings/zmk/hid_usage_pages.h>
|
|
#include <zmk/endpoints.h>
|
|
@@ -70,14 +71,13 @@ static int hid_listener_keycode_released(const struct zmk_keycode_state_changed
|
|
}
|
|
|
|
int hid_listener(const zmk_event_t *eh) {
|
|
- const struct zmk_keycode_state_changed *kc_ev = as_zmk_keycode_state_changed(eh);
|
|
- if (kc_ev) {
|
|
- if (kc_ev->state) {
|
|
- hid_listener_keycode_pressed(kc_ev);
|
|
+ const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
|
+ if (ev) {
|
|
+ if (ev->state) {
|
|
+ hid_listener_keycode_pressed(ev);
|
|
} else {
|
|
- hid_listener_keycode_released(kc_ev);
|
|
+ hid_listener_keycode_released(ev);
|
|
}
|
|
- return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/app/src/hog.c b/app/src/hog.c
|
|
index f915d27a91..1733ffa45c 100644
|
|
--- a/app/src/hog.c
|
|
+++ b/app/src/hog.c
|
|
@@ -306,28 +306,7 @@ void send_mouse_report_callback(struct k_work *work) {
|
|
}
|
|
};
|
|
|
|
-K_WORK_DEFINE(hog_mouse_work, send_mouse_report_callback);
|
|
-
|
|
int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) {
|
|
- int err = k_msgq_put(&zmk_hog_mouse_msgq, report, K_NO_WAIT);
|
|
- if (err) {
|
|
- switch (err) {
|
|
- case -EAGAIN: {
|
|
- LOG_WRN("Mouse message queue full, dropping report");
|
|
- return err;
|
|
- }
|
|
- default:
|
|
- LOG_WRN("Failed to queue mouse report to send (%d)", err);
|
|
- return err;
|
|
- }
|
|
- }
|
|
-
|
|
- k_work_submit_to_queue(&hog_work_q, &hog_mouse_work);
|
|
-
|
|
- return 0;
|
|
-};
|
|
-
|
|
-int zmk_hog_send_mouse_report_direct(struct zmk_hid_mouse_report_body *report) {
|
|
struct bt_conn *conn = destination_connection();
|
|
if (conn == NULL) {
|
|
return 1;
|
|
diff --git a/app/src/main.c b/app/src/main.c
|
|
index d3b3e578b3..ae604a7b9e 100644
|
|
--- a/app/src/main.c
|
|
+++ b/app/src/main.c
|
|
@@ -17,10 +17,6 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
#include <zmk/display.h>
|
|
#include <drivers/ext_power.h>
|
|
|
|
-#ifdef CONFIG_ZMK_MOUSE
|
|
-#include <zmk/mouse.h>
|
|
-#endif /* CONFIG_ZMK_MOUSE */
|
|
-
|
|
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
|
|
|
|
void main(void) {
|
|
@@ -33,8 +29,4 @@ void main(void) {
|
|
#ifdef CONFIG_ZMK_DISPLAY
|
|
zmk_display_init();
|
|
#endif /* CONFIG_ZMK_DISPLAY */
|
|
-
|
|
-#ifdef CONFIG_ZMK_MOUSE
|
|
- zmk_mouse_init();
|
|
-#endif /* CONFIG_ZMK_MOUSE */
|
|
}
|
|
diff --git a/app/src/mouse.c b/app/src/mouse.c
|
|
new file mode 100644
|
|
index 0000000000..a02d6dd0e9
|
|
--- /dev/null
|
|
+++ b/app/src/mouse.c
|
|
@@ -0,0 +1,43 @@
|
|
+/*
|
|
+ * Copyright (c) 2021 The ZMK Contributors
|
|
+ *
|
|
+ * SPDX-License-Identifier: MIT
|
|
+ */
|
|
+
|
|
+#include <drivers/behavior.h>
|
|
+#include <logging/log.h>
|
|
+
|
|
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
+
|
|
+#include <zmk/events/mouse_button_state_changed.h>
|
|
+#include <zmk/hid.h>
|
|
+#include <zmk/endpoints.h>
|
|
+#include <zmk/mouse.h>
|
|
+
|
|
+static void listener_mouse_button_pressed(const struct zmk_mouse_button_state_changed *ev) {
|
|
+ LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
+ zmk_hid_mouse_buttons_press(ev->buttons);
|
|
+ zmk_endpoints_send_mouse_report();
|
|
+}
|
|
+
|
|
+static void listener_mouse_button_released(const struct zmk_mouse_button_state_changed *ev) {
|
|
+ LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
+ zmk_hid_mouse_buttons_release(ev->buttons);
|
|
+ zmk_endpoints_send_mouse_report();
|
|
+}
|
|
+
|
|
+int mouse_listener(const zmk_event_t *eh) {
|
|
+ const struct zmk_mouse_button_state_changed *mbt_ev = as_zmk_mouse_button_state_changed(eh);
|
|
+ if (mbt_ev) {
|
|
+ if (mbt_ev->state) {
|
|
+ listener_mouse_button_pressed(mbt_ev);
|
|
+ } else {
|
|
+ listener_mouse_button_released(mbt_ev);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ZMK_LISTENER(mouse_listener, mouse_listener);
|
|
+ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_button_state_changed);
|
|
diff --git a/app/src/mouse/Kconfig b/app/src/mouse/Kconfig
|
|
deleted file mode 100644
|
|
index 1161b86b42..0000000000
|
|
--- a/app/src/mouse/Kconfig
|
|
+++ /dev/null
|
|
@@ -1,38 +0,0 @@
|
|
-# Copyright (c) 2021 The ZMK Contributors
|
|
-# SPDX-License-Identifier: MIT
|
|
-
|
|
-menuconfig ZMK_MOUSE
|
|
- bool "Enable ZMK mouse emulation"
|
|
- default n
|
|
-
|
|
-config ZMK_MOUSE_TICK_DURATION
|
|
- int "Mouse tick duration in ms"
|
|
- default 8
|
|
-
|
|
-if ZMK_MOUSE
|
|
-
|
|
-choice ZMK_MOUSE_WORK_QUEUE
|
|
- prompt "Work queue selection for mouse events"
|
|
- default ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
-
|
|
-config ZMK_MOUSE_WORK_QUEUE_SYSTEM
|
|
- bool "Use default system work queue for mouse events"
|
|
-
|
|
-config ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
- bool "Use dedicated work queue for mouse events"
|
|
-
|
|
-endchoice
|
|
-
|
|
-if ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
-
|
|
-config ZMK_MOUSE_DEDICATED_THREAD_STACK_SIZE
|
|
- int "Stack size for dedicated mouse thread/queue"
|
|
- default 2048
|
|
-
|
|
-config ZMK_MOUSE_DEDICATED_THREAD_PRIORITY
|
|
- int "Thread priority for dedicated mouse thread/queue"
|
|
- default 3
|
|
-
|
|
-endif # ZMK_MOUSE_WORK_QUEUE_DEDICATED
|
|
-
|
|
-endif
|
|
diff --git a/app/src/mouse/key_listener.c b/app/src/mouse/key_listener.c
|
|
deleted file mode 100644
|
|
index 713d032352..0000000000
|
|
--- a/app/src/mouse/key_listener.c
|
|
+++ /dev/null
|
|
@@ -1,160 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2021 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <drivers/behavior.h>
|
|
-#include <logging/log.h>
|
|
-
|
|
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
-
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/events/mouse_button_state_changed.h>
|
|
-#include <zmk/events/mouse_move_state_changed.h>
|
|
-#include <zmk/events/mouse_scroll_state_changed.h>
|
|
-#include <zmk/events/mouse_tick.h>
|
|
-#include <zmk/hid.h>
|
|
-#include <zmk/endpoints.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-static struct vector2d move_speed = {0};
|
|
-static struct vector2d scroll_speed = {0};
|
|
-static struct mouse_config move_config = (struct mouse_config){0};
|
|
-static struct mouse_config scroll_config = (struct mouse_config){0};
|
|
-static int64_t start_time = 0;
|
|
-
|
|
-bool equals(const struct mouse_config *one, const struct mouse_config *other) {
|
|
- return one->delay_ms == other->delay_ms &&
|
|
- one->time_to_max_speed_ms == other->time_to_max_speed_ms &&
|
|
- one->acceleration_exponent == other->acceleration_exponent;
|
|
-}
|
|
-
|
|
-static void clear_mouse_state(struct k_work *work) {
|
|
- move_speed = (struct vector2d){0};
|
|
- scroll_speed = (struct vector2d){0};
|
|
- start_time = 0;
|
|
- zmk_hid_mouse_movement_set(0, 0);
|
|
- zmk_hid_mouse_scroll_set(0, 0);
|
|
- LOG_DBG("Clearing state");
|
|
-}
|
|
-
|
|
-K_WORK_DEFINE(mouse_clear, &clear_mouse_state);
|
|
-
|
|
-void mouse_clear_cb(struct k_timer *dummy) {
|
|
- k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_clear);
|
|
-}
|
|
-
|
|
-static void mouse_tick_timer_handler(struct k_work *work) {
|
|
- zmk_hid_mouse_movement_set(0, 0);
|
|
- zmk_hid_mouse_scroll_set(0, 0);
|
|
- LOG_DBG("Raising mouse tick event");
|
|
- ZMK_EVENT_RAISE(
|
|
- zmk_mouse_tick(move_speed, scroll_speed, move_config, scroll_config, &start_time));
|
|
- zmk_endpoints_send_mouse_report();
|
|
-}
|
|
-
|
|
-K_WORK_DEFINE(mouse_tick, &mouse_tick_timer_handler);
|
|
-
|
|
-void mouse_timer_cb(struct k_timer *dummy) {
|
|
- LOG_DBG("Submitting mouse work to queue");
|
|
- k_work_submit_to_queue(zmk_mouse_work_q(), &mouse_tick);
|
|
-}
|
|
-
|
|
-K_TIMER_DEFINE(mouse_timer, mouse_timer_cb, mouse_clear_cb);
|
|
-
|
|
-static int mouse_timer_ref_count = 0;
|
|
-
|
|
-void mouse_timer_ref() {
|
|
- if (mouse_timer_ref_count == 0) {
|
|
- start_time = k_uptime_get();
|
|
- k_timer_start(&mouse_timer, K_NO_WAIT, K_MSEC(CONFIG_ZMK_MOUSE_TICK_DURATION));
|
|
- }
|
|
- mouse_timer_ref_count += 1;
|
|
-}
|
|
-
|
|
-void mouse_timer_unref() {
|
|
- if (mouse_timer_ref_count > 0) {
|
|
- mouse_timer_ref_count--;
|
|
- }
|
|
- if (mouse_timer_ref_count == 0) {
|
|
- k_timer_stop(&mouse_timer);
|
|
- }
|
|
-}
|
|
-
|
|
-static void listener_mouse_move_pressed(const struct zmk_mouse_move_state_changed *ev) {
|
|
- move_speed.x += ev->max_speed.x;
|
|
- move_speed.y += ev->max_speed.y;
|
|
- mouse_timer_ref();
|
|
-}
|
|
-
|
|
-static void listener_mouse_move_released(const struct zmk_mouse_move_state_changed *ev) {
|
|
- move_speed.x -= ev->max_speed.x;
|
|
- move_speed.y -= ev->max_speed.y;
|
|
- mouse_timer_unref();
|
|
-}
|
|
-
|
|
-static void listener_mouse_scroll_pressed(const struct zmk_mouse_scroll_state_changed *ev) {
|
|
- scroll_speed.x += ev->max_speed.x;
|
|
- scroll_speed.y += ev->max_speed.y;
|
|
- mouse_timer_ref();
|
|
-}
|
|
-
|
|
-static void listener_mouse_scroll_released(const struct zmk_mouse_scroll_state_changed *ev) {
|
|
- scroll_speed.x -= ev->max_speed.x;
|
|
- scroll_speed.y -= ev->max_speed.y;
|
|
- mouse_timer_unref();
|
|
-}
|
|
-
|
|
-static void listener_mouse_button_pressed(const struct zmk_mouse_button_state_changed *ev) {
|
|
- LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
- zmk_hid_mouse_buttons_press(ev->buttons);
|
|
- zmk_endpoints_send_mouse_report();
|
|
-}
|
|
-
|
|
-static void listener_mouse_button_released(const struct zmk_mouse_button_state_changed *ev) {
|
|
- LOG_DBG("buttons: 0x%02X", ev->buttons);
|
|
- zmk_hid_mouse_buttons_release(ev->buttons);
|
|
- zmk_endpoints_send_mouse_report();
|
|
-}
|
|
-
|
|
-int mouse_listener(const zmk_event_t *eh) {
|
|
- const struct zmk_mouse_move_state_changed *mmv_ev = as_zmk_mouse_move_state_changed(eh);
|
|
- if (mmv_ev) {
|
|
- if (!equals(&move_config, &(mmv_ev->config)))
|
|
- move_config = mmv_ev->config;
|
|
-
|
|
- if (mmv_ev->state) {
|
|
- listener_mouse_move_pressed(mmv_ev);
|
|
- } else {
|
|
- listener_mouse_move_released(mmv_ev);
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- const struct zmk_mouse_scroll_state_changed *msc_ev = as_zmk_mouse_scroll_state_changed(eh);
|
|
- if (msc_ev) {
|
|
- if (!equals(&scroll_config, &(msc_ev->config)))
|
|
- scroll_config = msc_ev->config;
|
|
- if (msc_ev->state) {
|
|
- listener_mouse_scroll_pressed(msc_ev);
|
|
- } else {
|
|
- listener_mouse_scroll_released(msc_ev);
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- const struct zmk_mouse_button_state_changed *mbt_ev = as_zmk_mouse_button_state_changed(eh);
|
|
- if (mbt_ev) {
|
|
- if (mbt_ev->state) {
|
|
- listener_mouse_button_pressed(mbt_ev);
|
|
- } else {
|
|
- listener_mouse_button_released(mbt_ev);
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-ZMK_LISTENER(mouse_listener, mouse_listener);
|
|
-ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_button_state_changed);
|
|
-ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_move_state_changed);
|
|
-ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_scroll_state_changed);
|
|
diff --git a/app/src/mouse/main.c b/app/src/mouse/main.c
|
|
deleted file mode 100644
|
|
index 49208a76ef..0000000000
|
|
--- a/app/src/mouse/main.c
|
|
+++ /dev/null
|
|
@@ -1,30 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <kernel.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
-K_THREAD_STACK_DEFINE(mouse_work_stack_area, CONFIG_ZMK_MOUSE_DEDICATED_THREAD_STACK_SIZE);
|
|
-static struct k_work_q mouse_work_q;
|
|
-#endif
|
|
-
|
|
-struct k_work_q *zmk_mouse_work_q() {
|
|
-#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
- return &mouse_work_q;
|
|
-#else
|
|
- return &k_sys_work_q;
|
|
-#endif
|
|
-}
|
|
-
|
|
-int zmk_mouse_init() {
|
|
-#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
|
|
- k_work_q_start(&mouse_work_q, mouse_work_stack_area,
|
|
- K_THREAD_STACK_SIZEOF(mouse_work_stack_area),
|
|
- CONFIG_ZMK_MOUSE_DEDICATED_THREAD_PRIORITY);
|
|
-#endif
|
|
- return 0;
|
|
-}
|
|
\ No newline at end of file
|
|
diff --git a/app/src/mouse/tick_listener.c b/app/src/mouse/tick_listener.c
|
|
deleted file mode 100644
|
|
index 9c76bd5d2a..0000000000
|
|
--- a/app/src/mouse/tick_listener.c
|
|
+++ /dev/null
|
|
@@ -1,102 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2020 The ZMK Contributors
|
|
- *
|
|
- * SPDX-License-Identifier: MIT
|
|
- */
|
|
-
|
|
-#include <logging/log.h>
|
|
-
|
|
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|
-
|
|
-#include <zmk/event_manager.h>
|
|
-#include <zmk/events/mouse_tick.h>
|
|
-#include <zmk/endpoints.h>
|
|
-#include <zmk/mouse.h>
|
|
-
|
|
-#include <sys/util.h> // CLAMP
|
|
-
|
|
-#if CONFIG_MINIMAL_LIBC
|
|
-static float powf(float base, float exponent) {
|
|
- // poor man's power implementation rounds the exponent down to the nearest integer.
|
|
- float power = 1.0f;
|
|
- for (; exponent >= 1.0f; exponent--) {
|
|
- power = power * base;
|
|
- }
|
|
- return power;
|
|
-}
|
|
-#else
|
|
-#include <math.h>
|
|
-#endif
|
|
-
|
|
-struct vector2d move_remainder = {0};
|
|
-struct vector2d scroll_remainder = {0};
|
|
-
|
|
-static int64_t ms_since_start(int64_t start, int64_t now, int64_t delay) {
|
|
- int64_t move_duration = now - (start + delay);
|
|
- // start can be in the future if there's a delay
|
|
- if (move_duration < 0) {
|
|
- move_duration = 0;
|
|
- }
|
|
- return move_duration;
|
|
-}
|
|
-
|
|
-static float speed(const struct mouse_config *config, float max_speed, int64_t duration_ms) {
|
|
- // Calculate the speed based on MouseKeysAccel
|
|
- // See https://en.wikipedia.org/wiki/Mouse_keys
|
|
- if (duration_ms > config->time_to_max_speed_ms || config->time_to_max_speed_ms == 0 ||
|
|
- config->acceleration_exponent == 0) {
|
|
- return max_speed;
|
|
- }
|
|
- float time_fraction = (float)duration_ms / config->time_to_max_speed_ms;
|
|
- return max_speed * powf(time_fraction, config->acceleration_exponent);
|
|
-}
|
|
-
|
|
-static void track_remainder(float *move, float *remainder) {
|
|
- float new_move = *move + *remainder;
|
|
- *remainder = new_move - (int)new_move;
|
|
- *move = (int)new_move;
|
|
-}
|
|
-
|
|
-static struct vector2d update_movement(struct vector2d *remainder,
|
|
- const struct mouse_config *config, struct vector2d max_speed,
|
|
- int64_t now, int64_t *start_time) {
|
|
- struct vector2d move = {0};
|
|
- if (max_speed.x == 0 && max_speed.y == 0) {
|
|
- *remainder = (struct vector2d){0};
|
|
- return move;
|
|
- }
|
|
-
|
|
- int64_t move_duration = ms_since_start(*start_time, now, config->delay_ms);
|
|
- move = (struct vector2d){
|
|
- .x = speed(config, max_speed.x, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000,
|
|
- .y = speed(config, max_speed.y, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000,
|
|
- };
|
|
-
|
|
- track_remainder(&(move.x), &(remainder->x));
|
|
- track_remainder(&(move.y), &(remainder->y));
|
|
-
|
|
- return move;
|
|
-}
|
|
-
|
|
-static void mouse_tick_handler(const struct zmk_mouse_tick *tick) {
|
|
- struct vector2d move = update_movement(&move_remainder, &(tick->move_config), tick->max_move,
|
|
- tick->timestamp, tick->start_time);
|
|
- zmk_hid_mouse_movement_update((int16_t)CLAMP(move.x, INT16_MIN, INT16_MAX),
|
|
- (int16_t)CLAMP(move.y, INT16_MIN, INT16_MAX));
|
|
- struct vector2d scroll = update_movement(&scroll_remainder, &(tick->scroll_config),
|
|
- tick->max_scroll, tick->timestamp, tick->start_time);
|
|
- zmk_hid_mouse_scroll_update((int8_t)CLAMP(scroll.x, INT8_MIN, INT8_MAX),
|
|
- (int8_t)CLAMP(scroll.y, INT8_MIN, INT8_MAX));
|
|
-}
|
|
-
|
|
-int zmk_mouse_tick_listener(const zmk_event_t *eh) {
|
|
- const struct zmk_mouse_tick *tick = as_zmk_mouse_tick(eh);
|
|
- if (tick) {
|
|
- mouse_tick_handler(tick);
|
|
- return 0;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-ZMK_LISTENER(zmk_mouse_tick_listener, zmk_mouse_tick_listener);
|
|
-ZMK_SUBSCRIPTION(zmk_mouse_tick_listener, zmk_mouse_tick);
|
|
\ No newline at end of file
|
|
diff --git a/app/tests/mouse-keys/mkp/events.patterns b/app/tests/mouse-keys/mkp/events.patterns
|
|
new file mode 100644
|
|
index 0000000000..2599345c2d
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mkp/events.patterns
|
|
@@ -0,0 +1 @@
|
|
+s/.*zmk_hid_mouse_button_//p
|
|
diff --git a/app/tests/mouse-keys/mkp/keycode_events.snapshot b/app/tests/mouse-keys/mkp/keycode_events.snapshot
|
|
new file mode 100644
|
|
index 0000000000..ab58cc9575
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mkp/keycode_events.snapshot
|
|
@@ -0,0 +1,10 @@
|
|
+press: Button 0 count 1
|
|
+press: Mouse buttons set to 0x01
|
|
+press: Button 1 count 1
|
|
+press: Mouse buttons set to 0x03
|
|
+release: Button 1 count: 0
|
|
+release: Button 1 released
|
|
+release: Mouse buttons set to 0x01
|
|
+release: Button 0 count: 0
|
|
+release: Button 0 released
|
|
+release: Mouse buttons set to 0x00
|
|
diff --git a/app/tests/mouse-keys/mmv/native_posix.keymap b/app/tests/mouse-keys/mkp/native_posix.keymap
|
|
similarity index 64%
|
|
rename from app/tests/mouse-keys/mmv/native_posix.keymap
|
|
rename to app/tests/mouse-keys/mkp/native_posix.keymap
|
|
index ecf06601c0..dd55b1640f 100644
|
|
--- a/app/tests/mouse-keys/mmv/native_posix.keymap
|
|
+++ b/app/tests/mouse-keys/mkp/native_posix.keymap
|
|
@@ -10,8 +10,8 @@
|
|
|
|
default_layer {
|
|
bindings = <
|
|
- &mmv MOVE_LEFT &none
|
|
- &none &none
|
|
+ &mkp LCLK &none
|
|
+ &none &mkp RCLK
|
|
>;
|
|
};
|
|
};
|
|
@@ -20,7 +20,9 @@
|
|
|
|
&kscan {
|
|
events = <
|
|
- ZMK_MOCK_PRESS(0,0,100)
|
|
- ZMK_MOCK_RELEASE(0,0,10)
|
|
+ ZMK_MOCK_PRESS (0,0,100)
|
|
+ ZMK_MOCK_PRESS (1,1,100)
|
|
+ ZMK_MOCK_RELEASE(1,1, 10)
|
|
+ ZMK_MOCK_RELEASE(0,0, 10)
|
|
>;
|
|
-};
|
|
\ No newline at end of file
|
|
+};
|
|
diff --git a/app/tests/mouse-keys/mkp/native_posix_64.keymap b/app/tests/mouse-keys/mkp/native_posix_64.keymap
|
|
new file mode 100644
|
|
index 0000000000..dd55b1640f
|
|
--- /dev/null
|
|
+++ b/app/tests/mouse-keys/mkp/native_posix_64.keymap
|
|
@@ -0,0 +1,28 @@
|
|
+#include <behaviors.dtsi>
|
|
+#include <dt-bindings/zmk/keys.h>
|
|
+#include <dt-bindings/zmk/kscan_mock.h>
|
|
+#include <dt-bindings/zmk/mouse.h>
|
|
+
|
|
+/ {
|
|
+ keymap {
|
|
+ compatible = "zmk,keymap";
|
|
+ label ="Default keymap";
|
|
+
|
|
+ default_layer {
|
|
+ bindings = <
|
|
+ &mkp LCLK &none
|
|
+ &none &mkp RCLK
|
|
+ >;
|
|
+ };
|
|
+ };
|
|
+};
|
|
+
|
|
+
|
|
+&kscan {
|
|
+ events = <
|
|
+ ZMK_MOCK_PRESS (0,0,100)
|
|
+ ZMK_MOCK_PRESS (1,1,100)
|
|
+ ZMK_MOCK_RELEASE(1,1, 10)
|
|
+ ZMK_MOCK_RELEASE(0,0, 10)
|
|
+ >;
|
|
+};
|
|
diff --git a/app/tests/mouse-keys/mmv/events.patterns b/app/tests/mouse-keys/mmv/events.patterns
|
|
deleted file mode 100644
|
|
index 833100f6ac..0000000000
|
|
--- a/app/tests/mouse-keys/mmv/events.patterns
|
|
+++ /dev/null
|
|
@@ -1 +0,0 @@
|
|
-s/.*hid_listener_keycode_//p
|
|
\ No newline at end of file
|
|
diff --git a/app/tests/mouse-keys/mmv/keycode_events.snapshot b/app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
deleted file mode 100644
|
|
index 259501ba3d..0000000000
|
|
--- a/app/tests/mouse-keys/mmv/keycode_events.snapshot
|
|
+++ /dev/null
|
|
@@ -1,2 +0,0 @@
|
|
-pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
|
-released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
|
diff --git a/docs/docs/behaviors/mouse-emulation.md b/docs/docs/behaviors/mouse-emulation.md
|
|
index efe095e7a0..299fad4b25 100644
|
|
--- a/docs/docs/behaviors/mouse-emulation.md
|
|
+++ b/docs/docs/behaviors/mouse-emulation.md
|
|
@@ -17,16 +17,6 @@ This feature should be enabled via a config option:
|
|
CONFIG_ZMK_MOUSE=y
|
|
```
|
|
|
|
-This option enables several others.
|
|
-
|
|
-### Dedicated thread processing
|
|
-
|
|
-`CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED` is enabled by default and separates the processing of mouse signals into a dedicated thread, significantly improving performance.
|
|
-
|
|
-### Tick rate configuration
|
|
-
|
|
-`CONFIG_ZMK_MOUSE_TICK_DURATION` sets the tick rate for mouse polling. It is set to 8 ms. by default.
|
|
-
|
|
## Keycode Defines
|
|
|
|
To make it easier to encode the HID keycode numeric values, most keymaps include
|
|
@@ -37,7 +27,7 @@ provided by ZMK near the top:
|
|
#include <dt-bindings/zmk/mouse.h>
|
|
```
|
|
|
|
-Doing so allows using a set of defines such as `MOVE_UP`, `MOVE_DOWN`, `LCLK` and `SCROLL_UP` with these behaviors.
|
|
+Doing so allows using a set of defines such as `LCLK` and `RCLK` with these behaviors.
|
|
|
|
## Mouse Button Press
|
|
|
|
@@ -53,58 +43,3 @@ Example:
|
|
```
|
|
&mkp LCLK
|
|
```
|
|
-
|
|
-## Mouse Movement
|
|
-
|
|
-This behavior is used to manipulate the cursor.
|
|
-
|
|
-### Behavior Binding
|
|
-
|
|
-- Reference: `&mmv`
|
|
-- Parameter: A `uint32` with the first 16 bits relating to horizontal movement
|
|
- and the last 16 - to vertical movement.
|
|
-
|
|
-Example:
|
|
-
|
|
-```
|
|
-&mmv MOVE_UP
|
|
-```
|
|
-
|
|
-## Mouse Scrolling
|
|
-
|
|
-This behaviour is used to scroll, both horizontally and vertically.
|
|
-
|
|
-### Behavior Binding
|
|
-
|
|
-- Reference: `&mwh`
|
|
-- Parameter: A `uint16` with the first 8 bits relating to horizontal movement
|
|
- and the last 8 - to vertical movement.
|
|
-
|
|
-Example:
|
|
-
|
|
-```
|
|
-&mwh SCROLL_UP
|
|
-```
|
|
-
|
|
-## Acceleration
|
|
-
|
|
-Both mouse movement and scrolling have independently configurable acceleration profiles with three parameters: delay before movement, time to max speed and the acceleration exponent.
|
|
-The exponent is usually set to 0 for constant speed, 1 for uniform acceleration or 2 for uniform jerk.
|
|
-
|
|
-These profiles can be configured inside your keymap:
|
|
-
|
|
-```
|
|
-&mmv {
|
|
- time-to-max-speed-ms = <500>;
|
|
-};
|
|
-
|
|
-&mwh {
|
|
- acceleration-exponent=<1>;
|
|
-};
|
|
-
|
|
-/ {
|
|
- keymap {
|
|
- ...
|
|
- };
|
|
-};
|
|
-```
|