Custom display resolutions in QEMU

04.05.2013 19:19

QEMU emulates a VESA-compliant VGA card that supports a static set of standard and a-bit-less-standard display resolutions. However, this set is far from universal and for example doesn't include the wide-screen 1600x900 resolution on my laptop. This means that running a virtualized OS full-screen would always stretch the display somewhat and give a blurry image.

Here's how I fixed that. Following instructions should pretty much work for adding an arbitrary resolution to QEMU's virtualized graphics card (but only when using -vga std). They are based on this patch.

Fetch QEMU source (I used 1.4.0) and edit roms/vgabios/vbetables-gen.c. For instance, to add 1600x900 I applied this patch:

--- qemu-1.4.0.orig/roms/vgabios/vbetables-gen.c	2013-02-16 00:09:22.000000000 +0100
+++ qemu-1.4.0/roms/vgabios/vbetables-gen.c	2013-05-04 11:46:55.000000000 +0200
@@ -76,6 +76,9 @@
 { 2560, 1600, 16                     , 0x18a},
 { 2560, 1600, 24                     , 0x18b},
 { 2560, 1600, 32                     , 0x18c},
+{ 1600,  900, 16                     , 0x18d},
+{ 1600,  900, 24                     , 0x18e},
+{ 1600,  900, 32                     , 0x18f},
 { 0, },
 };

Now re-build the VGA BIOS binary image (apt-get install bcc first):

$ cd roms/vgabios
$ make stdvga-bios

QEMU's make install will not install the image you just built. Instead, it will use an already built binary they ship with the source. Therefore you have to install it manually:

$ cp VGABIOS-lgpl-latest.stdvga.bin $PREFIX/share/qemu/vgabios-stdvga.bin

Of course, replace $PREFIX with the prefix you used when installing QEMU (/usr/local by default). Now when you start a virtualized OS you should see the resolution you added to vbetables-gen.c (for example as reported by xrandr or under Screen resolution in Windows).

Posted by Tomaž | Categories: Code | Comments »

Multilib weirdness

13.04.2013 21:41

Multilib is a mechanism in GCC for handling multiple binary versions of a single library that have been compiled using different compiler options. This is useful for instance when compiler options affect the ABI and the linker has to choose the correct library version to link your program with. ARM architecture with its multitude of ABIs and floating point unit options is a prime example where this comes in handy.

Multilib works by mapping compiler command-line options to directories where libraries can be found. For instance, GCC compiled with my fork of summon-arm-toolchain says this about its multilib support:

$ arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard

What this says is that binaries compiled with -mthumb will be linked with libraries that appear under thumb/ and binaries with -mfloat-abi=hard will use libraries under fpu/ relative to the usual library search path.

However:

$ arm-none-eabi-gcc -print-multi-directory -mthumb
thumb
$ arm-none-eabi-gcc -print-multi-directory -mfloat-abi=hard
.

While thumb option seems to work as expected, the hardware-float libraries don't appear to be used. Why is that?

It turns out that multilib is somewhat smarter than what the documentation and -print-multi-lib would lead you to believe. It doesn't just check the options that you give GCC explicitly on the command line but also their default values.

It seems that -print-multi-lib assumes built-in default values for these options. It believes that fpu/ versions have been compiled using ARM, not thumb mode. But since -marm is default, it doesn't print it out explicitly.

However, this GCC has been compiled using --with-mode=thumb, which changes the default to -mthumb:

$ arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/home/avian/local/libexec/gcc/arm-none-eabi/4.6.3/lto-wrapper
Target: arm-none-eabi
Configured with: ../gcc-4.6.3/configure --target=arm-none-eabi
--prefix=/home/avian/local --enable-interwork --enable-multilib --with-newlib
--disable-shared --with-gnu-as --with-gnu-ld --disable-nls --disable-werror
--with-system-zlib --with-arch=armv7-m --with-mode=thumb --with-float=soft
Thread model: single
gcc version 4.6.3 (GCC)

Multilib is smart enough to know that libraries under fpu/ won't work with code compiled with -mthumb and falls back to the default directory and hopes for the best. So, to get the compiler to use libraries under fpu/, you have to explicitly set it to ARM mode:

$ arm-none-eabi-gcc -print-multi-directory -marm -mfloat-abi=hard
fpu

