Friday, July 6, 2012

elographics touchscreen setup

This is a tutorial of sorts on how to set up an elographics serial touchscreen. I don't actually have such a device but the question pops up every couple of months. Together with Tom Munro Glass and Tias Guns, we got one working properly.

Edit: 18/09/2014 - add systemd description

A bit of history first: not too long ago, the X server was talking to serial devices directly and thus had several drivers for specific input devices. The elographics X drivers is one of them. Unfortunately, due to lack of hardware we, the upstream maintainers, can only perform cursory testing of that driver. The Linux kernel however supports a large amount of serial devices too, so for this tutorial I'll explain how to use the linux kernel to talk to the device. I'll show how to set up udev rules to use inputattach and then the X.Org evdev driver, thus making the device utilise a well-tested driver that has some client-stack support not found for the X.Org elographics driver [1].

Kernel setup

USB devices are automagically detected by the kernel and it will load the right drivers. Serial devices on the other hand require some manual configuration. Elographics devices have serial kernel drivers and inputattach can be used to hook serial devices up with those kernel drivers. First we need to load the kernel module, then call inputattach with the right options for our device:
root@localhost:~> modprobe elo
root@localhost:~> inputattach -elo /dev/ttyS0 --daemon
The path to the device may need to be changed on your box. Do look up the inputattach man page, depending on your device you may need a different flag.

Once inputattach is running, the device should be visible in /proc/bus/input/devices. You can run evtest against it and see the event stream.

udev setup pre systemd

Since we don't want to run inputattach manually each time, we'll now set up udev to run this command for us. According to Tom, the elographics device does not have a pnpid, so he configured it with a fixed device path on ttyS4:
$> cat /lib/udev/rules.d/99-elographics.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS4", \
        RUN+="/sbin/modprobe elo", \
        RUN+="/sbin/inputattach -elo /dev/%k --daemon"
If a device has a pnpid, the rule can be more flexible in what ttyS* the device needs to appear on. For example, a Wacom serial tablet may have the id WACf004 so we can use the match rule below.
$> cat /lib/udev/rules.d/99-wacom-w8001.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS[0-9]*", \
        ATTRS{id}=="WACf*", \ 
        RUN+="/sbin/modprobe wacom_w8001", \
        RUN+="/sbin/inputattach -w8001 /dev/%k --daemon"
Once this rule is in place, inputattach will be started for us at boot time (of course the device needs to be connected at boot time too). The next step is to configure X to see the device.

udev setup with systemd

