Compare commits

..

No commits in common. "671cea5eb0c6accf0d3300b65bb69229f5f3b664" and "2b6cdfa5936fbe49446710bfca8588eb8b4591f9" have entirely different histories.

41 changed files with 220 additions and 615 deletions

View file

@ -27,6 +27,7 @@ target_sources(app PRIVATE src/behavior.c)
target_sources_ifdef(CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS app PRIVATE src/kscan_sideband_behaviors.c)
target_sources(app PRIVATE src/matrix_transform.c)
target_sources(app PRIVATE src/physical_layouts.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/main.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)
@ -43,7 +44,8 @@ target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SOFT_OFF app PRIVATE src/behaviors/behavior_soft_off.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/input_listener.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/main.c)
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/hid_input_listener.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_ifdef(CONFIG_ZMK_BEHAVIOR_HOLD_TAP app PRIVATE src/behaviors/behavior_hold_tap.c)

View file

@ -71,7 +71,8 @@ config ZMK_BEHAVIOR_KEY_TOGGLE
config ZMK_BEHAVIOR_MOUSE_KEY_PRESS
bool
default y
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED && ZMK_MOUSE
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED
imply ZMK_MOUSE
config ZMK_BEHAVIOR_STICKY_KEY
bool
@ -96,7 +97,8 @@ config ZMK_BEHAVIOR_SOFT_OFF
config ZMK_BEHAVIOR_INPUT_TWO_AXIS
bool
default y
depends on DT_HAS_ZMK_BEHAVIOR_INPUT_TWO_AXIS_ENABLED && ZMK_MOUSE
depends on DT_HAS_ZMK_BEHAVIOR_INPUT_TWO_AXIS_ENABLED
imply ZMK_MOUSE
config ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON
bool

View file

@ -1,9 +1,3 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <behaviors/key_press.dtsi>
#include <behaviors/key_toggle.dtsi>
#include <behaviors/transparent.dtsi>
@ -25,9 +19,9 @@
#include <behaviors/key_repeat.dtsi>
#include <behaviors/backlight.dtsi>
#include <behaviors/macros.dtsi>
#include <behaviors/mouse_key_press.dtsi>
#include <behaviors/soft_off.dtsi>
#include <behaviors/studio_unlock.dtsi>
#include <behaviors/mouse_move.dtsi>
#include <behaviors/mouse_scroll.dtsi>
#include <behaviors/macros.dtsi>
#include <behaviors/mouse_keys.dtsi>

View file

@ -16,9 +16,4 @@
#binding-cells = <1>;
};
};
mkp_input_listener: mkp_input_listener {
compatible = "zmk,input-listener";
device = <&mkp>;
};
};

View file

@ -1,9 +0,0 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "mouse_key_press.dtsi"
#include "mouse_move.dtsi"
#include "mouse_scroll.dtsi"

View file

@ -1,9 +1,3 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/dt-bindings/input/input-event-codes.h>
/ {
@ -17,9 +11,4 @@
acceleration-exponent = <1>;
};
};
mmv_input_listener: mmv_input_listener {
compatible = "zmk,input-listener";
device = <&mmv>;
};
};

View file

@ -1,10 +1,3 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/dt-bindings/input/input-event-codes.h>
/ {
@ -18,9 +11,4 @@
acceleration-exponent = <0>;
};
};
msc_input_listener: msc_input_listener {
compatible = "zmk,input-listener";
device = <&msc>;
};
};

View file

@ -11,10 +11,6 @@ properties:
y-input-code:
type: int
required: true
trigger-period-ms:
type: int
default: 16
description: The time (in ms) between generated inputs when an input has non-zero speed.
delay-ms:
type: int
time-to-max-speed-ms:

View file

@ -1,21 +0,0 @@
description: |
Listener to subscribe to input events and send HID updates after processing
compatible: "zmk,input-listener"
properties:
device:
type: phandle
required: true
xy-swap:
type: boolean
x-invert:
type: boolean
y-invert:
type: boolean
scale-multiplier:
type: int
default: 1
scale-divisor:
type: int
default: 1

View file