By the way, the combinations of options and directory names printed out by -print-multi-lib are set using MULTILIB_OPTIONS and friends in gcc/config/arm/t-arm-elf in the GCC source tree.

Posted by Tomaž | Categories: Code | Comments »

Blinken Kindle

21.03.2013 21:50

Kindle 3 has a two-color LED in the power button. With original software, you can see it glow briefly when you slide the button or when the battery is charging. A Kindle running Debian of course allows many more interesting possibilities.

The two-color LED is actually composed of two separate LEDs that are controlled separately: an amber and a green one.

The amber LED is lit when the battery is charging. Currently it is not clear to me how exactly it is controlled, but it seems to involve both the hardware-controlled charger LED pin of the MC13892 power management IC and a software-controlled GPIO. The relevant code starts at line 929 in arcotg_udc.c. Note that pmic_green_led_disable() function forces the MC13892 pin state (which as I understand actually affects the amber LED, not the green one).

In any case, there doesn't seem to be any user-space interface available for controlling this LED. It's turned off by default.

The green LED is much easier to control. It's connected directly to one of the signaling LED drivers on the MC13892 and there's a convenient, if somewhat weird interface for those in sysfs. Relevant code is in pmic_light.c.

All operations are made through the /sys/devices/platform/pmic_light.1/lit file. You can write statements in the form of "command value" to this file to control the LED drivers. Supported commands are:

  • ch - select channel on which subsequent commands will operate. Kindle's LED uses channel 4, so before issuing any other commands, always write ch 4. Better not touch other channels.
  • cur - set LED current. Can be set from 0 to 7 to control LED brightness. Kindle's built-in software uses 7.
  • dc - set PWM duty-cycle. Can be set from 0 to 32. 0 means constantly off, 32 means constantly on.
  • bp - set PWM frequency. Can be set from 0 to 3. At 0, frequency is high enough for blinking to be invisible to human eye and PWM setting can be used as an additional brightness control. On higher settings, the PWM output is seen as blinking (see MC13892 datasheet for exact frequencies).
  • ra - Either 0 or 1. If set to 0, PWM duty-cycle changes are immediate. If set to 1, changes happen via a hardware generated ramp, making smooth visual transitions.

As an example, here's what I have in /etc/rc.local to turn off the green LED at boot:

echo "ch 4"	> /sys/devices/platform/pmic_light.1/lit
echo "cur 0"	> /sys/devices/platform/pmic_light.1/lit
echo "dc 0"	> /sys/devices/platform/pmic_light.1/lit
Posted by Tomaž | Categories: Code | Comments »

Standard C and embedded programming

09.03.2013 15:14

Previous week I had a few discussions with my colleagues regarding some finer details of variable types in C and how code generated by GCC behaves in various edge cases. This led me to read a few chapters of the actual C standard and research this topic a bit.

It's surprising how much of embedded C code I see on a day to day basis depends on behaviors that are implementation-specific according to the standard. The most common cases seem to be:

  • Assuming how struct and union types are stored in memory - specifically how the struct elements are aligned in memory and how assigning one element in a union type affects other elements.
  • Assuming how integer types are stored - specifically byte order when casting between pointers to differently sized integers.
  • Assuming what the storage size for enum types is.

In the world of software for personal computers, it's more or less universally agreed (at least in free software community) that these offenses are bad. They lead to unportable software and angry package maintainers that have to deal with bugs that only appear when software is compiled on certain architectures.

With embedded software the situation is less clear. First of all, embedded software is by definition more closely tied with the hardware it is running on. It's impossible to make it independent of the architecture. A large fraction of firmwares are also developed over a relatively short-term: Compared to desktop software that can be maintained over years, once a firmware image is finished it is often shipped with the physical product and never updated (even if a possibility for that exists). That means that it's unlikely that the CPU architecture or the compiler will change during the development cycle.

In embedded software you often have to deal with serialization and deserialization of types. For instance, you might be sending structures or multi-byte integers over a bus that only processes bytes at a time. Just casting char buffer pointer to a complex type at the first glance produces shorter, simpler code than doing it the standard-compliant way with arithmetic operations and assignments to individual struct fields.

But is the code really simpler? The emphasis should always be on code that is easy to read, not easy to write. When making a cast from *char to *int you silently assume that the next pair of eyes knows the endianess of the architecture you are working on.