Newer udev (for some value of new, we're talking about Fedora 18 or so) won't let RUN start long-running processes, such processes get killed off. If you are on system with systemd you're best off setting up a systemd service file for inputattach (see also this post). In that case, your udev rule becomes
SUBSYSTEM=="tty|pnp", KERNEL=="ttyS4",  \
      RUN+="/sbin/modprobe elo", \
      TAG+="systemd", ENV{SYSTEMD_WANTS}+="elo-inputattach@%k.service"
So we tag the device for systemd and tell it to start a servirce. The %k gets replaced with the ttySx device. The matching systemd unit file looks like this:
$> cat /etc/systemd/system/elo-inputattach@.service
[Unit]
Description=inputattach for elo serial devices

[Service]
Type=simple
ExecStart=/usr/bin/inputattach -elo /dev/%I
Once both of these are in place, a reboot will initialise inputattach, and the device is available as kernel device.

X.Org configuration

X requires the udev properties ID_INPUT and one of ID_INPUT_MOUSE, ID_INPUT_TABLET, etc. to to recognise an input device. Each of those triggers the respective MatchIsPointer, MatchIsTablet, etc. directive in the xorg.conf.d snippets. On modern systems, the udev properties should be assigned automatically [2]. If that doesn't happen on your box, you can modify the above udev rules to add it manually:
$> cat /lib/udev/rules.d/99-elographics.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS4", \
        RUN+="/sbin/modprobe elo", \
        RUN+="/sbin/inputattach -elo /dev/%k --daemon", \
        ENV{ID_INPUT}="1", ENV{ID_INPUT_TOUCHSCREEN}="1"
Once this is done, the X server will pick up the device, and the default configuration [3] will assign the evdev driver to it. Restart X, and you're done.

If you require additional options, set up an xorg.conf.d snippet. There you can add any options found in evdev(4):
$> cat /etc/X11/xorg.conf.d/99-elographics.conf
Section "InputClass"
  Identifier "elographics config"
  MatchProduct "Elo Serial TouchScreen"
  Option "EmulateThirdButton" "on"
EndSection
This snippet will match any device with the product name containing "Elo Serial Touchscreen" and enable the right button emulation feature in the evdev driver. If you are unsure about the name of your device, check /proc/bus/input/devices once inputattach is running.

X.Org configuration on Red Hat Enterprise Linux (RHEL) 6.x

This section applies to derivatives as well, e.g. CentOS 6. On RHEL 6.x, we use HAL as a configuration backend. So you will need an fdi snippet to match the device up with the driver. The snippet below is the one Tom ended up using, and it also shows the Calibration option being merged.
$> cat /etc/hal/fdi/policy/10-elographics.fdi
<?xml version="1.0" encoding="ISO-8859-1"?>
<deviceinfo version="0.2">
  <device>
    <match key="info.category" contains="input">
      <match key="info.product" contains="Elo Serial TouchScreen">
        <merge key="input.x11_driver" type="string">evdev</merge>
        <!-- next line is equivalent to an xorg.conf.d statement of
                Option "Calibration "40 4000 40 4000" -->
        <merge key="input.x11_options.calibration" type="string">40 4000
40 4000</merge>
      </match>
    </match>
  </device>
</deviceinfo>
Note the "match key" statement. Apparently, this particular device does not set "input.touchscreen", so we match on just "input" instead. Not too big a deal, since we then also match on the product name.

Once this file is in place, restart haldaemon and check with lshal that the right options are assigned. Then restart X and the device should work.

Good luck!

Many thanks to Tias and Tom for proof-reading this article multiple times.

[1] for example, evdev supports dynamic recalibration with the xinput_calibrator tool
[2] check the output of udevadm info --export-db
[3] your distribution should ship /usr/share/X11/xorg.conf.d/10-evdev.conf which assigns evdev to MatchIsTablet.

[edit 22 Feb 13: fix typo in MatchProduct name]

9 comments:

timreid said...

Thank you for posting all of this information in one place. As Fedora has been changing the underpinnings of this type of connection, it has been harder and harder for me to get my elographics and accutouch serial touchscreens working correctly with each release, as all of the required information does not appear to be in a single location until now.

Again, thank you very much.

-Tim Reid

Unknown said...

In Linux Mint 11, this is not working.
In Linux Mint 13 I have succes with ELO, but one file has moved:

I do: vi /lib/udev/rules.d/99-elo.rules
and type following:


KERNEL=="ttyS0", \
RUN+="/sbin/modprobe elo", \
RUN+="/usr/bin/inputattach -elo /dev/ttyS0 --daemon"


Greetings to all ELO fans!

Unknown said...

Bart could you please explain how exactly you did on Linux Mint 13? I can get it to work.

thnx

Jopelepoop

L said...

One small correction, in this line

MatchProduct "Elo Serial Touchscreen"
should be
MatchProduct "Elo Serial TouchScreen"

the name needs to match the name you see in xtest.

Thanks for posting this info, without it I would have never gotten my touchscreen working properly on EL6

Peter Hutterer said...

L: thanks, typo fixed

Anonymous said...

A very convenient thing to add to the 99-elo.rules is :

ACTION=="add|change", ATTRS{name}=="Elo Serial TouchScreen", SYMLINK="input/elographics"

That way you always have a /dev/input/elographics link for X-configuration etc.

This came up because "my" device didn't work - at all - with a MatchDevice section in xorg.conf.d/ so I had to write an explicit InputDevice section.

Unknown said...

We found this tutorial very helpful during our transition from RHEL5 to RHEL6. Now we are moving to RHEL7, and things have changed again. Do you have any pointers as to how to get a serial ELO Touch device to work with Xorg (including calibration) given that Red Hat no longer ships the xorg-x11-drv-elographics driver, and HAL/FDI is no longer present. I can build the Xorg driver, but don't know how to get the calibration constants installed.

Peter Hutterer said...

Craig: on RHEL7 you should be able to use the normal setup with inputattach and the evdev driver, together with the evdev driver's calibration options.

Otherwise, if you want to use the xorg elographics driver just drop an xorg.conf.d snippet into /etc/X11/xorg.conf.d/ that assigns the elographics driver. xorg.conf configuration has never gone away and it's still supported, we're just trying to remove the need for it in most cases.

Unknown said...

Thanks, that's exactly what we ended up doing. The evdev driver worked fine with the /dev/input/eventX device created by invoking "inputattach -elo /dev/ttyS0"

Xorg snippet...
Section "InputClass"
Identifier "elographics config"
MatchProduct "Elo Serial TouchScreen"
Option "EmulateThirdButton" "on"
Option "InvertY" "true"
Option "IgnoreRelativeAxes" "true"
Option "Mode" "Absolute"
Option "Calibration" "50 4035 81 4009"
EndSection

Udev rule ...
KERNEL=="ttyS0", RUN+="/sbin/modprobe -bv elo", TAG+="systemd", ENV{SYSTEMD_WANTS}+="elo-inputattach@%k.service"

Systemd service file "elo-inputattach@.service"
[Unit]
Description=inputattach for ELO touchscreen compatible devices
After=display-manager.service

[Service]
Type=simple
ExecStart=/usr/bin/inputattach -elo /dev/%I
Restart=always