Skip to content

Commit

Permalink
feat(mouse): Add mouse move and scroll support [WIP]
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Krikun <[email protected]>
Co-authored-by: Robert U <[email protected]>
Co-authored-by: Shawn Meier <[email protected]>
  • Loading branch information
4 people authored and petejohanson committed Dec 4, 2023
1 parent 03bdce0 commit 0eb5091
Show file tree
Hide file tree
Showing 31 changed files with 803 additions and 70 deletions.
10 changes: 9 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/key_listener.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/main.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE 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)
Expand All @@ -35,13 +38,16 @@ 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_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/events/mouse_move_state_changed.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/events/mouse_tick.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE 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_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/main.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)
Expand All @@ -60,6 +66,8 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_VAR app PRIVATE src/behaviors/behavior_sensor_rotate_var.c)
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON app PRIVATE src/behaviors/behavior_sensor_rotate_common.c)
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_MOUSE_KEY_PRESS app PRIVATE src/behaviors/behavior_mouse_key_press.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/behaviors/behavior_mouse_move.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/behaviors/behavior_mouse_scroll.c)
target_sources(app PRIVATE src/combo.c)
target_sources(app PRIVATE src/behaviors/behavior_tap_dance.c)
target_sources(app PRIVATE src/behavior_queue.c)
Expand Down
4 changes: 1 addition & 3 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,7 @@ endmenu

menu "Mouse Options"

config ZMK_MOUSE
bool "Enable ZMK mouse emulation"
default n
rsource "src/mouse/Kconfig"

#Mouse Options
endmenu
Expand Down
3 changes: 3 additions & 0 deletions app/dts/behaviors.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
#include <behaviors/backlight.dtsi>
#include <behaviors/macros.dtsi>
#include <behaviors/mouse_key_press.dtsi>
#include <behaviors/mouse_move.dtsi>
#include <behaviors/mouse_scroll.dtsi>
#include <behaviors/macros.dtsi>
12 changes: 12 additions & 0 deletions app/dts/behaviors/mouse_move.dtsi
Original file line number Diff line number Diff line change
@@ -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>;
};
};
};
12 changes: 12 additions & 0 deletions app/dts/behaviors/mouse_scroll.dtsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/ {
behaviors {
/omit-if-no-ref/ 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>;
};
};
};
13 changes: 13 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-mouse-move.yaml
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions app/dts/bindings/behaviors/zmk,behavior-mouse-scroll.yaml
Original file line number Diff line number Diff line change
@@ -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
36 changes: 35 additions & 1 deletion app/include/dt-bindings/zmk/mouse.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 The ZMK Contributors
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
Expand All @@ -22,3 +22,37 @@

#define MB4 BIT(3)
#define MB5 BIT(4)

#ifndef ZMK_MOUSE_DEFAULT_MOVE_VAL
#define ZMK_MOUSE_DEFAULT_MOVE_VAL 600
#endif

#ifndef ZMK_MOUSE_DEFAULT_SCRL_VAL
#define ZMK_MOUSE_DEFAULT_SCRL_VAL 10
#endif

/* Mouse move behavior */
#define MOVE_Y(vert) ((vert)&0xFFFF)
#define MOVE_Y_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
#define MOVE_X(hor) (((hor)&0xFFFF) << 16)
#define MOVE_X_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)

#define MOVE(hor, vert) (MOVE_X(hor) + MOVE_Y(vert))

#define MOVE_UP MOVE_Y(-ZMK_MOUSE_DEFAULT_MOVE_VAL)
#define MOVE_DOWN MOVE_Y(ZMK_MOUSE_DEFAULT_MOVE_VAL)
#define MOVE_LEFT MOVE_X(-ZMK_MOUSE_DEFAULT_MOVE_VAL)
#define MOVE_RIGHT MOVE_X(ZMK_MOUSE_DEFAULT_MOVE_VAL)

/* Mouse scroll behavior */
#define SCRL_Y(vert) ((vert)&0xFFFF)
#define SCRL_Y_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
#define SCRL_X(hor) (((hor)&0xFFFF) << 16)
#define SCRL_X_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)

#define SCROLL(hor, vert) (SCRL_X(hor) + SCRL_Y(vert))

#define SCRL_UP SCRL_Y(ZMK_MOUSE_DEFAULT_SCRL_VAL)
#define SCRL_DOWN SCRL_Y(-ZMK_MOUSE_DEFAULT_SCRL_VAL)
#define SCRL_LEFT SCRL_X(-ZMK_MOUSE_DEFAULT_SCRL_VAL)
#define SCRL_RIGHT SCRL_X(ZMK_MOUSE_DEFAULT_SCRL_VAL)
2 changes: 1 addition & 1 deletion app/include/zmk/endpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ int zmk_endpoints_send_report(uint16_t usage_page);

#if IS_ENABLED(CONFIG_ZMK_MOUSE)
int zmk_endpoints_send_mouse_report();
#endif // IS_ENABLE(CONFIG_ZMK_MOUSE)
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
33 changes: 33 additions & 0 deletions app/include/zmk/events/mouse_move_state_changed.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#include <zephyr/kernel.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_X_DECODE(encoded),
.y = MOVE_Y_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});
}
34 changes: 34 additions & 0 deletions app/include/zmk/events/mouse_scroll_state_changed.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#include <zephyr/kernel.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 = SCRL_X_DECODE(encoded),
.y = SCRL_Y_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});
}
39 changes: 39 additions & 0 deletions app/include/zmk/events/mouse_tick.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#include <dt-bindings/zmk/mouse.h>
#include <zephyr/kernel.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(),
});
}
18 changes: 17 additions & 1 deletion app/include/zmk/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
#define ZMK_HID_REPORT_ID_CONSUMER 0x02
#define ZMK_HID_REPORT_ID_MOUSE 0x03

// Needed until Zephyr offers a 2 byte usage macro
#define HID_USAGE16(idx) \
HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), (idx & 0xFF), (idx >> 8 & 0xFF)

static const uint8_t zmk_hid_report_desc[] = {
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP),
HID_USAGE(HID_USAGE_GD_KEYBOARD),
Expand Down Expand Up @@ -167,6 +171,13 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_REPORT_SIZE(0x08),
HID_REPORT_COUNT(0x03),
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL),
HID_USAGE_PAGE(HID_USAGE_CONSUMER),
HID_USAGE16(HID_USAGE_CONSUMER_AC_PAN),
HID_LOGICAL_MIN8(-0x7F),
HID_LOGICAL_MAX8(0x7F),
HID_REPORT_SIZE(0x08),
HID_REPORT_COUNT(0x01),
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL),
HID_END_COLLECTION,
HID_END_COLLECTION,
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
Expand Down Expand Up @@ -237,7 +248,8 @@ struct zmk_hid_mouse_report_body {
zmk_mouse_button_flags_t buttons;
int8_t d_x;
int8_t d_y;
int8_t d_wheel;
int8_t d_scroll_y;
int8_t d_scroll_x;
} __packed;

struct zmk_hid_mouse_report {
Expand Down Expand Up @@ -278,6 +290,10 @@ 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();
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)

Expand Down
19 changes: 18 additions & 1 deletion app/include/zmk/mouse.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 The ZMK Contributors
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
Expand All @@ -10,3 +10,20 @@

typedef uint8_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();
Loading

0 comments on commit 0eb5091

Please sign in to comment.