There's also the question of crossing the fine line between implementation specific and undefined behaviors. Former depend only on the architecture (and perhaps minor compiler version) and the latter can change under your feet in more subtle ways. For instance, I have seen a few cases where results of arithmetic operations that depended on undefined behaviors would change with changes to unrelated code. That leads to heisenbugs and other such beasts you most certainly do not want near your project. Granted these usually involve more cleverness from the developer's side than the memory storage assumptions I mentioned above. In fact since these seem to be depended on so often you could say that some of the struct and union storage details are de-facto standard these days.

So what's the verdict here? I admit I'm guilty of using some of these tricks myself. In the most extreme case they can save you hundreds of lines of boiler plate code that just shuffles bytes hence and forth. And down in the lonely trenches of proprietary firmware development code reusability can be such a low concern that it doesn't matter if your code even compiles the day after the dead-line.

Before starting a project it makes sense to take a step back and set a policy depending on the predicted life-time of the code. I do think though that sticking to portable code is a must if you want to publish your work under and open source license. With the ever growing open source hardware community, sharing drivers between platforms is getting more and more common. Even with proprietary projects, I'm sure the person down the line that will be debugging your code will be happier if she didn't have to needlessly delve into specifics of the processor architecture you are using.

Posted by Tomaž | Categories: Code | Comments »

Setting up Wi-Fi on Kindle, 2

25.02.2013 20:12

In my previous post I've mentioned that Kindle's AR6002 wireless chip set seems to work fine with the configuration tools that come with Debian.

Such setup however has an annoying problem. The wireless interface doesn't see packets addressed to the MAC broadcast address (even in promiscuous mode with tcpdump). This means that the kernel on Kindle won't see things like ARP requests (but will see ARP replies) and pings of the broadcast IP. The former means that IP connections initiated from other machines on the network mostly won't work, unless these machines already have Kindle's MAC address in their ARP cache. You can work around that by adding a manual entry for Kindle in the ARP cache or making Kindle establish a connection first, but these are ugly workarounds.

It turns out that the AR6002 driver that was shipped by Kindle kind of implements standard Linux wireless extensions, but not really. Kindle OS uses a modified wpa_supplicant that uses some kind of a proprietary ioctl interface to talk to the kernel module and using that the broadcasts work correctly.

Since WPA supplicant comes under the BSD license, Amazon didn't feel the need to provide the source to the modified version in their GPL-compliance package (aren't permissive licenses great?). Hence I've again lifted the binaries from the Kindle OS image and created another Debian package, similar to the firmware-ar6002 I mentioned in the last post.

The wpasupplicant-ar6002 package is available here and of course will only install on the armel architecture. It uses a bit of dpkg-divert and shell scripting magic to transparently add a ar6000 driver to wpa_supplicant. This means that you can simply use the wpa-driver directive in the interfaces and the system will use Amazon's patched binary instead of the one shipped with Debian.

The full /etc/network/interfaces snippet for Kindle's wireless network now looks like this:

auto wlan0
iface wlan0 inet static
        pre-up wmiconfig -i wlan0 --power maxperf

        address xxx.xxx.xxx.xxx
        netmask xxx.xxx.xxx.xxx
        gateway xxx.xxx.xxx.xxx

        wpa-driver ar6000
        wpa-ssid xxx
        wpa-psk xxx
Posted by Tomaž | Categories: Code | Comments »

Setting up Wi-Fi on Kindle

08.02.2013 18:30

Setting up wireless LAN under Debian was a bit tricky. Kindle 3 has a Atheros AR6002-series chipset and Amazon ships an ar6000 kernel module for it. However simply loading this module doesn't work. User space needs to do a complicated firmware setup procedure before a standard wlan0 network device appears.

Atheros AR6102G on Amazon Kindle 3 motherboard.

On a stock Kindle OS, firmware and the kernel module is loaded by /opt/ar6k/host/support/loadAR6000.sh that is invoked from /etc/init.d/wifi. This script in turn depends on two binary executables (bmiloader, eeprom.AR6002) and quite a few binary firmware files. For my new Debian system, I've shuffled things around a bit - I've made a new, LSB-compliant init script and moved files from /opt/ar6k to /usr/share/firmware-ar6002. The scripts themselves I left mostly unmodified, except for commenting out parts that were communicating with other parts of the (now absent) Kindle framework.

There's also a wmiconfig utility that allows you to set a lot of hardware-specific settings once the driver and firmware has been loaded.

