This repo contains a kernel module to use a rotary encoder connected to gpio pins as a volume control. rather than completely reinvent the wheel this makes use of the rotary_encoder module from the linux source tree. This has been tested on a raspberry pi running both raspbian and OSMC, however as this module and the rotary_encoder module use nothing more than the sysfs gpio interface this should work on other SBC's with gpio capability.
sudo modprobe rotary-encoder
if it completes without error then this module should work.either:
a. clone this repo
b. copy the source and makefile from the module
subfolder
Then open terminal in the folder containing the source and makefile
/boot/config.txt
to add the following line:dtoverlay=rotary-encoder:relative_axis=1,linux_axis=9
/boot/config.txt
to add the following line:dtoverlay=rotary-encoder-overlay:relative_axis=1,linux_axis=9
currently the only way to load the module on boot is to add it to the /etc/modules
file, this must be on it's own line:
rotary_volume
Ideally this would be replaced by a device tree overlay that would also enable the encoder directly, just requiring a single dtoverlay entry in the config file, but this is not currently implemented.
If you are on OSMC then the rotary encoder is available in the dev branch as I write this, requiring kernel 4.14.30-2 or newer. otherwise you could download the source directly here, you could either try the latest branch, or get the version that matches your kernel. then use the makefile from the extras folder here
to use this with kodi required changing udev rules, because on load kodi grabs all input devices, this includes the rotary encoder event though it doesn't know what to do with any of the events from it. by changing the ownership of that input from root:input
to root:root
we can prevent it from being accesible to kodi, allowing this module to work as intended.
on OSMC this can be achieved by editing /etc/udev/rules.d/998-fix-input.rules
to contain the following:
# input
KERNEL=="mouse*|mice|event*", MODE="0660", GROUP="osmc"
KERNEL=="event*", DRIVERS=="rotary-encoder", MODE="0660", GROUP="root"
KERNEL=="ts[0-9]*|uinput", MODE="0660", GROUP="osmc"
KERNEL=="js[0-9]*", MODE="0660", GROUP="osmc"
# tty
SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0666"
you can test each stage by using evtest, if you have already set up the udev rules then this will need to be run as root.
if you run evtest
and select the rotary device you should see ea long list of supported keys ending in the volume keys, the driver will never send any other keys than volume up and down, however kodi ignored events from devices with 20 or less keys, so this is currently a hacky workaround to make kodi recognise this module.
when you turn the rotary encoder you should see events come in, with code 9 (the axis we picked) and value of either 1 or -1, the positive events get turned into volume up presses, and negative becomes volume down.
assuming the first test is successful we can then test this module by selecting it with evtest
, again we should see evets come in when we turn the encoder, either KEY_VOLUMEUP or KEY_VOLUMEDOWN.
when writing this module I only had a 400 pulse per revolution encoder available, so I wrote in the capability to require multiple "counts" before sending a keypress, this is the count_per_press
variable here reducing this number will result in more events, if you reduce it to 1 and its still not fast enough for your liking you could add either:
steps-per-period=2
or
steps-per-period=4
to the line in the config file for the rotary encoder, eg:
`dtoverlay=rotary-encoder:relative_axis=1,linux_axis=9,steps-per-period=2`