Skip to main content

Pointing Devices

ZMK's pointing device support builds upon the Zephyr input API to offer pointing/mouse functionality with various hardware. A limited number of input drivers are available in the Zephyr version currently used by ZMK, but additional drivers can be found in external modules for a variety of hardware.

The details will depend on if you are adding a pointing device to a split peripheral as opposed to a unibody keyboard or split central part:

Input Device

First, we must define the pointing device itself. The specifics of where this node goes will depend on the specific hardware. Most pointing hardware uses either SPI or I2C for communication, and will be nested under a properly configured bus node, e.g. &pro_micro_i2c or for a complete onboard setup, &i2c3. See the documentation on pin control if you need to configure the pins for an I2C or SPI bus.

For example, if setting up an SPI device, you may have a node like:

&pro_micro_spi {
status = "okay";
cs-gpios = <&pro_micro 19 GPIO_ACTIVE_LOW>;

glidepoint: glidepoint@0 {
compatible = "cirque,pinnacle";
reg = <0>;
spi-max-frequency = <1000000>;
status = "okay";
dr-gpios = <&pro_micro 5 (GPIO_ACTIVE_HIGH)>;

sensitivity = "4x";
sleep;
no-taps;
};
};

The specifics of the properties required to set for a given driver will vary; always consult the devicetree bindings file for the specific driver to see what properties can be set.

Listener

Every input device needs an associated listener added that listens for events from the device and processes them before sending the events to the host using a HID mouse report. See input listener configuration for the full details. For example, to add a listener for the above device:

/ {
glidepoint_listener {
compatible = "zmk,input-listener";
device = <&glidepoint>;
};
};

Input Processors

Some physical pointing devices may be generating input events that need adjustment before being sent to hosts. For example a trackpad might be integrated into a keyboard rotated 90° and need the X/Y data adjusted appropriately. This can be accomplished with input processors. As an example, you could enhance the above listener with the following input processor that inverts and swaps the X/Y axes:

#include <dt-bindings/zmk/input_transform.h>

/ {
glidepoint_listener {
compatible = "zmk,input-listener";
device = <&glidepoint>;
input-processors = <&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_X_INVERT | INPUT_TRANSFORM_Y_INVERT)>;
};
};