For the rest of the wireless network setup, the stock Debian ifupdown framework seems to work just fine. This is what I have in /etc/network/interfaces at the moment:

auto wlan0
iface wlan0 inet static
	pre-up wmiconfig -i wlan0 --power maxperf

	address xxx.xxx.xxx.xxx
	netmask xxx.xxx.xxx.xxx
	gateway xxx.xxx.xxx.xxx

	wpa-ssid xxx
	wpa-psk xxx

The wmiconfig part comes from the Openmoko Wiki where it says that it makes networking more reliable (looks like at the expense of power consumption). Although I didn't see it make any noticeable difference.

I have seen a weird problem though where sometimes the Kindle won't see ARP broadcasts when another machine on the network tries to establish a connection to it. If that happens, tcpdump on Kindle doesn't show ARP request packets even when a sniffer on another machine on the same wireless network does see them. Other connections work normally however and if I manually add an ARP table entry on the connecting machine, it can connect to the Kindle without problems. So this doesn't look like a power management problem.

For anyone interested in running Debian on their Kindle like this, I've made the firmware-ar6002 package available here. It will install on armel architecture only and assumes that modprobe can load the ar6000 kernel module (module itself is not included).

Finally, a note about licensing might be appropriate here. This package contains scripts and binaries that were lifted from the read-only root partition that Amazon ships with Kindles. All of them seem to come from Atheros' SDK (see Openmoko SVN for example) and that code appears to be under GPL 2. However, Amazon doesn't include sources for these utilities on their source code page. It might be that Amazon got this code under some proprietary license from Atheros. There are certainly no apparent notices regarding that.

I'm going to assume nobody will be too angry if I publish this Debian package, but if you want to redistribute it, know that it's at best a legal gray area.

Posted by Tomaž | Categories: Code | Comments »

MXC serial port timeout

05.02.2013 14:01

Playing with my Debian-running Kindle over the serial console (because I don't have networking running natively yet under Debian) exposed one interesting feature. The serial port would stop responding if it was left idle (no traffic in or out) for a few tens of seconds. By accident I found out that sliding the power button restores it back to normal operation, however the reason for this was a mystery until I looked into the Linux kernel source.

Kindle uses a NXP MX35-series CPU. The serial port /dev/ttymxc0 is provided by the mxc_uart driver, which is compiled into the kernel image shipped by Amazon. Inspecting the source (drivers/serial/mxc_uart.c in the Linux kernel tree) shows that the driver implements a power-saving feature that powers down the peripheral and disables its clock if there is no activity for 30 seconds.

This clock gating feature is enabled by default, but luckily you can disable it through the sysfs on a per-UART basis. I now have the following line in the /etc/rc.local file and the serial console remains available even if left idle for a while:

echo 0 > /sys/devices/platform/mxcintuart.0/uart_clk_state
Posted by Tomaž | Categories: Code | Comments »

Booting Kindle 3

02.02.2013 19:17

It seems I'm bound to hacking various ARM-based devices these days. I've been using a kindly donated Kindle 3 with a broken screen for a few months now as kind of sandbox machine. It's always nice to have a few systems on-line one can log into from various unfashionable corners of the Internet for bouncing connections or for running a service on a whim. A Debian-running Kindle is especially nice for an always-on machine, since it consumes very little power.

So far I've been running the Kindle with a stock system, only jailbroken and with the usbnet hack installed. I installed a basic, 1.5 GB Debian chroot into the FAT partition on Kindle's flash and had a ssh daemon running on the wireless LAN interface. While it's still quite useful, that's only a part of the 4 GB of built-in storage and the daemons running in the stock system consume a lot of RAM. Plus, they sometimes mess with the hardware in ways I don't like. For instance, the wireless LAN connection usually drops when USB power goes away. Obviously the way to go was to run Debian natively.

Before I could install Debian onto the flash drive directly, I had to find out how the Kindle actually boots and what facilities are there to recover in case something goes wrong.

Kindle 3 with an RS232 adapter

As seems to be the standard on Linux-running ARMs, the first visible thing that happens is U-boot. It's stored in boot flash memory that is mapped into CPU's address space (this flash is different from the built-in MMC drive that the operating system uses).

If you press a key on the serial console at the Hit any key to stop autoboot prompt, you get a simple command line. It allows you to inspect memory, load code or data via the serial port into RAM or flash and boot a kernel that is present somewhere in the address space. There seem to also be some facility for tftp network booting, but without a wired Ethernet adapter on board it appears useless. Although U-boot can also include functionality for accessing the MMC drive, version on my Kindle has that disabled.

If you don't want to mess with the boot flash (I don't want to for now), the only thing that you can do from U-boot is to boot the Linux kernel. Kernel and an initrd image are also stored in the boot flash and hence directly accessible in the ARM address space.

