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).
This commit is contained in:
parent
b1deea5cc2
commit
f8a0c397e2
36 changed files with 120 additions and 943 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
|
|
|
@ -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});
|
||||
}
|
|
@ -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});
|
||||
}
|
|
@ -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(),
|
||||
});
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
|
@ -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) */
|
|
@ -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) */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
43
app/src/mouse.c
Normal file
43
app/src/mouse.c
Normal file
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
1
app/tests/mouse-keys/mkp/events.patterns
Normal file
1
app/tests/mouse-keys/mkp/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_hid_mouse_button_//p
|
10
app/tests/mouse-keys/mkp/keycode_events.snapshot
Normal file
10
app/tests/mouse-keys/mkp/keycode_events.snapshot
Normal file
|
@ -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
|
|
@ -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)
|
||||
>;
|
||||
};
|
||||
};
|
28
app/tests/mouse-keys/mkp/native_posix_64.keymap
Normal file
28
app/tests/mouse-keys/mkp/native_posix_64.keymap
Normal file
|
@ -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)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_listener_keycode_//p
|
|
@ -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
|
|
@ -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 {
|
||||
...
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
Loading…
Add table
Reference in a new issue