|How To...||Why not..?||Scripts|
Last update: 2018-08-10
This article show you how you can get the extra multimedia keys working. For this I use only software that is part of the base system - with the exception of the media player mpv.
The keyboard I use at home is Das Keyboard 4 Ultimate. It has the following extra keys available:
|Key||Description / Action|
|Moon||Sleep / Hibernate / Shutdown|
|Mute||Mute / unmute the speakers|
|Wheel||Volume up / Volume down|
||Play / Pause|
First, you must find out which USB HID devices are detected by OpenBSD during boot. Use dmesg(8) together with grep(1) to get the list:
$ dmesg | grep uhidev uhidev0 at uhub2 port 2 configuration 1 interface 0 "Logitech USB Receiver" rev 2.00/12.03 addr 3 uhidev0: iclass 3/1 ukbd0 at uhidev0: 8 variable keys, 6 key codes uhidev1 at uhub2 port 2 configuration 1 interface 1 "Logitech USB Receiver" rev 2.00/12.03 addr 3 uhidev1: iclass 3/1, 8 report ids ums0 at uhidev1 reportid 2: 16 buttons, Z and W dir uhid0 at uhidev1 reportid 3: input=4, output=0, feature=0 uhid1 at uhidev1 reportid 4: input=1, output=0, feature=0 uhid2 at uhidev1 reportid 8: input=1, output=0, feature=0 uhidev2 at uhub2 port 2 configuration 1 interface 2 "Logitech USB Receiver" rev 2.00/12.03 addr 3 uhidev2: iclass 3/0, 33 report ids uhid3 at uhidev2 reportid 16: input=6, output=6, feature=0 uhid4 at uhidev2 reportid 17: input=19, output=19, feature=0 uhid5 at uhidev2 reportid 32: input=14, output=14, feature=0 uhid6 at uhidev2 reportid 33: input=31, output=31, feature=0 uhidev3 at uhub2 port 4 configuration 1 interface 0 "Metadot - Das Keyboard Das Keyboard" rev 2.00/1.00 addr 4 uhidev3: iclass 3/1 ukbd1 at uhidev3: 8 variable keys, 6 key codes uhidev4 at uhub2 port 4 configuration 1 interface 1 "Metadot - Das Keyboard Das Keyboard" rev 2.00/1.00 addr 4 uhidev4: iclass 3/0, 3 report ids uhid7 at uhidev4 reportid 1: input=0, output=0, feature=7 uhid8 at uhidev4 reportid 2: input=1, output=0, feature=0 uhid9 at uhidev4 reportid 3: input=3, output=0, feature=0
The uhid(4) devices are the ones you are looking for. In my case the devices uhid8 and uhid9 are relevant because there is no driver attached to these devices. And these devices provide HID descriptors of the type input.
On a fresh installation of OpenBSD you will find only four uhid(4) devices in
$ ls /dev/uhid* /dev/uhid0 /dev/uhid1 /dev/uhid2 /dev/uhid3
If your dmesg(8) shows more uhid(4) devices than are available in /dev you will
have to create the extra devices manually. Those devices are only accessible if
a matching device file exists in
$ cd /dev $ for i in $(jot -ns " " - 4 9) ; do > doas ./MAKEDEV uhid$i > done $
The OpenBSD tool usbhidctl(1) is able to read and display the data it receives from uhid(4) devices. The tool will try to translate the received report descriptors into human readable strings.
I use script(1) to collect the output of usbhidctl(1) in a file:
$ script -c "doas usbhidctl -l -f /dev/uhid9" usbkeys.txt Script started, output file is usbkeys.txt doas (email@example.com) password:
You should define an order to press the keys. The translation doesn’t always give you meaningful names for each key you press. And the amount of data you get for each keypress/keyrelease event can be bigger than you might expect.
When you are done pressing keys you can quit script(1) with ^C. The next step is to filter out the relevant information. Use grep(1) for this task:
^CScript done, output file is usbkeys.txt $ grep =1 usbkeys.txt Consumer_Control.Mute=1 Consumer_Control.Scan_Previous_Track=1 Consumer_Control.Play/Pause=1 Consumer_Control.Scan_Next_Track=1 Consumer_Control.Volume_Decrement=1 Consumer_Control.Volume_Increment=1 $
Lucky me, Das Keyboard gives me proper names for the keys I’ve pressed. That must not be the case with all the keyboards out there. My former keyboard Logitech K800 produced some weird output.
You can use the captured data to prepare the config file for usbhidaction(1).
$ grep =1 usbkeys.txt | sed 's/_Control//;s/\./:/;s/=/\ /' > usbhidaction.conf $ cat usbhidaction.conf Consumer:Mute 1 Consumer:Scan_Previous_Track 1 Consumer:Play/Pause 1 Consumer:Scan_Next_Track 1 Consumer:Volume_Decrement 1 Consumer:Volume_Increment 1
Now you can the command to execute for each key as a separate line below the key. You can also insert comments beginning with a #. When you have finished the file should look similar to mine:
# Das Keyboard 4 Ultimate Consumer:Mute 1 mixerctl outputs.master.mute=toggle Consumer:Scan_Previous_Track 1 echo "playlist-prev" > /tmp/mpvctl Consumer:Play/Pause 1 echo "keypress p" > /tmp/mpvctl Consumer:Scan_Next_Track 1 echo "playlist-next" > /tmp/mpvctl Consumer:Volume_Decrement 1 mixerctl outputs.master=-8 Consumer:Volume_Increment 1 mixerctl outputs.master=+8
To test your configuration you can start usbhidaction(1) manually:
$ doas usbhidaction -c /etc/usbhidaction.conf -f /dev/uhid9
At the time of writing this, there is no rc.d(8) script for usbhidaction(1) yet. You can use this one:
#!/bin/ksh # # $OpenBSD: extrakeys.md,v 1.2 2018/08/05 12:10:43 bruno Exp $ daemon="/usr/bin/usbhidaction" . /etc/rc.d/rc.subr rc_cmd $1
Save the above lines to
/etc/rc.d/usbhidaction and run the following commands:
$ doas chmod 555 /etc/rc.d/usbhidaction $ doas rcctl enable usbhidaction $ doas rcctl set usbhidaction flags -c /etc/usbhidaction.conf -f /dev/uhid9
That’s it, folks!
>>|don’t work for me
OpenBSD provides a central volume control with mixerctl(1).
But there is no central control for
>>|. If you like it or
not, you have to find a way to send the right commands to your favorite media
I use mpv as my swiss army knife for multimedia files. It has
the ability to connect to a FIFO (aka named pipe) and accept simple text strings
as commands from it. You can see the commands above in my
Next, I need a way to create the FIFO automatically when I log in. For this I
add the following line to
[[ -p /tmp/mpvctl ]] || mkfifo /tmp/mpvctl
As a last step I a add the following line to
Whenever I press
>>| usbhidaction(1) will write the matching
command to the FIFO and if mpv is running, it will react on it.