The initrd image contains some recovery utilities that can be accessed by pressing Enter at the Press [ENTER] for recovery menu... prompt. Since these run directly from the initrd, they work even if the MMC drive is completely corrupted. The most useful is option 3 from the recovery menu. It exports the MMC drive as an USB mass storage device, which can then be used to setup the root filesystem from another computer (with friendly still alive... messages periodically being sent to the serial line).

Menu
====
3. Load MMC0 over USB storage
4. Erase MMC0
I. Initialize Partition Table (fdisk) and format FAT
O. Format and overwrite FAT partition
E. Export FAT partition
U. Update using update*.bin file on FAT partition
M. Update using update*.bin file on FAT partition of second MMC port
D. dmesg / kernel printk ring buffer.
Q. quit 

Oh, and option 3 requires a password, which is the well-known fiona + four (not three as for the root password) hex digits of the MD5 digest of the serial number.

If you don't enter the recovery menu, the code in initrd mounts the root filesystem and executes /sbin/init. From there on things proceed as usual in a normal Linux system. Kernel parameters stored in U-boot set the root filesystem as the first partition on the built-in MMC drive.


This boot process seems to be completely compatible with an armel Debian Squeeze install. One snag I did encounter is that the root partition needs to have at least /dev/console and /dev/null special files. Other device files are created at boot time by udev, but without these two, I get a tried-to-kill-init kernel panic at boot. Also, it helps to double-check /etc/fstab and /etc/inittab, since debootstrap doesn't set these up for you. Root filesystem is /dev/mmcblk0p1. If you want to be able to log-in from the serial console, a line like this works in the inittab:

mxc0:2345:respawn:/sbin/getty -L 115200 ttymxc0

The original Kindle comes with a MBR-style partition table on the MMC drive (here it's called /dev/sdd since I was inspecting it from another computer - on Kindle it's /dev/mmcblk0):

Disk /dev/sdd: 4001 MB, 4001366016 bytes
4 heads, 16 sectors/track, 122112 cylinders, total 7815168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdd1   *        7688     1338943      665628   83  Linux
/dev/sdd2         1338944     1388095       24576   83  Linux
/dev/sdd3         1388096     1404479        8192   83  Linux
/dev/sdd4         1404480     7815167     3205344    b  W95 FAT32

sdd1 is the root partition for the stock Kindle OS with an ext3 filesystem. sdd2 contains another ext3 filesystem with some kind of configuration and log storage. sdd3 is empty and was all zeros on this Kindle. sdd4 contains the storage that is visible when you attach an un-modified Kindle to a computer. It contains another MBR partition table with a single, FAT32-formatted partition.

I removed all of these and just created a single ext3 partition over the complete drive. At boot this causes some scary messages from the initrd code which seems to attempt some sanity checks on the partition table and checks for possible system updates in the FAT32 partition. Apparently it tries to correct the situation, but luckily gives up without modifying the partition table before starting Debian's init process.

While I now have a basic Debian installation running directly on the Kindle, there are still things missing. For instance, I still have to get wireless LAN to work again and there are some oddities with power management which I hope to cover in another one of these posts. All in all, Kindle turned out to be much more hacker-friendly than the Chromebook, which is surprising considering that in contrast to the evil Kindle the former has been advertised as being developer friendly.

Posted by Tomaž | Categories: Code | Comments »

Tilt-wheel actions on Firefox 17

04.12.2012 13:06

Starting with version 17, Firefox has a new set of preferences for mouse wheel actions. Unfortunately, this change makes it impossible to directly define "back in history" and "forward in history" actions for tilting the scroll wheel on tilt-wheel mice (something that used to be possible by setting mousewheel.horizscroll.withnokey.action=2 in about:config)

