This document describes how to configure the Open Joypad driver via device tree. The driver supports four distinct operating modes:
- none (GPIO-only)
- multiadc (multiple ADC channels)
- singleadc (single ADC channel + analog multiplexer)
- miyooserial (Miyoo-like serial protocol over
/dev/ttyS1)
Below you’ll find:
The Open Joypad driver provides a flexible input subsystem interface for devices with various input configurations:
- Simple GPIO-only button input (no analog).
- Multi-ADC analog input, each axis mapped to its own ADC channel.
- Single-ADC plus an analog multiplexer (amux), toggling between multiple axes on a single ADC input.
- A Miyoo serial mechanism reading joystick frames over
/dev/ttyS1.
Child nodes in the device tree define individual GPIO buttons, each with a gpios property and a linux,code specifying the Linux input keycode.
-
noneOnly GPIO buttons, no analog axes. -
multiadcMultiple ADC channels, one per analog axis. -
singleadcA single ADC channel with an external analog multiplexer. The driver configures GPIO lines to select which axis to read. -
miyooserialReads a 6-byte frame at 9600 8N1 on/dev/ttyS1, parsing two analog sticks (left & right) from the data.
-
compatibleMust be"open,joypad". -
joypad-modeA string:"none","multiadc","singleadc", or"miyooserial". -
Child nodes: Each child node corresponds to a GPIO button.
gpios—<&gpioX pinY GPIO_ACTIVE_LOW>or similar.label— optional human-readable name.linux,code— integer, the Linux keycode (e.g.0x131for KEY_ENTER).linux,input-type— optional; defaultEV_KEYif not specified.
-
joypad-nameString that overrides the default input device name ("open-joypad"). -
poll-intervalInteger (milliseconds). How often the driver polls inputs (default10). -
autorepeatBoolean. If present, the driver enables auto-repeat for keys. -
button-adc-fuzzInteger specifying analog axis fuzz (noise filter). Defaults to0. -
button-adc-flatInteger specifying a flat zone for analog axes (± this range is zero). Defaults to0. -
button-adc-scaleInteger scale factor for ADC values (default1). -
button-adc-deadzoneInteger radial deadzone. Ifsqrt(x^2 + y^2)is below this, the axis is reported as zero. -
Axis Inversion Flags Each is a boolean property. If present, it inverts that axis:
invert-absxinvert-absyinvert-abszinvert-absrxinvert-absryinvert-absrz
-
pwm-namesIf present (e.g."enable"), the driver tries to get a PWM device for rumble. This enables a force-feedback interface (FF_RUMBLE).
(Valid only if joypad-mode = "multiadc")
-
io-channel-namesA string array listing each ADC channel needed (e.g."adc-x", "adc-y", ..."). -
Axis Tuning Overrides e.g.
abs_x-p-tuning,abs_x-n-tuning,abs_y-p-tuning, etc. Each is an integer adjusting positive/negative scaling. Defaults to180if not set.
(Valid only if joypad-mode = "singleadc")
-
amux-countThe number of virtual channels (axes) read from the multiplexer (e.g.4for X/Y + RX/RY). -
amux-channel-mappingAn array of 4 integers (default<0 1 2 3>) specifying how the multiplexer channels map to axes. -
amux-a-gpios,amux-b-gpios,amux-en-gpiosGPIO lines for the multiplexer select bits and enable. -
io-channel-namesTypically a single entry"amux_adc"referencing the single ADC input used by the AMUX. -
Tuning Overrides Similar to multi-ADC, e.g.
abs_x-p-tuning,abs_y-n-tuning, etc.
(Valid only if joypad-mode = "miyooserial")
-
The driver reads a 6-byte frame: [0xFF, leftY, leftX, rightY, rightX, 0xFE]
-
It automatically calibrates zero from ~50 frames on initialization.
-
No additional DT properties required unless customizing calibration or the UART device node.
joypad0: joypad@0 {
compatible = "open,joypad";
joypad-mode = "none";
poll-interval = <10>;
autorepeat; /* optional boolean */
button@0 {
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
label = "BUTTON_A";
linux,code = <0x131>; /* e.g. KEY_ENTER */
linux,input-type = <0x01>; /* EV_KEY */
};
button@1 {
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
label = "BUTTON_B";
linux,code = <0x133>; /* e.g. KEY_HOME */
linux,input-type = <0x01>; /* EV_KEY */
};
};
joypad1: joypad@1 {
compatible = "open,joypad";
joypad-mode = "multiadc";
poll-interval = <10>;
/* Provide multiple ADC channels for axes: e.g. RY, RX, Y, X, Z, RZ */
io-channel-names = "adc-ry", "adc-rx", "adc-y", "adc-x", "adc-z", "adc-rz";
button-adc-scale = <1>;
button-adc-deadzone = <200>;
/* Example: invert right-X axis */
invert-absrx;
/* Optional GPIO buttons as child nodes */
button@0 {
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
label = "SELECT_BUTTON";
linux,code = <0x161>;
};
button@1 {
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
label = "START_BUTTON";
linux,code = <0x162>;
};
};
joypad2: joypad@2 {
compatible = "open,joypad";
joypad-mode = "singleadc";
poll-interval = <10>;
amux-count = <4>;
/* Single ADC channel for the mux output */
io-channel-names = "amux_adc";
amux_adc: io-channels = <&saradc0 0>;
/* MUX selection lines */
amux-a-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
amux-b-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
amux-en-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
/* Map internal mux channels; default is <0 1 2 3> */
amux-channel-mapping = <0 1 2 3>;
/* Example additional GPIO buttons */
button@0 {
gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
label = "BUTTON_X";
linux,code = <0x133>;
};
button@1 {
gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
label = "BUTTON_Y";
linux,code = <0x134>;
};
};
joypad3: joypad@3 {
compatible = "open,joypad";
joypad-mode = "miyooserial";
poll-interval = <10>;
/* The driver opens /dev/ttyS1 at 9600 8N1 to parse frames */
button@0 {
gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
label = "A_BUTTON";
linux,code = <0x130>;
};
button@1 {
gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
label = "B_BUTTON";
linux,code = <0x131>;
};
};
joypad-rumble: joypad@4 {
compatible = "open,joypad";
joypad-mode = "none";
/* Indicate a PWM device for vibration/rumble */
pwm-names = "enable";
/* Reference a valid PWM in your SoC */
pwms = <&pwm0 0 1000000 0>;
button@0 {
gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
label = "BUTTON_L";
linux,code = <0x136>;
};
};
-
GPIO References Your SoC may define GPIO pins differently (e.g.
<&pio 0 0 GPIO_ACTIVE_HIGH>). Adjust accordingly. -
Keycodes
linux,codemust be a valid Linux input keycode (seeinclude/uapi/linux/input-event-codes.h). -
ADC Requirements For
multiadcorsingleadc, ensure you have matchingio-channelsdefined for your SoC or external ADC. Each name inio-channel-namesmust match a channel resource in the device tree. -
Serial The Miyoo serial mode is currently hardcoded to read
/dev/ttyS1at 9600 8N1. Modify the driver source if you need a different UART or baud rate. -
Rumble/Force Feedback Specifying
pwm-names = "enable"tells the driver to register a force-feedback device (FF_RUMBLE) using the PWM. From user space, you can test or trigger rumble via typical FF APIs or tools such asfftest.