@ -77,9 +77,9 @@
#define ZMK_HID_REPORT_ID_CONSUMER 0x02
#define ZMK_HID_REPORT_ID_MOUSE 0x03
#define HID_USAGE16(a, b) HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), a, b
#define HID_USAGE16_SINGLE(a) HID_USAGE16((a & 0xFF), ((a >> 8) & 0xFF))
// 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),
@ -195,7 +195,7 @@ static const uint8_t zmk_hid_report_desc[] = {
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_SINGLE(HID_USAGE_CONSUMER_AC_PAN),
HID_USAGE16(HID_USAGE_CONSUMER_AC_PAN),
HID_LOGICAL_MIN16(0xFF, -0x7F),
HID_LOGICAL_MAX16(0xFF, 0x7F),
HID_REPORT_SIZE(0x08),

View file

@ -10,3 +10,5 @@
typedef uint8_t zmk_mouse_button_flags_t;
typedef uint16_t zmk_mouse_button_t;
int zmk_mouse_init(void);

View file

@ -43,13 +43,12 @@ struct behavior_input_two_axis_data {
struct behavior_input_two_axis_config {
int16_t x_code;
int16_t y_code;
uint16_t delay_ms;
uint16_t time_to_max_speed_ms;
uint8_t trigger_period_ms;
int delay_ms;
int time_to_max_speed_ms;
// acceleration exponent 0: uniform speed
// acceleration exponent 1: uniform acceleration
// acceleration exponent 2: uniform jerk
uint8_t acceleration_exponent;
int acceleration_exponent;
};
#if CONFIG_MINIMAL_LIBC
@ -108,8 +107,9 @@ static float update_movement_1d(const struct behavior_input_two_axis_config *con
}
int64_t move_duration = ms_since_start(state->start_time, now, config->delay_ms);
move = (move_duration > 0)
? (speed(config, state->speed, move_duration) * config->trigger_period_ms / 1000)
move =
(move_duration > 0)
? (speed(config, state->speed, move_duration) * CONFIG_ZMK_MOUSE_TICK_DURATION / 1000)
: 0;
track_remainder(&(move), &(state->remainder));
@ -145,10 +145,10 @@ static void tick_work_cb(struct k_work *work) {
const struct device *dev = data->dev;
const struct behavior_input_two_axis_config *cfg = dev->config;
uint64_t timestamp = k_uptime_get();
uint32_t timestamp = k_uptime_get();
LOG_INF("x start: %llu, y start: %llu, current timestamp: %llu", data->state.x.start_time,
data->state.y.start_time, timestamp);
LOG_INF("tick start times: %lld %lld %lld", data->state.x.start_time, data->state.y.start_time,
timestamp);
struct vector2d move = update_movement_2d(cfg, &data->state, timestamp);
@ -165,36 +165,33 @@ static void tick_work_cb(struct k_work *work) {
}
if (should_be_working(data)) {
k_work_schedule(&data->tick_work, K_MSEC(cfg->trigger_period_ms));
k_work_schedule(&data->tick_work, K_MSEC(CONFIG_ZMK_MOUSE_TICK_DURATION));
}
}
static void set_start_times_for_activity_1d(struct movement_state_1d *state) {
if (state->speed != 0 && state->start_time == 0) {
state->start_time = k_uptime_get();
} else if (state->speed == 0) {
state->start_time = 0;
}
}
static void set_start_times_for_activity(struct movement_state_2d *state) {
set_start_times_for_activity_1d(&state->x);
set_start_times_for_activity_1d(&state->y);
if (state->x.speed != 0 && state->x.start_time == 0) {
state->x.start_time = k_uptime_get();
}
if (state->y.speed != 0 && state->y.start_time == 0) {
state->y.start_time = k_uptime_get();
}
}
static void update_work_scheduling(const struct device *dev) {
struct behavior_input_two_axis_data *data = dev->data;
const struct behavior_input_two_axis_config *cfg = dev->config;
set_start_times_for_activity(&data->state);
if (should_be_working(data)) {
k_work_schedule(&data->tick_work, K_MSEC(cfg->trigger_period_ms));
k_work_schedule(&data->tick_work, K_MSEC(CONFIG_ZMK_MOUSE_TICK_DURATION));
} else {
k_work_cancel_delayable(&data->tick_work);
}
}
int behavior_input_two_axis_adjust_speed(const struct device *dev, int16_t dx, int16_t dy) {
int zmk_input_synth_pointer_adjust_speed(const struct device *dev, int16_t dx, int16_t dy) {
struct behavior_input_two_axis_data *data = dev->data;
LOG_DBG("Adjusting: %d %d", dx, dy);
@ -208,6 +205,15 @@ int behavior_input_two_axis_adjust_speed(const struct device *dev, int16_t dx, i
return 0;
}
// static void process_key_state(const struct device *dev, int32_t val, bool pressed) {
// for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
// if (val & BIT(i)) {
// WRITE_BIT(val, i, 0);
// input_report_key(dev, INPUT_BTN_0 + i, pressed ? 1 : 0, val == 0, K_FOREVER);
// }
// }
// }
static int behavior_input_two_axis_init(const struct device *dev) {
struct behavior_input_two_axis_data *data = dev->data;
@ -227,7 +233,7 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
int16_t x = MOVE_X_DECODE(binding->param1);
int16_t y = MOVE_Y_DECODE(binding->param1);
behavior_input_two_axis_adjust_speed(behavior_dev, x, y);
zmk_input_synth_pointer_adjust_speed(behavior_dev, x, y);
return 0;
}
@ -240,7 +246,7 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
int16_t x = MOVE_X_DECODE(binding->param1);
int16_t y = MOVE_Y_DECODE(binding->param1);
behavior_input_two_axis_adjust_speed(behavior_dev, -x, -y);
zmk_input_synth_pointer_adjust_speed(behavior_dev, -x, -y);
return 0;
}
@ -252,7 +258,6 @@ static const struct behavior_driver_api behavior_input_two_axis_driver_api = {
static struct behavior_input_two_axis_config behavior_input_two_axis_config_##n = { \
.x_code = DT_INST_PROP(n, x_input_code), \
.y_code = DT_INST_PROP(n, y_input_code), \
.trigger_period_ms = DT_INST_PROP(n, trigger_period_ms), \
.delay_ms = DT_INST_PROP_OR(n, delay_ms, 0), \
.time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
.acceleration_exponent = DT_INST_PROP_OR(n, acceleration_exponent, 1), \

View file

@ -30,5 +30,8 @@ int main(void) {
zmk_display_init();
#endif /* CONFIG_ZMK_DISPLAY */
#ifdef CONFIG_ZMK_MOUSE
zmk_mouse_init();
#endif /* CONFIG_ZMK_MOUSE */
return 0;
}

View file

@ -1,8 +1,40 @@
# Copyright (c) 2023 The ZMK Contributors
# SPDX-License-Identifier: MIT
config ZMK_MOUSE
menuconfig ZMK_MOUSE
bool "Mouse Emulation"
select INPUT
select INPUT_THREAD_PRIORITY_OVERRIDE
if ZMK_MOUSE
config ZMK_MOUSE_TICK_DURATION
int "Mouse tick duration in ms"
default 16
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

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/input/input.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zmk/mouse.h>
#include <zmk/endpoints.h>
#include <zmk/hid.h>
void handle_rel_code(struct input_event *evt) {
switch (evt->code) {
case INPUT_REL_X:
zmk_hid_mouse_movement_update(evt->value, 0);
break;
case INPUT_REL_Y:
zmk_hid_mouse_movement_update(0, evt->value);
break;
case INPUT_REL_WHEEL:
zmk_hid_mouse_scroll_update(0, evt->value);
break;
case INPUT_REL_HWHEEL:
zmk_hid_mouse_scroll_update(evt->value, 0);
break;
default:
break;
}
}
void handle_key_code(struct input_event *evt) {
int8_t btn;
switch (evt->code) {
case INPUT_BTN_0:
case INPUT_BTN_1:
case INPUT_BTN_2:
case INPUT_BTN_3:
case INPUT_BTN_4:
btn = evt->code - INPUT_BTN_0;
if (evt->value > 0) {
zmk_hid_mouse_button_press(btn);
} else {
zmk_hid_mouse_button_release(btn);
}
break;
default:
break;
}
}
void input_handler(struct input_event *evt) {
switch (evt->type) {
case INPUT_EV_REL:
handle_rel_code(evt);
break;
case INPUT_EV_KEY:
handle_key_code(evt);
break;
}
if (evt->sync) {
zmk_endpoints_send_mouse_report();
zmk_hid_mouse_scroll_set(0, 0);
zmk_hid_mouse_movement_set(0, 0);
}
}
INPUT_CALLBACK_DEFINE(NULL, input_handler);

View file

@ -1,222 +0,0 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT zmk_input_listener
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/input/input.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zmk/endpoints.h>
#include <zmk/mouse.h>
#include <zmk/hid.h>
#define ONE_IF_DEV_OK(n) \
COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_PHANDLE(n, device), okay), (1 +), (0 +))
#define VALID_LISTENER_COUNT (DT_INST_FOREACH_STATUS_OKAY(ONE_IF_DEV_OK) 0)
#if VALID_LISTENER_COUNT > 0
enum input_listener_xy_data_mode {
INPUT_LISTENER_XY_DATA_MODE_NONE,
INPUT_LISTENER_XY_DATA_MODE_REL,
INPUT_LISTENER_XY_DATA_MODE_ABS,
};
struct input_listener_xy_data {
enum input_listener_xy_data_mode mode;
int16_t x;
int16_t y;
};
struct input_listener_data {
union {
struct {
struct input_listener_xy_data data;
struct input_listener_xy_data wheel_data;
uint8_t button_set;
uint8_t button_clear;
} mouse;
};
};
struct input_listener_config {
bool xy_swap;
bool x_invert;
bool y_invert;
uint16_t scale_multiplier;
uint16_t scale_divisor;
};
static void handle_rel_code(struct input_listener_data *data, struct input_event *evt) {
switch (evt->code) {
case INPUT_REL_X:
data->mouse.data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
data->mouse.data.x += evt->value;
break;
case INPUT_REL_Y:
data->mouse.data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
data->mouse.data.y += evt->value;
break;
case INPUT_REL_WHEEL:
data->mouse.wheel_data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
data->mouse.wheel_data.y += evt->value;
break;
case INPUT_REL_HWHEEL:
data->mouse.wheel_data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
data->mouse.wheel_data.x += evt->value;
break;
default:
break;
}
}
static void handle_abs_code(const struct input_listener_config *config,
struct input_listener_data *data, struct input_event *evt) {}
static void handle_key_code(const struct input_listener_config *config,
struct input_listener_data *data, struct input_event *evt) {
int8_t btn;
switch (evt->code) {
case INPUT_BTN_0:
case INPUT_BTN_1:
case INPUT_BTN_2:
case INPUT_BTN_3:
case INPUT_BTN_4:
btn = evt->code - INPUT_BTN_0;
if (evt->value > 0) {
WRITE_BIT(data->mouse.button_set, btn, 1);
} else {
WRITE_BIT(data->mouse.button_clear, btn, 1);
}
break;
default:
break;
}
}
static void swap_xy(struct input_event *evt) {
switch (evt->code) {
case INPUT_REL_X:
evt->code = INPUT_REL_Y;
break;
case INPUT_REL_Y:
evt->code = INPUT_REL_X;
break;
}
}
static inline bool is_x_data(const struct input_event *evt) {
return evt->type == INPUT_EV_REL && evt->code == INPUT_REL_X;
}
static inline bool is_y_data(const struct input_event *evt) {
return evt->type == INPUT_EV_REL && evt->code == INPUT_REL_Y;
}
static void filter_with_input_config(const struct input_listener_config *cfg,
struct input_event *evt) {
if (!evt->dev) {
return;
}
if (cfg->xy_swap) {
swap_xy(evt);
}
if ((cfg->x_invert && is_x_data(evt)) || (cfg->y_invert && is_y_data(evt))) {
evt->value = -(evt->value);
}
evt->value = (int16_t)((evt->value * cfg->scale_multiplier) / cfg->scale_divisor);
}
static void clear_xy_data(struct input_listener_xy_data *data) {
data->x = data->y = 0;
data->mode = INPUT_LISTENER_XY_DATA_MODE_NONE;
}
static void input_handler(const struct input_listener_config *config,
struct input_listener_data *data, struct input_event *evt) {
// First, filter to update the event data as needed.
filter_with_input_config(config, evt);
switch (evt->type) {
case INPUT_EV_REL:
handle_rel_code(data, evt);
break;
case INPUT_EV_ABS:
handle_abs_code(config, data, evt);
break;
case INPUT_EV_KEY:
handle_key_code(config, data, evt);
break;
}
if (evt->sync) {
if (data->mouse.wheel_data.mode == INPUT_LISTENER_XY_DATA_MODE_REL) {
zmk_hid_mouse_scroll_set(data->mouse.wheel_data.x, data->mouse.wheel_data.y);
}
if (data->mouse.data.mode == INPUT_LISTENER_XY_DATA_MODE_REL) {
zmk_hid_mouse_movement_set(data->mouse.data.x, data->mouse.data.y);
}
if (data->mouse.button_set != 0) {
for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
if ((data->mouse.button_set & BIT(i)) != 0) {
zmk_hid_mouse_button_press(i);
}
}
}
if (data->mouse.button_clear != 0) {
for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
if ((data->mouse.button_clear & BIT(i)) != 0) {
zmk_hid_mouse_button_release(i);
}
}
}
zmk_endpoints_send_mouse_report();
zmk_hid_mouse_scroll_set(0, 0);
zmk_hid_mouse_movement_set(0, 0);
clear_xy_data(&data->mouse.data);
clear_xy_data(&data->mouse.wheel_data);
data->mouse.button_set = data->mouse.button_clear = 0;
}
}
#endif // VALID_LISTENER_COUNT > 0
#define IL_INST(n) \
COND_CODE_1( \
DT_NODE_HAS_STATUS(DT_INST_PHANDLE(n, device), okay), \
(static const struct input_listener_config config_##n = \
{ \
.xy_swap = DT_INST_PROP(n, xy_swap), \
.x_invert = DT_INST_PROP(n, x_invert), \
.y_invert = DT_INST_PROP(n, y_invert), \
.scale_multiplier = DT_INST_PROP(n, scale_multiplier), \
.scale_divisor = DT_INST_PROP(n, scale_divisor), \
}; \
static struct input_listener_data data_##n = {}; \
void input_handler_##n(struct input_event *evt) { \
input_handler(&config_##n, &data_##n, evt); \
} INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_INST_PHANDLE(n, device)), input_handler_##n);), \
())
DT_INST_FOREACH_STATUS_OKAY(IL_INST)