I use tilt-wheel mice almost exclusively and this is the only modern feature since the addition of the vertical scroll wheel on the middle button that I have been able to tolerate on mice. I just hate those new models that put buttons everywhere. But using the tilt-wheel for moving backwards and forwards in browser's history soon became second nature and now it's just annoying to be left without this feature.

Here's a quick workaround for this regression in Mozilla's software I found. Add the following to ~/.Xmodmap:

pointer = 1 2 3 4 5 8 9 0 0

This remaps pointer buttons 6 and 7 (horizontal scroll) to mouse buttons 8 and 9. Buttons 8 and 9 seem to be used by default in Firefox as shortcuts for back and forward buttons, so this solution doesn't require any additional poking around about:config. Of course, this also affects all other applications, so now you won't be able to use the tilt-wheel for horizontal scrolling.

Log-out and back in for the change to take effect or run xmodmap ~/.Xmodmap.

By the way, loading the .Xmodmap file in your home directory automatically when you log-in is not a given. GNOME display manager 3 on Debian seems to do it. Yours might not. If it doesn't work (you can check current button mappings with xmodmap -pp), check around /etc/X11/Xsession or /etc/gdm/Xsession.

Also, xmodmap seems to be deprecated in favor of setxkbmap, but I don't see any way of mapping pointer buttons with that.

Posted by Tomaž | Categories: Code | Comments »

Rainbow plots

03.12.2012 18:57

In the most simple mode of operation, VESNA with the spectrum sensing expansion is basically a very slow, slightly inaccurate but also a very small and cheap spectrum analyzer. The FCD scanner application exploits that and displays the spectrum in the traditional waterfall plot or a plain spectrogram.

Because of limited bandwidth the receiver can only see a small part of the spectrum at once and operates as a swept-spectrum analyzer. This means that it's essentially blind at most frequencies most of the time. If a device is transmitting individual packets with a lot of quiet time in between it is very probable that its transmission will only be picked up after several frequency sweeps, as it must happen by chance that VESNA's receiver will be listening at the same frequency as the transmitted packet.

FCD scanner waterfall spectrogram plot.

The waterfall plot shows this nicely, for instance above for wireless LAN beacons - these are transmitted in regular intervals with a bandwidth much wider than resolution bandwidth, hence giving a distinct moiré pattern.

However, waterfall plots aren't particularly convenient to estimate the power of the signal or it's bandwidth since the power is displayed in color. On the other hand just plotting power versus frequency doesn't show you information about past sweeps.

Active FMT triggered by frequency change of a WLAN signal

Rohde & Schwarz has this really nice persistence display mode on their high-end spectrum analyzers that shows signal's history in color and power and frequency on the spatial axes. What they do is basically show you a two-dimensional histogram of power and frequency pairs (more detailed description is in their white paper).

This is all great, but their hardware can do hundreds of thousands of Fourier transforms per second, meaning they fill up the histogram in an instant. Directly copying this method to FCD scanner is quite useless, as VESNA gives you a sweep per second or less. This means it takes unreasonably long to accumulate enough history to build any kind of a useful histogram. Here's for instance how the histogram looks like for a history of 10 sweeps:

FCD scanner old persistence spectrum plot.

I did however come up with a method that manages to produce results that are pretty close to the histogram method, but actually works with significantly less data. Here's how it looks like:

FCD scanner new rainbow persistence plot.

The outline of the wireless LAN network is nicely visible, as well as some other packet transmissions on the higher frequencies.

It works by sorting all power measurements at each frequency from the highest to the lowest, placing them on a power versus frequency plot and then filling the space between the samples with colors from a colormap. The colors are evenly distributed between the samples, with the median value given the highest value (i.e. brightest color) and both extremes given the lowest one. This gives you one vertical line and the whole plot is constructed by repeating this procedure for all frequencies in a sweep.

This display mode is now available using the --rainbow-plot option in fcd_scanner. Check the source for exact details of the implementation - the rainbowplot() is just 28 lines of code using matplotlib.

Posted by Tomaž | Categories: Code | Comments »

GNU linker and ELF program header

14.11.2012 12:15

Here's a little annoyance I've been trying to fix.

Most of the time we are using a custom bootloader on VESNA. On the VESNA's STM32F1 microcontroller the flash ROM starts at the address 0x8000000 and the bootloader takes the first 0x12800 bytes of it. At CPU reset the bootloader does some housekeeping tasks, possibly reprogramming some sections of the flash ROM, and then transfers control to the application code that lives above 0x8012800.

