Category Archives: Uncategorized

My Summer Sabbatical from Open Source and Volunteerism

tl;dr open source vacation

I’ve always enjoyed being part of communities. Whether it’s in software, the Ubuntu community, the Puppet community, the OpenStack community, etc. Or whether it’s outside of software, doing volunteer work for the US Forest Service or my son’s scout group. While I enjoy these activities and consider them to also be hobbies, they are massive time sinks and that time has to come from somewhere. I have the unfortunate personal habit of signing up for more work than I can or should do at the expense of other activities. I don’t want to call it burn-out but it does cause me to be frustrated, which I’ve noticed I’ve become more and more. So I’ve decide that I want to enjoy my summer to it’s fullest extent, so to that end I announced that I was detaching from opensource/volunteer work for the summer.

I’ve gotten a bunch of questions already so here goes:

Q: Why?
A: See Above

Q: Why announce it?
A: Because it makes it easier for me to say “no” to something and people won’t wonder where I disappeared to.

Q: Do you still like us?
A: Yes.

Q: Will you still be on IRC/mailing lists etc.
A: Yes, this is still my full time job. I will be online and available during normal work hours. I will probably stop my IRC bouncer.

Q: Will you still be pushing commits to opensource stuff?
A: Yes, for my day job.

Q: Okay so what won’t you be doing?
A: I won’t be on IRC 24/7. I probably won’t be replying to emails on the operators mailing list. I won’t be pushing stuff to osops. I won’t be doing any packaging work. I won’t be on my laptop every evening working on stuff.

Q: So what will you be doing?
A: Riding bikes with my wife & kids. Hiking and camping. Working on beer recipes. Trying new breweries. Cleaning my basement. Sitting on my patio. In other words, like a normal person, work during work hours, don’t work during non-work hours.

Announcing a Gopher Client for Ubuntu Touch

I’ve been wanting to work on an app for Ubuntu Touch for awhile now and so I finally started on it this weekend. I’ve really been swayed by all the arguments about not re-inventing things that have gone on around Ubuntu Touch, so that got me thinking that we really need a gopher client.¬†After all gopher is “faster and more efficient and more organized” than the web, and we could all use more organization.

So with that in mind, here are the first screenshots from my Gopher client:

gopher

Right now this is a very early release. I am still fighting with getting rcs setup locally so I’m not quite ready to share it, but when it’s up, I’ll host a uuencoded tarball on my compuserve page.

I hope that 0.2 will add more features, including:

  1. Veronica search built into the dash
  2. Support for more modern themes, including Green on Black and Yellow on Blue.
  3. EBCDIC support (IBM phones only)
  4. Automated image to ASCII graphics conversion

Once this app is finished, I plan on dealing with the lack of the twitter app. I really don’t understand the issue here, we’ve had the finger protocol since 1977 and it works fine, other than the awkward discussions it can lead to.

 

Tagged

Copenhagen Elevators

Producing the best product in the least amount of time with the right amount of resources is all about efficiency. Here in Copenhagen I heard someone say today to be careful about making sure that nobody was blocked, that you helped anyone who needed help. The reason why this is important is that most projects will cascade a block downstream ending in a much larger delay than the original issue. For example, if you are waiting for the system architect to finish specifying an API, you’re blocked (as the implementer), but so is anyone who relies on your code or the QA team who tests it. There are many ways to solve these situations, mocks, fakes, etc. For example, when doing UI layout, I used to stick in a “FPO image” that was the right size so we could put the elements around it. On the command-line side, I used to just have my API return fake data until I could implement each feature. There are hundreds of other solutions. The goal was for me to implement the minimum so that everyone else could get started on their job and eliminate myself as the project bottleneck.

A great example of efficiency is what our hotel in Copenhagen has done with the elevators, with what I presume is an elevator scheduler. There is no up or down button, instead you enter what floor you want to go to. In theory, this allows the elevator to more efficiently schedule its trips. If there are people going to 10 different floors, say 3-7 and 21-25, it can send two elevators and the latter will be an express right to 21. With information gathered over days and months and data input about room usage, the elevators could stage themselves efficiently as well, up high in the mornings and in the lobby in the afternoon.

The elevator key pad asks for your room number.

