I THINK ∴ I'M DANGEROUS

This is an old revision of the document!


Project: Tin

Decided I wanted a programmable pocket computer. Something that fits in a tin and runs off a battery. Something I can use to cause all sortsa mischief.

Use Cases

  • Work as an Onity Skeleton Key
  • GPS tracker (?)
  • Universal Remote Control (IR led can be drive directly via gpio)
  • rtl-sdr for use as radio receiver and transmitter (via this)
    • Being able to receive and transmit means possibly scanning for and then spoofing signals.
  • Speaker (plugs into headphone jack so it can be removed and headphones used)
  • rfID and NFC cracker (?)
  • communicate with car computers (via ELM327) to perform various tasks (clear trouble codes, possibly disable engine)
  • Voice Changer (via bluetooth mic or usb mic + audio out and sox)
  • Ethernet interception device (plug in between ethernet and device to sniff traffic)
  • Wifi AP scanner

Features

  • Battery powered
  • Works as a mobile bus pirate / bus pirate integration
  • USB and bluetooth peripheral support
  • rtl-sdr integration (?)
  • serial character display with multi-button interface
  • Compass

Hardware

Parts

Modules

Obviously, the R-pi is the main component. Along with it is the custom built add-on board that connects directly to the R-pi's main header. On the custom add-on board is:

New Plan:

MSP430 Galore!

An MSP430 will be used as to essentially implement ACPI. A lithium ion battery with support (charging) circuitry will power everything (at 3.3V). An MSP connected to the R-Pi via SPI will actuate either a mosfet or a solid-state relay to switch power on and off to the R-Pi. The R-Pi can tell the MSP to power off or a button connected to one of the MSP's GPIO pins can actuate it. The Pi can schedule a wake up time.

Assuming the MSP is not too busy, it will also act as an RTC, communication also via SPI.

The MSP also takes input from the various other buttons and sends them to the Pi via SPI.