When linking application code using GNU linker, we are using the following script:

MEMORY
{
	rom (rx) : ORIGIN = 0x08012800, LENGTH = 512K - 0x12800
	ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}

INCLUDE libopencm3_stm32f1.ld

This produces a working binary (using objdump -Obinary) when it's loaded at 0x8012800 by our bootloader.

However, sometimes it's convenient to skip the application reprogramming through the bootloader (which is slow for unrelated reasons) and program the application code directly through JTAG using openocd. Strangely enough this corrupts the bootloader, even though the linker MEMORY definition above only specifies the application area of the ROM.

Looking closely at the ELF file produced by the linker, I noticed the program headers:

Program Header:
0x70000001 off    0x0000e4cc vaddr 0x0801e4cc paddr 0x0801e4cc align 2**2
         filesz 0x000000e8 memsz 0x000000e8 flags r--
    LOAD off    0x00000000 vaddr 0x08010000 paddr 0x08010000 align 2**15
         filesz 0x0000e5b4 memsz 0x0000e5b4 flags r-x
    LOAD off    0x00010000 vaddr 0x20000000 paddr 0x0801e5b8 align 2**15
         filesz 0x000009b4 memsz 0x00000bc0 flags rw-
private flags = 5000002: [Version5 EABI] [has entry point]

For some reason GNU linker insists on aligning program segments on a 32 kB boundary. Therefore it aligns the segment containing the application code at 0x8010000, which is 0x2800 bytes inside the bootloader territory. Since the code still has to start at 0x8012800, it pads the start of the segment and this padding overwrites a part of the bootloader when it's loaded into flash ROM by openocd.

Why does it do that? I have no idea. There also doesn't seem to be any option to adjust the alignment (flash ROM in this microcontroller has 512 byte pages, so it would make more sense to align the segments to those).

The simplest solution I've found is to simply dump the plain binary with objdump and use that instead of the ELF file with openocd. But that's ugly, because then you have to repeat the segment offset in the openocd script.

Posted by Tomaž | Categories: Code | Comments »

Remote Wireshark recipe

05.11.2012 17:03

Recently I've been trying to debug some SSL connection problems on remote machines. While tcpdump in an console-only ssh sesion usually does the trick for me, this time I really needed the user-friendliness of filters and SSL decryption features in Wireshark. I really didn't want to install Wireshark on a head-less server and do X11 forwarding, so I used tcpdump to do the actual capture on the server and forwarded the stream through a pipe and an ssh connection to Wireshark on my laptop.

Here's the recipe, mostly for my record and in case someone else might find it useful. I had problems with other recipes I found, since they either use dumpcap, which I don't have on the remote, or make it hard to start the packet capture command through sudo.

On remote machine:

$ mkfifo foo
$ sudo tcpdump not port 22 -U -w - >foo

