Keyboards, mouses, touchscreens, trackballs, keyboards, etc. Those are
all input devices. What happens when you connects stuff to your machine?
How does UNIX handle those?
This is what we are going to discuss today. Today, we have two guests:
z3bra and sshbio. Let's hope we understand the input devices on UNIX.
I am venam and you are listenning to the nixers podcast.
Let's start where everything starts: in the TTY.
# In the TTY
In the TTY there is not much to interact with other than text, and the
only viable input is the keyboard, typing text. Our first guess is that
those are raw keyboard inputs, it seems like that at first: everything
will be hardcoded in the kernel, just at glance in the source code of for
example Linux kernel, there is a mapping of the keys written directly
into it. And then you may guess that we need to recompile the kernel
to get the appropriate mapping to configure the keys the way you want to.
However, that is just partly true. You can do the same in userland
using the init process: the ID 1; for instance rc.conf or systemd.
""" If you change the keyboard translation with this process, it will
propagate the keyboard layout to all its children. That is why it looks
like everything is using this layout. """
... so, configuration of the init process. Or you can also use other
ways that may be specific to your operating system like locals, or you
can temporarily set the custom map using the command `loadkeys`
The command `loadkeys` in fact modifies the console keyboard driver
translation table of the kernel. Thus, it modifies how the kernel
understands all the keys that is sent to it. Thus, you can see that it
is not really hardcoded, but translated.
This topic of translation - how the input devices and events are
understood - will be talked a lot this podcast.
At every single level there is a certain way of understanding input
devices, the related events, and how to handle them.
A little note on here. I am not so sure of it, but it is plausible
that handling of input was really hardcoded in the kernel in the firsts
versions of UNIX, because most operating system, UNIX-like, pre-1980
were tight to a single hardware platform. It makes sense. But I am
not sure of it.
We said that in the TTY, all that matters is text. However, it does not
means that the mouse is excluded. There is a piece of software called the
"GPM": General Purpose Mouse which is surprisingly a cursor in the TTY.
It gives the ability to move a little block cursor on the screen which
you can use to select and copy text. And it is quite nifty and useful,
so I urge you to check it out! And, I did not check the lower level
implementation and how it transtlates it and understands it at the TTY
level, but that is an exercise that I leave to the listener.
So, overall, other than the keyboard and mice there are not many input
devices that makes sense to use in the TTY. Maybe there are somes that -
too - makes sense, but they are probably considered as mices or keyboards.
Now, let's remember that on UNIX everything is a file, and the TTY does
not magically gets the input from the hardware and understands them.
It has to use some sort of ways to get those values, and does not speaks
hardware language. What seems to us like a hardcoded value is in fact
interpreted events received where the TTY sits: At higher level.
# Low level and /dev/
What we are going to discuss now is what is happening at this lower level.
The lowest level consists of the /dev/ directory.
Let's refresh our mind about what it is, and what is the role of the
/dev/ directory.
""" What is /dev/ and what is it used for?
Under UNIX operating systems there is a /dev/ directory available in
the root that is used to hold, to contain all the devices plugged in
the computer, and provides an interface to these devices.
It is a virtual interface to any hardware that is connected to this
machine. It might be for example USB devices, keyboard, mouses,
headphones, external WiFi cards, or printers, or whatever: Everything
that is plugged in the computer is represented in this directory.
And as on UNIX everything is a file, they are represented as files in
this directory. """
Maybe the listenner will better understand with a little example:
""" In early unix days, when OSS was still the sound device, you could
just play random music by just dumping the content of a file to /dev/dsp,
and it would magically produce sound. """
To understand the /dev/ directory, we must go through its history,
and this is what we are going to go through now. Yay, /dev/ directory!
""" So, let's move on to the /dev/ directory... How does it work and
how is it populated and what is in there.
At first, the /dev/ directory was statically populated, so whenever you
plugged in a device, you had to manually create the file corresponding
to your device, using the `mknod` command.
For example, whenever you plugged in a device - for example USB keyboard,
you had to run `mknod * a magic set of parameters *` to finally be able to
access your file. It was really tedious, and really boring; so a new
filesystem came up, mdevfs - mdev filesystem - which would be mounted
on /dev/ and create all possible devices that could be plugged in the
computer. So your /dev/ directory contained everything that could be
plugged in, so you had a huge load in this directory. So whenever you
plugged in a new device, you could easily just mount your device because
the file was already created and it was instantly accessible.
The problem with this method is that everything was created, there
was no way to know what was plugged in and what was not. So this was
really tedious. """
So that is where the device manager enters. So what is the relation
with the device manager?
The device manager was introduced because - as z3bra said - it was very
tedious otherwise, but also because of other problems.
For example when devices are connected, they are mapped to a file in
/dev/ indeed. Now what if it is for example a printer and the script
map it as printer 1; then suddenly the printer disconnect and another
printer is connected. This new printer is mapped as printer number 1,
because the script only maps to the next number. What will happen to
the current printing process that was printing to printer 1. Will it
suddenly start printing on this new printer? Well... That is a big issue.
There are a lot of annoying edge cases.
The answer to all the conflicts like on the example of an action that
was ongoing, and is interrupted is the device manager. That is its role,
and its function.
What do we know on the different devices manager on the different most
popular UNIX-like operating systems?
Let's start with FreeBSD. On FreeBSD - for example - the device manager
is called NewBus. On Linux, as it is a kernel driver, there can be many
implementations, and we will talk about them in more depth in a bit.
Unfortunately, I could not find the name of other devices manager and
I could not find information about other BSDs.
However, one big difference between BSDs and Linux is that the way the
device manager maps devices is handled differently: On a BSD, they are
handled and configured at the kernel level, and on Linux, on the contrary,
they are handled at user space by a kernel driver.
The input events also need to be handled, and not necessarily by the
device manger. But it gives rise to a concept called an input event
interface. And the input event interface's role is generalized raw input.
It does that by abstracting the way the kernel communicates through the
help of a specific driver, for the related hardware input component.
So for example you could have a specific driver for a specific keyboard.
""" In order for this to work, uevents are sent from an API which
is set at the kernel level. So what is a device driver in the end?
It is a component that interfaces between the kernel generic view and a
representation in the filesystem. In the case of Linux that is it and
that is why it is said that everything is a file.
So it is something that will translate how the hardware works to an
interface that can be used by the kernel, so it is really an API in
the end.
"""
So for instance - on both Linux and BSD - the handling of USB events is
handled an usbhid driver, which stands for USB Human Interface Device,
which is the implementation of the protocol USB input devices use.
Let's talk a bit about Linux. The input driver exposes the input
events inside the user space. It is not hidden at the kernel level.
Maybe this design is a bit more flexible... depends on the way you see it.
And this is done through an fdev - an event device manager - which is
simply a role that a device manager takes by mapping new imput devices
under /dev/input/event with a little number at the end which recognise
which device it is. And if you listen at this file, you will notice
binary data going through, some sort of stream. Which is in fact a
C structure of strict format called input_events. And it is a well
documneted format that any other program can listen to and read from it
to know what input devices are doing and sending as events using this API.
We can find that flexibility on other areas. You can add action rules
and policies on input devices interactions. Sorts of triggers sent to
and from the kernel when something is connected, disconnected, etc.
The rules can be anything. They can be related to the device block,
to the time, anythnig literally. It can trigger scripts or commands, etc.
On Linux, those rules are specifically in /lib/udev/rules, or
/lib/<whatever your device manager is>/rules, because remember that on
linux, it is a kernel driver, not directly part of the kernel, and you
can have whatever device manager you want.
On FreeBSD, as it is the only BSD I could find good documentation about
the subject, you might think that you would not have much chice because
it a kernel based, but they use something called devd, device daemon.
And the configurations rules of devd and /etc/devd.conf have some rules to
those found on Linux. Thus you can find events attach, detach, notify,
nomatch, etc. Now for this devd to work on FreeBSD, you have to start
the daemon in your rc.conf, the init script of FreeBSD. So now the devd
listen for thekernel events on trigger.
Let's mention on Linux you can also do this trigger at the kernel level:
""" The Linux kernel also hade an hotplug interface where it would let
the user space register program to be run whenever a device was hotplug.
This is something that appeared in kernel version 2.3 if I remember
correctly. So you could for example a path to a file to run for
example /prog/sys/kernel/hotplug, and whenever a device was connected,
a device would run this command, execute this command. So it was a
simpler way... not really simpler, but an useful interface to let the
user run a command whenever a device was plugged, and device manager were
implemented that way so they did not have to be run all the time like a
daemon, but were called a device was plugged and would just create the
file in /dev/ and then quit. It would be a bit simpler than what udev
does all the rules and such, but it was another interface and I think
it is worth mentionning it. """
So both Linux and FreeBSD offer this sort of flexibility on trigger.
Again, if you find other info on other BSDs, please, notify me.
NB: Most input devices are characers devices.
We know there are many devices manager on Linux, but what is the deal
with them, what are the differences, why does someone use one and not
the other.
""" As of today I think it is a political choice, because for example
you have udev which is taking commands with systemd so if you run an OS
or at least a Linux distribution that is not based on systemd you need
to find a new device mananger, so Gentoo is maintaing eudev, which is
a fork of udev before it got merged into systemd.
There is also mdev, which is the device manager for busybox, which you
might use for embedded devices where you want for example keep your user
space as small as possible, so having a devices manager integrated into
the busybox binary could be useful in this case. Also if I remember
correctly mbev for busybox is using the hotplug mechanism from the kernel.
And there is also smdev which stands for suckless mdev, which is roughly
like busybox device manager, but is just a simple implementation that
can be run in any system.
So the choice is just up to the user, depending on what he likes and
what he wants to turn its system into. """
Let's sum-up about devices managers. The dig difference between Linux
and BSD is that on Linux the device manager runs on the user space,
and on BSD it runs on kernel space. It dynamically creates and remove
devices files, that is its main role, and it provides them with consistent
naming convention. It gives API to get programs to get events from
devices, and it can have a set of rules and policies regarding those
devices interaction.
Now, let's review some useful debugging commands for input devices.
On Linux because of the special /proc/ directory you can get info from
all the devices from the /proc/bus/input/devices file. You get almost
the same output on FreeBSD using camcontrol.
There is also the lsusb command on Linux which list all the usb devices.
The equivalent on FreeBSD is usbconfig. On both operating systems
you can use the command for kernel debugging, dmesg (debug message).
It will list all the triggers and events the kernel gets on input devices
connected and disconnected.
So this is all about the raw level of input devices.
The events are interperted and they do not really make sense if they
are not interpreted in a graphical environment. And that is where we
have to move now, because if we have a touchscreen or joystick, these
are input devices and they does not make sense when they are not use in
a graphical environment.
The graphical environment is a layer above the kernel and the device
manager. The input are also handled at that level, and this is what we
are going to discuss... Hooh-yah!
There are two kinds of graphical environments or display servers: X11
and Wayland. Wayland being a simple protocol definition, it does not
include any specs for handling input events. It is the role of the
compositor, implementing the protocol to do so.
To manage that, they build a sort of library called libinput which is
a workarand that takes into consideration the legacy of X11. It is an
abstraction of the input event handling that X11 has, it is a generic Xorg
input library. No need to mention that X11 handles the events itself.
Thus, libinput and X11 have the same handling of events.
X11 has a backend that listen for new events, on FreeBSD it listens to
devd, and on linux it listen on the input device manager implementation,
any of the one z3bra previously mentionned.
Once it gets an event, it checks if there is an X driver for it and
handles the event depending on that driver's configuration. So how does
that event handling happen on X11.
""" There are plenty of input devices, but most of them has no meaning
outside of a graphical environment: their configuration has no meaning
outside of it like a touchpad: A touchpad only takes its true meaning
if it is inside of X, or something that can have graphical interface
abilities: The sensitivity, acceleration, how the mouse will move,
what do the buttons do, gestures, etc. And the same for touchscreen,
joystick, keyboard mappings, etc.
So the graphical environment handles them with drivers specific fo
each device category, or through the device directly: A driver - or an
extension - for joystick, one for mouse, one for keyboard, etc.
And all configuration can be done at the same level. Libinput and
X11 has the same configurations fortunately: They are configured at
/usr/share/X11/xorg.conf.d or through utilities specific to each driver.
If you configure it through the file you need to restart the graphical
environment for it to take effect, it you use a command line utility
you won't have to. That is the interest. """
I have one example: with the joystick, by default when you install the
driver for it, it takes, it moves the arrows on the joystick, it takes
them as if it was a mouse input: it moves the mouse. You have to edit
the file, and then it does not directly takes effect. You have to
login/logout and restart X environment.
""" Yes, it makes sense. Only editing the file will not make any change
anything as the file is only loaded when X starts. """
""" Example of some useful commands are: `xset`, `xinput`. You may know
xset to configure fonts. Then for testing xinput you can use `xev`. """
Weird and akward stories:
Multiseats systems, where you use xinput, when you have a core keyboard,
and then you can have two core keyboards, and both of them are valid, and
you can have two mouse, and they are mapped as two pointers on the screen.
That is just kind of fun.
Bluetooth input devices:
As I have read and found out, some bluetooth are mapped in the HID,
Human Interface Device, and this is like the interface that is usually
used for USB input devices, like keyboards, mices etc., so bluetooth
maps to HID and then it is used as an input device.
But as I have read and found out, some Apple devices have some proprietary
stuff that you will not just connect through the bluetooth: we will
have to map it to HID, they are directly mapped as an input device,
which is nifty. I did not try it as I do not have an Apple product,
but I guess that is cool.
""" I tried to install Linux on my father's iMac but the only thing
which was not working was the bluetooth mouse... So ok. """
On a more serious note, Mac kernel being based on an UNIX kernel it does
offer some input device management. It shares most of its kernel part
with Darwin, and by reading the official documentation we can understand
that also like other BSDs, has a kernel-based implementation of the
input devices management. It has true plug-and-plays, dynamic devices
management, as in hot-plugging, and power management for both desktops
and portables.
It is also said that it will directly support most of the thing that
you plug to their machine that follows their standard specifications,
but that for other devices you need a driver. So if you connect the
bluetooth mouse, it will work directly. Sort of like as they said
"true" plug and play. It is understandable as Apple ships its own
hardware and peripherarls with its OS.
""" I am still struggling trying to change the layout of my mice, so...
"""
""" These programmable keyboard are not like changing mappings inside
the operating system: it directly changes key codes it sends to the
operating system. It may be quite a mess to figure out: "Ok, I'm
sending this key to my os, and I must be sure the os have the correct
layout an I must be sure my keyboard has the correct layout as well,
so I do not know how people do custom layout for these. """
Acessibility input. Input for peoples, persons that have issues.
What can we say about those on Linux.
""" This is a part that is truely important because some people need to
use a computer but might not be able to use the typical input or output
devices, so the screen or a mouse, so it is importand that the kernel is
able to accept devices that will help these people to use a computer.
It is usually turned out as user space, so there will be software that
will read the screen or what you are highlighting, for example. Or read
out loud what you are typing so this is for example software like orca,
which will read out everything that is typed on the screen or selected
with the mouse, etc. so people can use a computer even if they can't
see the screen, so that is really impressive to see.
I know there is also braille characters for the terminal, there are the
characters and such, but I must say I have no idea how it works. """
""" I just know they are very expensive. """
Well I did read a little story about that, about a blind dude that
was trying to install linux from scratch, and he had to debug the boot
process. And inside the boot process there are no output, nothing to
help, no braille, no nothing. So he had to just, I do not know... read
the what the output could look like from a forum, on another machine,
to figure out what to do. But I know that inside the TTY itself, there
is braille support. As he said on the story it took him like two years
to just install Linux, which is quite a lot!
There are even full desktop environments, that focus on audio only.
You can speak to the machine and the machine reads back the text from
the screen. So instead of reading you can listen. This is great for
blind people to interact with their UNIX box. And you could even take
some part of that idea...
""" It can be used as an interface with IRC, as an example: each time
someone mention its nickname, to have the message spoken out loud.
I think it is Sacha Chua who did this with emacs. So devices for disabled
people can also help people without disabilities. """
Security tip about access controll on devices so if you want to give
a user access to an input device, keep in mind that also the memory is
mapped as a device. So if you give the user access to all devices it
will also give access to the memory. And the root user also access the
memory, the same memory. He might be able to get root access, and that
is a security hole on your system.
""" Nowadays, you might have a box without any device connected,
excepted if you use a device which has everything plugged in directly.
We plug in hardware to devices all the time, it might be your mice,
your external hard drive, your phone, your headphones... There might
be a lot of devices so it is important how to know at least basically
how it is handled, becouse it will help you troubleshoot if there ever
is an issue. I had multiple times an issue plugging my USB devices that
at first did not show up in /dev/, I just realized that my usb connector
was not plugged in my motherboard.
So how to debug things and where to find information is important,
at least, and I think it might help other people as well. """
If I wanted to add something, like just a little thing, is that when you
know like this architecture, it gives you an idea of a good architecture
of the delegation of rules: like the kernel only does what it is supposed
to do, and then to the kernel, it does no matter what to do with the
graphical environment. Which is not the same as in other operating
systems that do handle the events and the graphical and everything in
one place.
So this is all about input devices on UNIX. A big thanks to our guests,
z3bra and sshbio. If you want to join them, to contact them, you can
check their website: z3bra is on z3bra.org "On IRC directly, or by
email" and sshbio is on josuah.net "I use emails". And you can contact
both by email directly: z3bra's email is willy at mailoo, and sshbio's
is mail at josuah dot net. And you can also join us on the nixers irc
as usual on #unix at unix.chat.
Now let's review last week and talk a bit about what we did this week.
Last week we talked about X11, Wayland, Xlib, Mir, XCB, etc., and what
they all mean and details. And if you do not know the differences between
them, what everything does, I urge you to have a look at this episode,
it was pretty dynamic I guess.
Now this week: what did you do guys?
""" I have been working on a small C project called sink that is supposed
to synchronise files between multiple nodes by comparing hash of files
and timestamps. And it was pretty interesting because I had to fiddle
with hashes and TCP connections again, which is pretty interesting.
Also it feels good to get into programming again. So yeah I did that
mostly this week. """
""" I just, really just got started with C, and I am at the early
beginning of what malloc does, and that is a good to learn C as it is
everywhere on UNIX and a system without anythin will at least have C.
And I got a mechanical keyboard too. It is an Atreus, not very famous.
It is not a split one, there are very few keys, made by technomancy,
the guy who did Leningen. """
Personally, I started reading a book by , it is the Author of 'The
Cathedral and The Bazaar', so it is a well known guy. It is a book called
'The art of UNIX programming', so it is sort of like the philosophy behind
UNIX programming and the history. A lot of funny stuff. And... Yeah
I have also got 4th place at the evoke 2016 ASCII art competition. It is sort
of a demo scene compo sort of thing. It was pretty fun.
So that is about it about this episode. I hope you got the big grasp
about input devices on UNIX.
As usual, if you like what you are listenning to you can contribute in
multiple ways:
The first easy way is to give your appreciation on IRC or on the forums
extended podcast threads. It gives us a push to know we are going to
the right direction.
The second way to contribute is by adding some relevant information on
those extended threads.
A third way would be help me fill the transcript on some episode that
are missing some
And the last way would be joining me on the podcast, by asking for a
podcast key on IRC, and with that key you can login on the user interface
on podcast.nixers.net. On this interface you set your available time for
the next week and the best time, the best common time is chosen and you
can join at that time.
And remember that you can all the episodes on this little short link:
podcast.nixers.net/what.
I wish you a wonderful day and thanks for listening.
This was venam for the nixers podcast.