* Power Regulation Circuit * This takes power from the 9v battery and efficiently puts out a clean 5 volts. Built using the LM2675-N-50, it has a few (annoyingly large) discrete componets, including an inductor a schotkey diode, and 3 capacitors. Test runs have shown (without any mind to power saving in software) at least 2 hours of run time on the 600 mAh rechargable 9v batteries I have. I absolutely expect this to improve as I tweak the software for power savings. * <html><iframe class=“imgur-album” width=“100%” height=“550” frameborder=“0” src=“imgur.com/a/nf46l/embed?background=ffffff&text=000000&link=4e76c9”></iframe></html> * OLED screen * This is mostly mounted here for convenience. It could (and may still) simply be mounted to the case with a few wires (Vcc, GND, SDA,SCL) running to the add-on board. * Input Devices * The 5-way switch and Two buttons </del> === USB Components === The vast majority of the interesting peripheral will be connected via USB. Internal components will be connected via a USB hub. The hub and the devices plugged into it will all be stripped of their housings and possibly coated in hot-glue or resin to prevent shorts. For testing purposes, electrical tape may be used. For power management, manual control of USB suspends will be utilized: https://www.kernel.org/doc/Documentation/usb/power-management.txt This will not be as efficient as actually cutting power to the device, but it's a good compromise between the complexity of trying to switch power on and off for each port and the flexibility of being able to do it in software. Devices will have their modules unloaded (as this will definitively mark the device as idle per Linux USB PM) and the USB port will set to aggressively keep the device suspend. When a device is needed (i.e. an rtl-sdr for when gqrx is launched) the launch script loads up the driver and forces the port to resume from suspend. == RTL-SDR == An SDR is too cool, too useful, and too cheap not to just build into the case. There are small form factor rtl-sdr based SDRs that == Sound Card == I definitely want and need a usb sound card. This is to provide a mic-input as well as a second audio out. I'll either make the onboard audio or the usb audio connect to a small speaker that can be driven via line-level audio (if this is too quiet, I may fashion a small class A or B audio amp circuit). The sound card will allow the FEK to do audio munging via SOX (can act as voice changer) as well as take analog audio input and transmit it. I may do 2 usb sound cards. one for a permanently affixed speaker and mic and one for auxiliary inputs. The real problems arise when I figure out how I want to handle audio routing. I despise pulseaudio, but it may be the most functional and best supported option. I would really prefer not to have to run it (and thus dbus). If only KLANG were more than vaporware. == Wifi == It'd sure be great if the upstream driver for rtl8192cu chipsets worked. As it is, the Pi Linux Kernel does not support the upstream driver for some unfathomable reason. The driver it does ship with is from realtek and only works for managed mode. Ad-hoc and master (via hostapd) do not work. == == ===== Software ===== Running arch linux with some modifications. ==== Kernel ==== Apparently, the r-pi cannot run a vanilla kernel. I learned this the hard way (after 10+ hours of compiling). The raspberry-pi branch of the linux kernel has some broken dmaengine.c / bcm2708-dmaengine.c. I'm no kernel hacker, but doing my best to resolve the issues. Update: There were too many issues to resolve myself, but switching to a newer 3.18 branch seems to have resolve that issue. I hit yet another issue which appears to be due to unzip not decompressing the rpi zip file correctly. Use of p7zip seems to have alleviated this issue. Update2: Well I had to wait for more progress to be made. I can now load 3.18.y and even load ssd1307fb, but apparently I have to manually add information into the Device Tree. Also I have to learn what the hell the “Device Tree” is. ==== Display ==== I'm using an OLED display ran using an SSD1306 driver chip. There is a linux driver to utilize this screen as a framebuffer device: http://lxr.free-electrons.com/source/drivers/video/fbdev/ssd1307fb.c === Stack === - SSD1307fb.c driver to implement as a /dev/fbX device - Run Xorg with directFB driver to point to /dev/fbX/ * export FRAMEBUFFER=/dev/fb1 startx - Tk can run directly (no Window Manager needed) under X, fullscreen. * (Tcl/Tk will be the main interface driver, it will lunch sub-programs) === Update === AndroWish distributes an SDL2 library and sdl2wish application! No X server is needed now! Tk is displayed using SDL. SDL is rendered using directfb. The kernel provides an framebuffer interface to the OLED display. === Update 2 === After all the trouble trying to get that OLED screen to work, and given the cramped conditions of the case, I've decided to make the FEK a headless-device: no screen or buttons on it. Interactions will occur via an ethernet connection. Either through the 10/100 port or via an ad-hoc wifi connection. The principal interface device will be a smart phone that can connect to it via ssh or via VNC. ==== pikeyd ==== Also running a custom fork of pikeyd to generate keyboard events based on gpio input. The 5 direction switch will be mapped to up, down, left, right. The center click will be left disconnected. the A and B buttons will be mapped to enter and backspace. The fork is largely a clean up of the code, with little functional changes. Addtional changes may be made as necessary. ==== fastinit ==== The fastinit script displaces systemd. It boots much faster and uses less RAM. And is entirely more sensible for an embedded system than the monster that is systemd. Because archlinux is designed to work with systemd-udevd (which uses netlink for communication), the kernels are compiled without the old style /proc/sys/kernel/hotplug or slightly newer /sys/kernel/uevent_helper. So I adapted some sample code from the kernel to make a wrapper for busybox's mdev so hotplug events reported via netlink can be passed to mdev. === Steps === - Install fastinit script to /sbin/fastinit * Be sure to make it executable: chmod +x /sbin/fastinit - Install busybox * pacman -S busybox - Symlink to busybox as mdev * ln -s /usr/bin/busybox /sbin/mdev - Edit /boot/cmdline.txt, add this to the end: * init=/sbin/fastinit You can switch back to a normal systemd init/boot by removing init=/sbin/fastinit from the cmdline.txt file. <file bash fastinit> #!/bin/bash export PATH=/bin:/sbin service () { while true; do $@ sleep 1 done & } #mount system pseudo filesystems mount -t proc proc /proc mount -t sysfs sys /sys mount -t devtmpfs dev /dev mkdir /dev/pts mount -t devpts devpts /dev/pts #launch the netlink to mdev bridge service service /usr/sbin/nl2mdev #load any modules specified in /etc/modprobe.d/* if [ $(ls /etc/modprobe.d/ | wc –lines) -gt 0 ]; then for module in /etc/modprobe.d/*; do modprobe $(< $module ) done fi #alternate module config info if [ $(ls /etc/modules-load.d/*.conf | wc –lines) -gt 0 ]; then cat /etc/modules-load.d/*.conf | xargs -i{} modprobe {} fi #rescan for device changes mdev -s #mount anything specified in /etc/fstab mount -a #set hostname hostname $(< /etc/hostname ) #initialize serial port stty -F /dev/ttyAMA0 sane #network setup and network dependent services ( ifconfig lo up 127.0.0.1 ifconfig eth0 up ifconfig eth0:0 up 192.168.10.1 #launch network-dependent services here service /usr/sbin/sshd -D ) & #other services service /sbin/agetty –noclear tty1 linux service /sbin/agetty ttyAMA0 115200 vt100 service /usr/bin/crond -n wait #done booting! </file> ==== nl2mdev ==== I could just recompile the kernel to support the older style hotplug manager, but I'm trying to keep changes down to a minimum to lessen the amount of trouble upgrading will be down the line. This little program (most of it from the example netlink code from the kernel documentation) let's me use an unmodified mdev from busybox and an unmodified archlinux kernel. In reviewing the code, I realized in my laziness (trying to avoid having to free() memory), I might have introduced a race condition. Oops. Will work on fixing this… <file c nl2mdev.c> /* nl2mdev - netlink wrapper for busybox's mdev * gcc -std=c99 -pedantic -Wall -O2 nl2mdev.c -o nl2mdev */ #define _XOPEN_SOURCE 500 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <sys/poll.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <linux/types.h> #include <linux/netlink.h> void die(char *s) { write(2,s,strlen(s)); exit(1); } int main(int argc, char *argv[]) { struct sockaddr_nl nls; struct pollfd pfd; char buf[512]; signal(SIGCHLD, SIG_IGN); Open hotplug event netlink socket memset(&nls,0,sizeof(struct sockaddr_nl)); nls.nl_family = AF_NETLINK; nls.nl_pid = getpid(); nls.nl_groups = -1; pfd.events = POLLIN; pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (pfd.fd==-1) die(“Not root\n”); Listen to netlink socket if (bind(pfd.fd, (void *)&nls, sizeof(struct sockaddr_nl))) die(“Bind failed\n”); while (-1!=poll(&pfd, 1, -1)) { int i, len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT); if (len == -1) die(“recv\n”); if (!fork()) { unsigned int count = 0; char **env = calloc(9, sizeof(char *)); i = 0; while (i<len) { env[count++] = (char *) strdup(buf+i); i += strlen(buf+i)+1; } env[count] = (char *) NULL; execle(“/usr/bin/mdev”, “/usr/bin/mdev”, (char *) NULL, env); exit(0); } } die(“poll\n”); Dear gcc: shut up. return 0; } </file> ===== References ===== * Mechanical Drawing of R-pi model B+