30
app/src/mouse/main.c Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/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(void) {
#if IS_ENABLED(CONFIG_ZMK_MOUSE_WORK_QUEUE_DEDICATED)
k_work_queue_start(&mouse_work_q, mouse_work_stack_area,
K_THREAD_STACK_SIZEOF(mouse_work_stack_area),
CONFIG_ZMK_MOUSE_DEDICATED_THREAD_PRIORITY, NULL);
#endif
return 0;
}

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,18 +0,0 @@
movement_set: Mouse movement set to -1/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -5/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -5/-5
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/-5
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,33 +0,0 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>
&mmv_input_listener {
scale-multiplier = <5>;
scale-divisor = <3>;
};
/ {
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&mmv MOVE_LEFT &mmv MOVE_UP
&none &none
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(0,1,100)
ZMK_MOCK_RELEASE(0,0,10)
ZMK_MOCK_RELEASE(0,1,10)
>;
};

View file

@ -1,18 +0,0 @@
movement_set: Mouse movement set to 1/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 2/2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 2/2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 3/2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 3/3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,33 +0,0 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>
&mmv_input_listener {
x-invert;
y-invert;
};
/ {
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&mmv MOVE_LEFT &mmv MOVE_UP
&none &none
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(0,1,100)
ZMK_MOCK_RELEASE(0,0,10)
ZMK_MOCK_RELEASE(0,1,10)
>;
};