The elevators also only hold about six people, so instead of two large elevators, they use several smaller ones. If you have people going to a bunch of different floors they get split up into different elevators. After you enter your floor it tells you which elevator, you should wait in front of, this avoids you having to look around for which elevator to use. Then to improve efficiency more, it pre-selects your floor; when you enter the elevator your floor button has already been “pushed”. This is especially helpful in a crowded elevator in an international hotel when calling out “Seis, por favor” may not be understood by the person near the buttons.

Elevators were a major problem at the Oakland UDS where in the morning and evening there was large delays of up to 20 minutes to get on one. My roommate and I gave up on taking the elevator later in the week and ended up taking the stairs. When UDS starts up next week we’ll see how these keep up, but I’m hopeful they’ll work out.

So what does this have to do with code? Other than pondering how one might write an elevator scheduler and feed usage patterns back in for more efficient routing, the real point of this post was me just thinking about efficiency. When you’re working on a project, you should take a brief moment to consider who you are blocking and how you can solve that. More than likely, if you spend ten minutes to help someone who is stuck, the payoff for your project will be hours or more once the downstream effects are realized. You don’t want to be the elevators at the Oakland UDS, you want to be the elevators at the Copenhagen UDS.

EDIT: Since I’ve not done any research on this, does anyone know if the elevators really are using an intelligent scheduler? If you do, please comment.

Tagged , ,

How Does udev Know What’s a Keyboard or Mouse?

Last week, I found myself having to dive into the udev code to figure out how it determines whether what is a mouse or a keyboard. To solve the problem I was working on, I ended up having to replicate some of that logic in python, which is posted at the bottom. Let me explain how it works.

Device Info in /sys

To start, let’s look in /sys and see what input devices we have. If you look in /sys/class/input on your system, you’ll see many symlinks to devices. I’ll pick /sys/class/input/event12 to look at in more detail, so cd to event12/device

mfisch@caprica:/sys/class/input/event12/device$ ls -al
total 0
drwxr-xr-x 7 root root 0 Jul 8 16:05 .
drwxr-xr-x 3 root root 0 Jul 8 16:05 ..
drwxr-xr-x 2 root root 0 Jul 8 16:05 capabilities
lrwxrwxrwx 1 root root 0 Jul 8 20:50 device -> ../../../serio1
drwxr-xr-x 3 root root 0 Jul 8 16:05 event12
drwxr-xr-x 2 root root 0 Jul 8 16:05 id
-r--r--r-- 1 root root 4096 Jul 8 20:50 modalias
drwxr-xr-x 3 root root 0 Jul 8 16:05 mouse0
-r--r--r-- 1 root root 4096 Jul 8 16:05 name
-r--r--r-- 1 root root 4096 Jul 8 20:50 phys
drwxr-xr-x 2 root root 0 Jul 8 20:50 power
-r--r--r-- 1 root root 4096 Jul 8 20:50 properties
lrwxrwxrwx 1 root root 0 Jul 8 16:05 subsystem -> ../../../../../../class/input
-rw-r--r-- 1 root root 4096 Jul 8 16:05 uevent
-r--r--r-- 1 root root 4096 Jul 8 20:50 uniq

There are some interesting things in here, but the two I’m interested in are “name” and the “capabilities” directory. Let’s look at name first.

mfisch@caprica:/sys/class/input/event12/device$ cat name
PS/2 Generic Mouse

Using Capabilities

Okay, so this looks like a mouse, but udev doesn’t use the name to figure this out, it uses the capabilities directory. Let’s look there:

mfisch@caprica:/sys/class/input/event12/device/capabilities$ ls -al
total 0
drwxr-xr-x 2 root root 0 Jul 8 16:05 .
drwxr-xr-x 6 root root 0 Jul 8 16:05 ..
-r--r--r-- 1 root root 4096 Jul 8 16:05 abs
-r--r--r-- 1 root root 4096 Jul 8 16:05 ev
-r--r--r-- 1 root root 4096 Jul 8 20:43 ff
-r--r--r-- 1 root root 4096 Jul 8 16:05 key
-r--r--r-- 1 root root 4096 Jul 8 20:39 led
-r--r--r-- 1 root root 4096 Jul 8 20:43 msc
-r--r--r-- 1 root root 4096 Jul 8 16:05 rel
-r--r--r-- 1 root root 4096 Jul 8 20:43 snd
-r--r--r-- 1 root root 4096 Jul 8 16:05 sw