(just pointing -w to a pipe won't work)

On the local machine:

$ wireshark -k -i <(ssh example.com cat foo)
Posted by Tomaž | Categories: Code | Comments »

Capture 0.0.5

05.10.2012 18:21

There's a new version of the capture code available from the am433 distribution. This version allows you to disable modulation auto-detection using the -M command-line argument and has a more robust detection of plain binary encoded packets.

In case you don't know what I'm talking about: capture tool is a part of my am433 project. It takes a low-frequency digital signal (say, with a 48000 Hz sampling rate or there-about), chops it into individual packets and applies some heuristics to determine the packet modulation type. You can think of it as a box that takes a continuous stream on one end and returns decoded packets and some meta-data on the other end. Optionally you can plug it into libpcap and your favorite packet dissector.

Screenshot of capture and Audacity

It was originally meant to decode the digitalized baseband data from my simple 433 MHz AM receiver. However it turned out quite useful for other applications as well. For example, it can be used with GNU Radio to decode transmissions on various frequency bands and modulations, as long as we are talking about devices that communicate infrequently with small packets (EnergyCount 3000 is one such case). With a proper receiver hardware it can even be used to decode infrared transmissions.

It can currently get data from an ALSA device or a file. You can also point it to a named pipe, which is currently the easiest way of using it from GNU Radio. It would be great though if someone would wrap it in a proper GNU Radio block.

Posted by Tomaž | Categories: Code | Comments »

Leaky librrd4

17.09.2012 21:21

librrd4, the library behind the RRDtool, version 1.4.3 as shipped in the current Debian Stable distribution (Squeeze) has a gross memory leak. This caused problems on my server because I use a long running daemon process to plot several graphs (not a script that periodically gets called from a cron job, which seems to be the dominant way of using RRDtool these days) and because I use the RRDs Perl bindings, which dynamically link to librrd4 (as opposed to RRDp which spawns a separate process).

The red dots on the graph below show the virtual memory size of a Perl process that continuously calls the RRDs::graph() function in librrd4 1.4.3:

Comparing memory usage between two versions of librrd4

The blue dots mark the same test using librrd4 1.4.7 which is currently in Debian Testing and which apparently has this problem fixed. While librrd4 1.4.7 doesn't seem to be present in Debian Backports, the source package from Testing compiles without a problem on Squeeze, so upgrading is pretty straightforward.

Just in case all of the above saves debugging time for someone...

Posted by Tomaž | Categories: Code | Comments »

Brute forcing IR remote

09.09.2012 19:24

I have an old Sony CMT-CP11 Hi-Fi that drives a pair of speakers in my living room. I use it to listen to the radio, CDs and everything sound-related my desktop computer outputs. If I remember correctly it will soon be 12 years old and it has aged incredibly well. I've only opened it up once, to make a backup battery hack so that I don't need to reprogram the radio stations each time power goes out.

It has one annoyance though. While it has two auxiliary audio inputs, it only allows switching to them by pressing a button on the front panel. Otherwise most other functions can only be activated from the infra-red remote control. That's unfortunate because it's preventing me from having a script on my desktop that sets everything up automatically when I want to listen to the audio from the computer on the Hi-Fi speakers.

I was thinking that maybe the Hi-Fi component actually implements a command for switching on the auxiliary input but whoever designed the remote control ran out of buttons or something like that. A bit of searching on the web quickly turned out a description of the physical protocol and a collection of codes used by Sony equipment.

After recording and inspecting the codes transmitted by my remote control it turned out that most buttons produce the 12-bit variant of the code with a few buttons using 20-bit codes. While the codes matched their functions as recorded at the site linked above, unfortunately none of the codes listed there for switching on the auxiliary inputs produced any response on my Hi-Fi.

Perhaps it is using some code that is not listed? 12 bits make for 4096 possible codes. That's not outside of reach of a brute force search: with 5 seconds per try that comes to around 6 hours. I chose a 5 second delay because for input switching that's how long it takes between a command is sent and the audio output actually appears on the speakers (plus some error margin).

Of course, I didn't want to spend 6 hours in front of the Hi-Fi, listening whether the correct output is playing. Therefore I hacked up a simple automatic detector. I made the computer connected to the auxiliary input play a continuous 600 Hz tone (using simply Audacity Generate -> Tone function and looped playback). On the other end a laptop running the IR code brute forcing had its line input connected to the headphones output and detected the tone.

Brute force search for IR codes on a Sony CMT-CP11

Not wanting to lose too much time with filters or anything fancy, I simply took a Fourier transform of the signal and compared the mean amplitude in the band around 600 Hz with the complete spectrum (excluding the DC component). This turned out to work well enough for this purpose, although I did get a few false positives when the radio was playing. But those were simple to filter out since they were limited to a few samples while a genuine switch would give a continuous detection:

# samples is an array of 2048 16-bit samples from ALSA
w = numpy.abs(numpy.fft.rfft(samples))

signal = w[30:32].mean()
noise = w[1:].mean()

if signal/noise > 100:
	# success! detected the 600 Hz signal ...

In the end, this exercise wasn't successful. I failed to find any 12-bit codes that would switch to the auxiliary inputs. I also tried all combinations of 20-bit codes with the 12-bit device prefixes I saw transmitted by the remote control (complete 20-bit space is a bit too much for an exhaustive search). I did find out that such brute force testing makes my (also Sony) TV go crazy, so I had to unplug it while the test was running.

I guess if I still want to be lazy and not get up to press the button the only solution left would be to hack together something that would press the button for me. Like a microcontroller that would hook up to the IR receiver in the Hi-Fi, recognize the code that isn't recognized by the Hi-Fi itself, and simulate a pressed key. On the second thought, while it might be a fun hack, I don't think I'm lazy enough to attempt that.

Posted by Tomaž | Categories: Code | Comments »