View file

@ -1,18 +0,0 @@
movement_set: Mouse movement set to 0/-1
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,32 +0,0 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>
&mmv_input_listener {
xy-swap;
};
/ {
keymap {
compatible = "zmk,keymap";
label ="Default keymap";
default_layer {
bindings = <
&mmv MOVE_LEFT &mmv MOVE_UP
&none &none
>;
};
};
};
&kscan {
events = <
ZMK_MOCK_PRESS(0,0,10)
ZMK_MOCK_PRESS(0,1,100)
ZMK_MOCK_RELEASE(0,0,10)
ZMK_MOCK_RELEASE(0,1,10)
>;
};

View file

@ -1,18 +1,22 @@
movement_set: Mouse movement set to -1/0
movement_update: Mouse movement updated to -1/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/-2
movement_update: Mouse movement updated to -2/0
movement_update: Mouse movement updated to -2/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/-2
movement_update: Mouse movement updated to -2/0
movement_update: Mouse movement updated to -2/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/-2
movement_update: Mouse movement updated to -3/0
movement_update: Mouse movement updated to -3/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/-3
movement_update: Mouse movement updated to -3/0
movement_update: Mouse movement updated to -3/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/-3
movement_update: Mouse movement updated to 0/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,5 +1,4 @@
#include <behaviors.dtsi>
#include <behaviors/mouse_move.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>

View file

@ -1,24 +1,27 @@
movement_set: Mouse movement set to -1/0
movement_update: Mouse movement updated to -1/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/0
movement_update: Mouse movement updated to -2/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -2/0
movement_update: Mouse movement updated to -2/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to -3/0
movement_update: Mouse movement updated to -3/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 1/0
movement_update: Mouse movement updated to 3/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 2/0
movement_update: Mouse movement updated to 5/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 2/0
movement_update: Mouse movement updated to 5/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 3/0
movement_update: Mouse movement updated to 6/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_update: Mouse movement updated to 6/0
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,5 +1,4 @@
#include <behaviors.dtsi>
#include <behaviors/mouse_move.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>

View file

@ -1,24 +1,27 @@
movement_set: Mouse movement set to 0/-1
movement_update: Mouse movement updated to 0/-1
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/-2
movement_update: Mouse movement updated to 0/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/-2
movement_update: Mouse movement updated to 0/-2
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/-3
movement_update: Mouse movement updated to 0/-3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/1
movement_update: Mouse movement updated to 0/3
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/2
movement_update: Mouse movement updated to 0/5
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/2
movement_update: Mouse movement updated to 0/5
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_set: Mouse movement set to 0/3
movement_update: Mouse movement updated to 0/6
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0
movement_update: Mouse movement updated to 0/6
scroll_set: Mouse scroll set to 0/0
movement_set: Mouse movement set to 0/0