The aptly named capabilities provide information to udev on what “capabilities” the device has. udev is specifically interested in the following ones: abs (Absolute axes), ev (Event types), key (Keys and Buttons), and rel (Relative axes). Let’s examine one of these to determine what data it contains:

mfisch@caprica:/sys/class/input/event12/device/capabilities$ cat ev
7

So what does 7 mean? This is a bitmask (111) who’s bits are defined in /usr/include/linux/input.h. That file has bits defined for each of the types listed in the capabilities directory, the #define prefix matches the name in the capabilities directory, so we’re looking at EV_ (Note: key is represented by defines KEY_ and BTN_, since it’s for keys and buttons).

Since this mask is 0x7 or 111, we have bits 0, 1, and 2 set and the rest are false. Judging from the #defines, the following bits are set for this device:

#define EV_SYN 0x00
#define EV_KEY 0x01
#define EV_REL 0x02

This tells us that our device gets key events, relative movement event, and synchronization events. (Figuring this out required poking around the header a bit more).

A Quick Note About the ‘key’ Capability

The entry ‘key’ is much longer than ev and requires more explanation. Let’s look at what the ‘key’ capabilities shows for my keyboard:

20000 20000000020 0 0 500f02100002 3803078f900d401 feffffdfffefffff fffffffffffffffe

So that’s much larger than ev was. It’s still a bitmask, but it’s been split into words, using the word-size sense, so 8 bytes on my system. Since this mask is little endian, the ‘20000’ represents the highest set bits. This makes processing need to take place in word-size chunks, starting at the right. Another way to think of the output above is to think about it as one large mask, as long as you pad each “word” to be 16 digits, for example, what you really see above is this:

00000000000200000000020000000020000000000000000000000000000000000000500f02100002 03803078f900d401feffffdfffeffffffffffffffffffffe

To solve my problem, I split the output up on the spaces and set 64-bits at a time in my mask starting from the right-most word.

Now that we’ve read all these bitmasks, we need to do something with it.

What udev Does with this Info

If you look at the udev source code, specifically udev/udev-builtin-input_id.c, you can see how this data is used.

For mice, the code is fairly straightforward, look at the code for the test_pointers function. We really want to know where they set “is_mouse”. The code is also looking for other stuff like touchpads, so let’s ignore that. It basically boils down to this:

if EV_REL and REL_X and REL_Y and BTN_MOUSE:
you have a mouse

There’s also a similar block where you can replace REL above with ABS, which the comment claims is for VMWare’s USB mouse, but I kept it in my solution because I didn’t quite trust the comment and it seemed harmless otherwise.

For keyboards, the code is a bit more complex because it’s basically checking to see if you have a bunch of keys defined, this code is in the function test_key. then test_key looks for a keyboard it boils down to this:

If any bits are set in 'ev' and
if bits 1-31 (but not 0) are set:
you have a keyboard

Note: bits 1-31 represent the Escape key, numbers, and Q through D.

Putting it All Together

So now that we know how it works, let’s see it in action! Here it is run on my dev box:

mfisch@caprica:~/tmp/find_input$ ./find_input.py
INFO:root:/dev/input/event3 is a keyboard (AT Translated Set 2 keyboard)
INFO:root:/dev/input/event12 is a mouse (PS/2 Generic Mouse)

Here it is run on another system with more devices attached:

INFO:root: /dev/input/event3 is a keyboard (AT Translated Set 2 keyboard)
INFO:root: /dev/input/event13 is a mouse (PS/2 Generic Mouse)
INFO:root: /dev/input/event15 is a keyboard (BTC USB Keyboard)
INFO:root: /dev/input/event16 is a mouse (Primax HP Wireless Laser Mini Mouse)

My python code including unit tests! is avaialble in bzr at lp:~mfisch/+junk/find_input

Comments, bugs, and fixes all gladly accepted.

Tagged , , ,

Forcing lightdm to Use a Specific Resolution

This morning I was debugging a problem in unity-greeter and I suspected that it might be related to the resolution of the system I was using. Since I was live booting it was a pain to make changes, mainly because I didn’t have all my standard tools (or web access). I ended up messing around with xorg.conf files for awhile, without much success (this reminded me of college, but not pleasantly). After some other searches, I ended up settling on this method:

