Ying Li (cyli) wrote,
Ying Li

Woots, rotation and navigation keys work on the XO.

Now I can use the XO as an ebook reader (in tablet mode) when using Ubuntu.

I was having problems before because the rotation key on the XO, as well as the directional keypad (see this image, although the rotation key is labeled as "backlight control" for some reason). xev didn't even register anything when I hit the keys (oddly enough it did register the gamepad buttons). I knew that that the kernel recognized the key presses, since od /dev/input/event3 register events when the directional pad keys and rotation button (and any other key on the keyboard) is pressed. However, thanks to waba.be's tutorial, I got it working.

Getting X to see the keys

Basically, I used tail -f /var/log/kern.log to get the number (?) of the unknown keys (it on my machine it was 65-69). Then I did dumpkeys --keys-only to figure out which keycodes were free, and I mapped those keys to keycodes 120-124 using setkeycode <key number> <keycode>. I put the setkeycode commands in /etc/init.d/olpckeys-setup.sh:

# rockerpad up
setkeycodes 65 120

# rockerpad right
setkeycodes 68 121

# rockerpad down
setkeycodes 66 122

# rockerpad left
setkeycodes 67 123

# rotate button
setkeycodes 69 124
and ran update-rc.d olpckeys-setup.sh start 99 2 3 4 5 . (Apparently this is the recommended way in Ubuntu to set up startup scripts?)

So yay, xev recognizes the keys (although oddly enough the keycodes given it gives are not in the 120-124 range - I guess X uses a different set of keycodes?) , which means that I can use wiki.laptop.org's instructions to bind that button to my rotate script (more later) using xbindkeys.

Getting rotate to work

I want to remap the directional pads every time the screen rotates, because I don't want to have to mentally translate up to right when the screen rotates 90 degrees. waba.be suggests key mappings are most easily done with xmodmap. The script given in by wiki.laptop.org simply rotates the screen so you have to change the it so that it remaps those keys as well as rotates.

I haven't figured out what I'm going to do with the game pad keys yet, so I only want to map 4 keys. I wanted to be able to map the other keys if I figured out what to do with them, but without having to do a lot of editing. So I changed the rotation script to:
# Rotates the screen 90 degrees on the olpc

import os, sys, re

# Get current screen orientation
xr = os.popen("xrandr -q").read()
m = re.search(r'\+\d\s+(.*?)\s*\(',xr)
if not m:
    raise "No match!"
rotation = m.group(1)

# Generate new orientation
# orientations:  0 is normal, 1 is left, 2 is inverted, and 3 is right
#   If we want to rotate 90 degrees we need to subtract 1, so the new
#   orientations would be [3, 0, 1, 2] (current = [0, 1, 2, 3])
new_orientations = ["right", "", "left", "inverted"]
val = new_orientations.index(rotation)
if val < 0:
    raise "xrandr output is not what's expected"

commands = ["xrandr -o %d" % val]

# Get the keycodes for the directional pad and game pad and cause them to 
# rotate as well
if len(sys.argv) > 1:
    if not os.path.isfile(sys.argv[1]):
        raise "%s either doesn't exist or isn't a regular file" % sys.argv[1]
    f = open(sys.argv[1])
    data = f.read().split("\n\n")
    for cluster_data in data:
        keycodes = []
        keysyms = []
        for line in cluster_data.split("\n"):
            if line.strip() and not line.startswith("#"):
                kc, ks = line.split("=", 1)
        for i in range(len(keycodes)):
            commands.append('xmodmap -e "keycode %s = %s"' % ( 
                    keycodes[i], keysyms[(i-val) % len(keycodes)]))

os.system("; ".join(commands))
Not the most elegant or robust script, but meh, it works and it makes changing key mappings easy. It takes a single configuration file, which is passed to it on the command line. The configuration file simply maps clusters of keys to their keysyms/values. I found the values by running xev and pressing the normal keyboard directional keys. Mine configuration file, for instance, is:
139 = Left 
134 = Up
210 = Right
209 = Down
If I wanted to later add mappings for the game pad keys, I just need to throw in a few extra empty lines (yes, my cluster of keys are determined by white space. blah blah...) and then put the keys values for them in. So for example:
139 = Left 
134 = Up
210 = Right
209 = Down

# yay, my script ignores comments

1 = a
2 = b
3 = c
4 = d 
As you can see, I completely made up the key numbers and key values for the directional pads. If you want to map something to space, however, you will need to use the keysym (not the value " " since I ignore whitespace there).

An alternative to using my script is using the scripts at this OLPC News forum post, with key numbers and keysyms/values changed (note: I don't think KP_UP, etc. are recognized symbols in Ubuntu on the OLPC without some xkb tweaking).

Also for some reason, I have to run xbindkeys after I start xfce4 in order for anything to work. I guess I need to modify some startup file.
Tags: ubuntu olpc x11

  • I've moved

    I have a new blog. This happened a while ago, but I never announced it here because I was hoping to migrate my old posts. I suppose I can do that…

  • Shelless SSH Server with Twisted

    I needed a shelless SSH server that would not honor shell requests or exec commands, because I wanted to provide SFTP access without allowing shell…

  • XrandR on Ubuntu on the XO

    The wiki.laptop.org instructions for installing Ubuntu on the XO tell you to install Holger Levsen's backported Xorg AMD drivers. They gave me…

  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded