User SPI Adventures

Last year I started working on a project in the space that I thought would be pretty cool, a Mystery Box. I made a box out of foam board, mounted a servo as a catch. Inside I wired up an Arduino to control the servo. The Arduino connected to a Raspberry Pi over SPI, I used SPI because it was a nice simple protocol to implement on both the Arduino and the Raspbery Pi.

The Mystery Box was going to run a BBS which had control over the servo. My idea was to use the box as a simple CTF target, with the servo giving instant and substantial feedback for success.

Around this time I had been asked to port NewCWV to FreeBSD, we wanted to have more than one implementation of the proposed standard available. Doing some development in the FreeBSD kernel made me want to look at using the operating system in other places.

Up to this point I had been using Linux on the Pi in the Mystery box, but I thought it would be fun to try FreeBSD. FreeBSD on the Pi was in a reasonable state, I didn't have trouble getting the Pi to boot. When it came to controlling the Arduino over SPI I hit a snag.

There wasn't (and still isn't) user space SPI support in FreeBSD. This means that I can control devices to connected to SPI from a kernel driver, but I can't do so from user space. Kernel code is harder to write, not portable and means I can't reuse Linux code. User space code is easier to write and if the interface is similar to existing ones I can reuse a lot of other code.

I was enjoying writing the NewCWV port and I thought to myself: "I should make the world a better place and write a user space SPI layer". And that is exactly what I set out to do over the next few months.


This week, well over 9 months later I finally have a working SPI layer. I can issue, read(2), write(2) and ioctl(2) commands and see the bus burst into life with data flowing across.

On the other end of the bus I have a Trinket Pro (Adafruit arduino clone). The Trinket acts as a SPI slave, when there is activity on the bus it spits on the values from the master over UART and writes the SPI values back onto the bus with 10 added.

The Arduino seems to struggle at the default bus speed of 500KHz, but runs fine when I lower the speed with a sysctl down to 50KHz.


Speaking to the Arduino is okay, but it doesn't make a very exciting demo. I had a couple of devices that can be controlled over SPI, a SSD1306 OLED Screen and a PN532 NFC Reader .

The NFC Reader is supported by libnfc , a quick look shows that libnfc is available in the FreeBSD ports tree. I looked at the libnfc code while writing the user space layer and it seemed pretty straight forward. libnfc opens the SPI device and calls the SPI IOC MESSAGE ioctl to send spi ioc transfer structs to the driver.

The interface I have written is a little different, using an object to describe the transfer similar to the way iic(4) works. To add FreeBSD support I need to create the struct and swap the ioctl(2) call, this should be straight forward.

Using the OLED is a little different. Adafruit have provided a python library to speak to the screen using either i2c or SPI. The python library imports a module to speak to SPI and seems to mostly use read(2) to control the screen. This is going to be harder to port across and get working.

There is also an Adafruit Arduino library for the SSD1306 and Arduino compatible boards. This is C++ that has been written to run on an Arduino rather than on a unix machine. This code could probably be slimmed down, with the calls to fastspiwrite swapped out to calls to the kernel interface.


My implementation is still a little rough around the edges, the code needs to be tidied up, moved into the kernel directly and tested on the latest head. I think that getting user space code working with it will show up any bugs, it will certainly make for more meaningful test cases.

My next step is to get the NFC reader working with libnfc and the raspberry pi, then I can start work on the screen. Once I have some SPI examples working I might even get back to setting up the Mystery Box for a CTF in the space.

31c3

31c3 Finished 21 days, probably enough for me to get past the conference high, but also enough time for me to catch up on almost all of the talks. All of the talks from 31c3 and most of the other congresses have been put online at media.ccc.de .

I took notes during Congress, but I had a hard time turning them into a post. If anyone wants to see my notes I am sure they could appear. Instead here are some thoughts.

Congress is Europe's largest temporary art installation. The CCH is a simply massive building, after 5 days of wandering around the I am still not sure I saw everything. It wasn't until day 4 of Congress that I realised the floor numbers were not floor numbers, but actually the Saal you were closest to. The ones and twos I could see around me were not helpful directions.

The building was augmented by the CCC to make it a home for hackers. The lights were dimmed, there were blinkenlights in every corner and just to make things even better there seemed to be a pop up interactive installation at random intervals. A pneumatic tube system was run around the ground floor of the building.

Of course there were talks 12 hours of the day, but the talks were streamed later. There were too many things that could only be found in the 4 days of Congress to sit in a full lecture theatre.

Instead we held court at our table in the international hackerspace village. Hung around with the crazy cooks in the Food Hacking Base , argued politics in Noisy Square and wandered the cavern is a daze.

At night(due to the lighting it was hard to tell when that was) we would be at our table hacking on something super cool, or hiding in the amazing nightclub.

It is probably impossible to describe congress, there is just too much happening. It is probably unfair to try and give someone else a picture, the only real way to know what it is like is to experience it.

Join us next year.

Strange Mast

Walking home from the hackerspace last night I came across this interesting mast behind a car parked on the pavement. I had to grab a picture of this strange thing on Union Street.

The guy operating the mast spotted me taking the picture and came down for a chat. This mast was acting as a 4G base station, there was a second vehicle driving around the city, listening for this mast to map 4G propagation. It turns out that Aberdeen city council are planning to roll out 4G across the entire city, with free access. The council want to use this for fleet management and I think it is probably part of their initiative to improve bandwidth in the city.

According to the operator of this mast the 4G won't just cover the city center, they have been mapping industrial estates in Altens and out towards the edges of the Bridge of Don

urtwn on FreeBSD ARM

This weekend I got FreeBSD on my Chromebook Snow in a usable state. Getting wifi going was a bit of a bother. I have an Edimax Wifi Adapter , but the default kernel config builds out support for wifi and the urtwn device driver.

The Beaglebone Black page on the FreeBSD wiki has a kernel config that includes the drivers I need. I took the wifi config and added them to a CHROMEBOOK-WIFI config so I could build a kernel for the Chromebook with support.

#USB WiFi
# Wireless NIC cards
device          wlan            # 802.11 support
options         IEEE80211_DEBUG
device          wlan_wep        # 802.11 WEP support
device          wlan_ccmp       # 802.11 CCMP support
device          wlan_tkip       # 802.11 TKIP support
device          wlan_xauth

device          firmware        # Required to load firmware
device          urtwnfw         # Firmware for RTL driver below
device          urtwn           # Realtek RTL8188CU/RTL8192CU

After building the new kernel and moving it over to the USB stick I use for the Chromebook I needed tell FreeBSD to accept the license terms for the wifi firmware.

Add to loader.conf
legal.realtek.license_ack=1

After that it was pretty norm wifi setup.

# ifconfig wlan0 create wlandev urtwn0
# wpa_supplicant -i wlan0 -c /etc/wpa_supplicant.conf -B
# dhclient wlan0

GPGME with Mutt on OS X

I found it quite difficult to get GPGME working with Mutt in OS X, I was using Homebrew to install mutt. I could see the option in the brew build file to use GPGME, but it was set as an optional dependency. I fought with it for a while then jumped across to #homebrew on freenode to get an answer.

I had to force brew to build mutt from source to get the dependency included. You will have to uninstall mutt if you have already installed it.

brew install mutt --build-from-source --with-gpgme

You will need to add the correct bits to your .muttrc to get mutt to use.

set crypt_use_gpgme = yes
set crypt_autosign = yes
set pgp_sign_as = 0xYOURGPGKEYGOESHERE*****