For this example, I wanted a resolution of 1024×600.

  1. Login to my system
  2. Open a terminal and run cvt 1024 600
  3. Copy the resulting output, minus ModeLine portion
  4. mfisch@caprica:~$ cvt 1024 600
    # 1024x600 59.85 Hz (CVT) hsync: 37.35 kHz; pclk: 49.00 MHz
    Modeline "1024x600_60.00"   49.00  1024 1072 1168 1312  600 603 613 624 -hsync +vsync
    
  5. Run xrandr –newmode
  6. mfisch@caprica:~$ xrandr --newmode "1024x600_60.00"   49.00  1024 1072 1168 1312  600 603 613 624 -hsync +vsync
    
  7. Run xrandr –addmode LVDS 1024x600_60.00. (Note that there are several displays that xrandr shows, I wanted to change my main laptop display, LVDS, you may want to change another. Run xrandr without arguments to see all the displays.)
  8. Run xrandr –output LVDS –mode 1024x600_60.00
  9. If that switches your resolution and looks right, then lets make it permanent.
  10. Edit: /etc/lightdm/lightdm.conf, add this line (note you can choose a different path:
  11. display-setup-script=/usr/bin/lightdmxrandr
  12. Make a new file called /usr/bin/lightdmxrandr, make it a shell script that just executes lines 4, 5, and 6 from above
  13. #!/bin/sh
    xrandr --newmode "1024x600_60.00"   49.00  1024 1072 1168 1312  600 603 613 624 -hsync +vsync
    xrandr --addmode LVDS 1024x600_60.00
    xrandr --output LVDS --mode 1024x600_60.00
    
  14. Make /usr/bin/lightdmxrandr executable, logout, and restart lightdm (sudo initctl restart lighthdm)
  15. Enjoy your new resolution!

Here are the two links that helped me piece this together:

How change display resolution settings using xrandr
How can I make xrandr customization permanent?

Tagged , ,

Locales and Building Packages

A couple weeks ago I participated in the Ubuntu Global Jam/Bug Fix session. I started by looking at all the “fails to build from source” aka ftbfs list. I read through the list and found a few interesting packages, but ended up working on live-manual, because I use live-build and also it seems odd that we can’t build a user-manual.

At first I was confused, because I pulled the source and ran dpkg-buildpackage on it and it worked fine on my amd64 box. So I tried an i386 VM that I had running, works fine there too! Next, the litmus test, a build in a pbuilder chroot. Guess what, that one failed. I traced the errors back to this one error when building the German user manual:

ERROR occurred, message:”invalid byte sequence in US-ASCII”

It was odd, why are we processing a German user manual file using a US ASCII locale?

I compared the environment between my system, where it built, and the pbuilder chroot, where it failed and found that inside a pbuilder chroot, the LC_ALL variable is set to “C”. C is equivalent of US-ASCII. After trying in vain to change the locale to something that understands utf-8, I realized that I needed to install a locale that could handle UTF-8 inside my pbuilder chroot.

debian/control:
-Build-Depends: debhelper (>= 8), ruby, libnokogiri-ruby
+Build-Depends: debhelper (>= 8), ruby, libnokogiri-ruby, language-pack-en

debian/rules:

%:
– dh ${@}
+ LC_ALL=en_US.UTF-8 dh ${@}

Now the build was working, so I submitted my merge proposal.

My fix was accepted but discussions revealed that the fix wouldn’t work in debian because their locale packages are different. With that in mind, I worked on a more generic fix, based on what python-djvulibre does. After some tweaking (not shown in the merge proposal), I settled on this fix:

debian/rules:

+override_dh_auto_build:
+ mkdir -p debian/tmp/locale/
+ localedef -f UTF-8 -i en_US ./debian/tmp/locale/en_US.UTF-8/
+ export LOCPATH=$(CURDIR)/debian/tmp/locale/ && \
+ export LC_ALL=en_US.UTF-8 && \
+ dh_auto_build

Note: During the development of that fix, I had trouble finding all the different steps in the debhelper build and what I could override. A debian developer pointed me to this great presentation which answered a lot of questions: Joey Hess’ Not Your Grandpa’s Debhelper.

So there are two ways to solve a locale issue during a build. Do you know of any others? If so I’d love to hear them in the comments.

Tagged , , ,