Wednesday, July 11, 2012

Daily tmp directory

My $HOME/tmp directory got a bit messy, especially with building test rpms or testing tarballs. My solution was to just change the directory to automatically change daily. Scripts below:
:: whot@yabbi:~> cat scripts/tmp-today 
#!/bin/bash
date=`date +%Y-%m-%d-%a`

tmpdir=$HOME/tmp/$date
tmplink=$HOME/tmp/today

if [ -e "$tmpdir" ]; then
    exit 0
fi

mkdir $tmpdir
ln -sf $tmpdir $tmplink
And the crontab entries to run this script:
0 2 * * * /home/whot/scripts/tmp-today
@reboot /home/whot/scripts/tmp-today
So run the thing at 2.00 am and on every reboot in case the box was shut off overnight. I had it on midnight first, but I think 2 am is better. If I'm still up at 2 and working, then mentally I'm still in on the day before and I don't want files to end up in different directories just because midnight clocked over. And because the laptop may be suspended overnight, we run the script on resume as well:
:: whot@yabbi:~> cat /etc/pm/sleep.d/00-tmp-dir 
#!/bin/bash

case "$1" in
 thaw|resume)
  su -c - whot /home/whot/scripts/tmp-today
  ;;
 *)
  ;;
esac
This obviously works for other directories as well, e.g. your daily download directory.

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]