View file

@ -1,6 +0,0 @@
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
CONFIG_ZMK_MOUSE=y

View file

@ -1,5 +1,4 @@
#include <behaviors.dtsi>
#include <behaviors/mouse_move.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/kscan_mock.h>
#include <dt-bindings/zmk/mouse.h>

View file

@ -43,8 +43,6 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
| Binding | Behavior | Description |
| ------- | ----------------------------------------------------------- | ------------------------------- |
| `&mkp` | [Mouse Button Press](mouse-emulation.md#mouse-button-press) | Emulates pressing mouse buttons |
| `&mmv` | [Mouse Button Press](mouse-emulation.md#mouse-move) | Emulates mouse movement |
| `&msc` | [Mouse Button Press](mouse-emulation.md#mouse-scroll) | Emulates mouse scrolling |
## Reset Behaviors

View file

@ -5,7 +5,8 @@ sidebar_label: Mouse Emulation
## Summary
Mouse emulation behaviors send mouse events, including mouse button presses, cursor movement and scrolling.
Mouse emulation behaviors send mouse events. Currently, only mouse button presses are supported, but movement
and scroll action support is planned for the future.
:::warning[Refreshing the HID descriptor]
@ -16,12 +17,14 @@ The mouse functionality will not work over BLE until that is done.
## Configuration Option
To use any of the behaviors documented here, the ZMK mouse feature must be enabled explicitly via a config option:
This feature can be enabled or disabled explicitly via a config option:
```
CONFIG_ZMK_MOUSE=y
```
If you use the mouse key press behavior in your keymap, the feature will automatically be enabled for you.
## Mouse Button Defines
To make it easier to encode the HID mouse button numeric values, include
@ -66,67 +69,3 @@ This example will send press of the fourth mouse button when the binding is trig
```
&mkp MB4
```
## Mouse Move
This behavior sends mouse X/Y movement events to the connected host.
### Behavior Binding
- Reference: `&mmv`
- Parameter: A `uint32` with 16-bits each used for vertical and horizontal velocity.
The following defines can be passed for the parameter:
| Define | Action |
| :----------- | :--------- |
| `MOVE_UP` | Move up |
| `MOVE_DOWN` | Move down |
| `MOVE_LEFT` | Move left |
| `MOVE_RIGHT` | Move right |
### Examples
The following will send a scroll down event to the host when pressed/held:
```
&mmv MOVE_DOWN
```
The following will send a scroll left event to the host when pressed/held:
```
&mmv MOVE_LEFT
```
## Mouse Scroll
This behavior sends vertical and horizontal scroll events to the connected host.
### Behavior Binding
- Reference: `&msc`
- Parameter: A `uint32` with 16-bits each used for vertical and horizontal velocity.
The following defines can be passed for the parameter:
| Define | Action |
| :----------- | :--------- |
| `MOVE_UP` | Move up |
| `MOVE_DOWN` | Move down |
| `MOVE_LEFT` | Move left |
| `MOVE_RIGHT` | Move right |
### Examples
The following will send a scroll down event to the host when pressed/held:
```
&msc MOVE_DOWN
```
The following will send a scroll left event to the host when pressed/held:
```
&msc MOVE_LEFT
```