Sunday, October 28, 2012

Phonetendo

I came across one of these in a local thrift store for $8:


Thrift stores are dangerous places to go; my powers of self-discipline can only be tested so far. Unlike the cabinet stereos that have troubled my past, this was fortunately small, cheap and clearly awesome. It begged to be adopted.


What is it?

This is about to get a little heavy on the detail, so feel free to skip to the last section to see what I did with this. But anyway:

This is an Iris 3000 videophone, manufactured by UMEC and distributed by ACN, launched in 2007 on The Apprentice. It's apparently a standard SIP phone with various quirks and flaws, though I've got no particular interest in using it that way.

Cracking it open reveals the motherboard:


On the back are composite video and audio outputs, a POTS jack, two ethernet jacks, a USB jack, a power jack, and a power switch. There are several unpopulated pads on the board, but nothing I've bothered investigating yet.


This board was manufactured in 2009 and also goes by the name CU776. Googling this leads to the manufacturer's specifications.


Here is the Freescale i.MX27 brain that runs the unit. This is an ARM chip with additional multimedia brawn, intended for the telecommunications market.

Looking around the board for a few other clues about its features, we find a FS453LF chip:


This is the TV encoder that feeds the video output at the back of the unit.

There is also a WM8731S chip:


This is a CODEC that handles the audio duties -- the speakerphone and handset. (And as you can see, the photo also contains another another of those useful-looking unpopulated headers.)

The only other feature worth mentioning is the SD card slot on the side; we'll get back to that.


Software

As mentioned on the Wikipedia page, this phone runs Linux. That's helpful to someone who wants to hack the device in some ways but there still needs to be a way to break into it. Luckily, hackers love a challenge. I found this very useful thread, which included instructions on gaining a root shell:
$ telnet 192.168.3.2
Trying 192.168.3.2...
Connected to 192.168.3.2.
Escape character is '^]'.


        Welcome to Freescale Semiconductor Embedded Linux Environment


freescale login: root
Password:
mx27#

Bingo! Some exploration turned up a pretty standard embedded systems setup:
  • Busybox for the system tools,
  • A great big monolithic QT application for the UI, and
  • A mixture of additional tools and programs for the details.
A Better Operating System

Luckily most of this is standard fare: V4L for the camera, /dev/fb0 for the LCD, ALSA for the audio, and /dev/input/event0 for the keypad. These are the normal ways of accessing the hardware on a Linux system, if occasionally a little musty.

So it'll do fine with Linux. However, a logical next question is: will it run Debian? Busybox is a little like skim milk -- fine for other people who want to lose weight, but to be kept strictly out of my coffee. I started with QEMU, an ARM emulator, and built a Debian disk image using steps similar to these. I wrote that disk image to a 2GB SD card, popped it in the side of the phone (which was even kind enough to auto-mount it for me), and used pivot_root to flip over to it. This isn't strictly the same as booting into Debian -- I'm still running busybox's init, for example, and need to manually start any services I want to run -- but it does get me a full libc and all the apt-get I want.

I did investigate the built-in bootloader and the chances of flashing the internal 128MB with a new boot image -- but decided against it; it's unnecessary for my purposes and risks bricking the phone. The other problem with that is that the kernel that ships with this phone is customized in at least a couple of ways: it has a very useful recovery mode which I've used twice to cover for my own stupid mistakes (ignore at your own risk the note in bold on the manpage for switch_root), and it has at least one custom kernel module, for which the source appears to closed. I am not a lawyer, but it sure looks to me like UMEC is violating the terms of the GPL. So I'm stuck with that kernel and any warts it has or I will lose the functionality those modifications provide.

Reverse Engineering

So a little bit of exploration left me with a few unknowns. I was especially interested in the following: how was the device sending audio to the handset and not just the speakerphone? How did it know the handset was on hook or off?

There are a number of tools to help answer this kind of question, starting with a very basic examination with strings, then moving to move advanced tools like strace and gdb.

The strings tool looks in any file for content that looks like it's human-readable and dumps it out. Using strings on a program tends to grab things like text that it displays on the screen, copyright notices, etc., but also reveals some internal details -- what hard-coded programs and files it interacts with. In this case it turned up several device files, including /dev/umec_device, and the names of some standard system tools like ifconfig, route, iptables, and amixer.

The /dev/umec_device file was an immediate suspect for specialized interaction between software and hardware, but there was no information online about it, so I had to get a sharper chisel.

The strace and gdb tools are generally for programmers trying to figure out why their program is going astray, but they can also be used to reverse-engineer 3rd-party programs. In particular, they can display information about interactions a program has with the system, which is exactly what interested me.

The first problem I encountered was that I was running the device with a split personality. The phone software and boot scripts were running using the busybox environment, and all my debugging tools and their respective libraries were running from the Debian-based SD card. This caused a minor amount of schizophrenia as gdb tried to reconcile the two. I resolved this by killing off the phone's UI, neutering the tools it tries to reach in order to configure the network (e.g. moving /sbin/ifconfig to /sbin/ifconfig-real), and starting it again from within the chroot environment. Luckily this worked.

This allowed me to look at a dump of what was happening when I took the handset off-hook or returned it to its cradle:
printf("bard dbg: g_speaker_status=%d ev"..., 0) = 37
memcpy(0xbe84cbdf, "/dev/umec_device", 17)       = 0xbe84cbdf
open("/dev/umec_device", 2, 00)                  = 18
ioctl(18, -1073458425, 0xbe84cbd4)               = 0
close(18)                                        = 0
memcpy(0xbe84cbdf, "/dev/umec_device", 17)       = 0xbe84cbdf
open("/dev/umec_device", 2, 00)                  = 18
ioctl(18, -1073458427, 0xbe84cbd4)               = 0
close(18)                                        = 0
memcpy(0xbe84cbdf, "/dev/umec_device", 17)       = 0xbe84cbdf
open("/dev/umec_device", 2, 00)                  = 18
ioctl(18, -1073458424, 0xbe84cbd4)               = 0
close(18)                                        = 0
memcpy(0xbe84cbdf, "/dev/umec_device", 17)       = 0xbe84cbdf
open("/dev/umec_device", 2, 00)                  = 18
ioctl(18, -1073458426, 0xbe84cbd4)               = 0
close(18)                                        = 0
printf("bard dbg: new g_speaker_status=%"..., 0) = 33
Great! Except that this isn't enough. The ioctl call is what interacts with the /dev/umec_device, and it can be called in a number of different ways. In many cases you don't pass it the actual instructions for what you want it to do; instead, you pass it the location in memory where it can find the instructions. That 0xbe84cbd4 looks suspiciously like just such a pointer, since it's passed into ioctl four times in a row.

So how to figure out what's being put in that location in memory before it's given to ioctl? Googling around for such a thing, I found this. It's basically a trojan horse: when you run a program, you first instruct Linux's library load code as follows: "By the way, before you load any external code, check here for it first." And you give it a special piece of code that defers to the same old library call that would've been made anyway, but logs what's happening first. Looking at the ioctl calls above, I wrote this wrapper:
#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <malloc.h>

FILE *preloadhackfp;

static int (*next_ioctl)(int fd, int request, void *data) = NULL;
int ioctl(int fd, int request, void *data) {
        char *msg;

        if (next_ioctl == NULL) {
                fprintf(stderr, "Wrapping ioctl.\n");
                fflush(stderr);
                next_ioctl = (int (*)(int, int, void*)) dlsym(RTLD_NEXT, "ioctl");
                if ((msg = dlerror()) != NULL) {
                        fprintf(stderr, "ioctl: dlopen failed : %s\n", msg);
                        fflush(stderr);
                        exit(1);
                }
                preloadhackfp = fopen("/tmp/preloadhack.log", "a");
                fprintf(preloadhackfp, "Opened log.\n");
                fflush(preloadhackfp);
        }
        if (request == -1073458425 || request == -1073458427 || request == -1073458424 || request == -1073458426) {
                long int i = *((int *) data);
                fprintf(preloadhackfp, "Logged %i: %li\n", request, i);
                fflush(preloadhackfp);
        }
        return next_ioctl(fd, request, data);
Running the phone binary with LD_PRELOAD set to load this poison pill got me a log containing exactly what I needed to know. Of course, all this would've been unnecessary if UMEC wasn't violating the GPL. On the plus side, I learned some new skills here.

A New Purpose

Some unknowns remain about this hardware, but this was enough for my purposes.

My goals here were twofold:
  1. Make a video game that uses the phone as an interface. Well, to be honest, this isn't actually a game -- it's a close fake. It looks like a game and acts like a game, but actually it's an office assistant simulator. You are required to suffer an unpleasant environment and given menial tasks to perform.
  2.  
  3. Turn the video phone into a gaming platform. By setting up the SD card in a particular way -- specifically, to provide a script called "sltp", which the phone for some reason is hard-coded to look for -- you can trick the phone into running the game instead of performing its usual startup. That means the SD card is effectively a into a game cartridge and the phone into a weird-looking Nintendo.
This is a work in progress, but currently it's an isometric game set in a cubicle maze. (Thanks to Clint Bellanger for the tiles.) You wander around amidst your coworkers and greet them. (Thanks to "Intimidated" at freesound.org for the samples.) You're all zombies, thanks again to art borrowed from Clint's open-source Flare RPG. (I had intended to use the zombie sprites only until I could scare up some suitable [so to speak] alternatives, but over time the zombies have grown charming.) Occasionally you'll receive robocalls. You can dial out but the line is always busy. Coworkers may ask you to find a lost stapler. The music is repetitive (thanks and, um, sorry, Antionio Fiorucci) and you can't turn it off.


The code is all new, written in C using SDL. There were a bunch of new algorithms and tools to learn en route -- pathfinding for the NPC behavior, drawing isometric maps, etc. -- and problem-solving varied from fun to frustrating.


In the coming weeks I hope to add more "missions" (deliver this file to so-and-so, maybe navigating phone maze hell, and the like) but for now it proves its point and hopefully shows the potential for reuse for this device.

The source code for this is posted on github.com. More to come, including a HOWTO describing how to build the SD card.

(I'll be showing this alongside many other bits of oddness at the Vancouver East Side Culture Crawl, Nov. 16-18 here in Vancouver. Come say hi.)

25 comments:

  1. Replies
    1. Definitely, but not in the next couple of weeks. I have to survive the Culture Crawl first.

      Delete
  2. I've been wanting to use this as a standard phone forever, also would be nice if I could get it to work as a SIP to google voice.....

    ReplyDelete
    Replies
    1. Lewis, some of the folks at the pbxinaflash.com thread linked in the blog entry have been trying to rehabilitate the phone in a similar way. I reverse-engineered the hook switch and speakerphone/handset audio routing, which is part of what you'll need. I don't particularly need a SIP phone so my hacking won't be heading in that direction, but the linked thread has some smart people on the case.

      Delete
  3. How very cool. I recently picked up a few Nortel 1535s for our firm partners and one for myself to use in lieu of our standard issue Cisco 7940 SIP phones at the office, and they seem very similar to your phone. Linux, busybox, SD card, telnet access, but I have yet to crack mine open to see what chips lie inside. I wonder if there's any relation to your phone. Will certainly do some investigating tomorrow afternoon if I don't get too busy. I have successfully transplanted some pre-built armv4l binaries to it (busybox, bash,) and intend to do some repurposing soon. Keep us posted on your progress. Fascinating stuff.

    ReplyDelete
    Replies
    1. Jeremy, I suspect the Cisco phones are different hardware. The ACN device is made by UMEC in violation of the GPL; Cisco has been burned by GPL violations in the past and is unlikely to play that game again so soon. I'd also like to hope they make better hardware; this phone is just a little bit cheesy. In summary, I kind of wish I had your phones instead :)

      Delete
    2. Actually, I'm referring to the Nortel 1535, not the Cisco. The Ciscos are pretty solid phones, but run a proprietary OS and not much fun to hack around with. The Nortel is a pretty cheesy phone as well -- buggy features, "meh" interface, VGA camera, etc. As soon as I saw your entry on Hackaday, my mind immediately went to the Nortel 1535 on my desk that I've been playing with lately. I didn't get a chance to open it up yet today, but did get a few minutes to telnet in and look at the /dev devices. Very different layout from yours, but your project here gave me good inspiration to continue to bend this phone to my will. :) Keep having fun with cheap electronics!

      Delete
  4. Bought mine from the thrift for $7.50 Plus Tax :).
    Have not dug into it nearly as far as you have.
    Thanks for the Links!

    ReplyDelete
    Replies
    1. Amazing how many of these ended up at thrift shops! I think you hold the record for cheapest acquisition so far, Dennis.

      Delete
  5. I LOVE the idea of using the phone itself as an interface. Great idea, and brilliant execution! Keep it up!

    ReplyDelete
  6. Pls tell me how setup this phone for using my Asterisk??!

    ReplyDelete
    Replies
    1. Ivan, try the pbxinaflash.com thread; this is probably the only IRIS-3000 thread on the whole Internet where that question is off topic :)

      Delete
  7. I got 2 of them for $30 total on ebay today. I plan to duplicate your hack, maybe use it as an x10 controller. Maybe find a way to wire up irda too.

    ReplyDelete
  8. I was inspired by this post and purchased an Iris 3000 for similar tinkering. Mine came with bash and strace available, but most utilities were indeed busybox-ed.

    So far:

    * Loaded a copy of Debian Squeeze on a SD card and manually chrooted into it
    * Compiled a static version of dropbear to replace the one that came with the phone; there was a bug that prevented modern SSH clients from authenticating successfully

    The one thing that I can't do for the life of me is access the framebuffer and run SDL apps. I would love to rewrite the UI for the phone and extend the featureset beyond what the stock ACN provides. I wonder what you did to get your Office Space simulator to start; and methinks it has to do with the sltp script called from your SD card. My attempt to simply kill the admin interface and fire up a copy of SDL Doom from the chroot hasn't gotten me anywhere.

    Well, I'll be patient for the guide like everyone else in the thread. :D

    Thanks for documenting what you have so far!

    ReplyDelete
    Replies
    1. Awesome, glad to hear someone else is heading down the weirdo-gaming path here. Where is Doom failing? The phone is pretty limited in the options to the SDL initialization code -- it supports 640x480x16bpp and very little else. Try a couple of bits and pieces of SDL sample code to find out what variations work before heading into Doom wholesale. But I would *love* to see Doom running on that phone. Will write up the rest soon.

      Delete
  9. Somebody know where to download the LTIB with 2.6.22.6 kernel? I want to compile a module for USB-mouse support.

    ReplyDelete
  10. http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=i.MX27PDK&fpsp=1&tab=Design_Tools_Tab

    ReplyDelete
    Replies
    1. LDK_IMX27_R1_1 contains only 2.6.22 kernel, and modules compiled with this kernel don't work on the 2.6.22.6 kernel that have this phone.

      Delete
    2. The phone runs a customized kernel that's in violation of the GPL so I suspect you'll have to do some reverse-engineering to figure out what toolset the manufacturer used.

      Delete
  11. Hey, I dont see a how to on github, I have rooted the phone. Any idea where the how-to is?

    ReplyDelete
    Replies
    1. I haven't written it yet. I'll make a new blog post when I've had a chance to write it up so feel free to drop it in your RSS reader.

      Delete
  12. Interesting... How many people are waiting for "how to"?
    ps/ somebody tried to compile something like this - http://mednafen.sourceforge.net/screenshots/nes/

    ReplyDelete
  13. All,

    I run a non-profit organization that trains people in political activism. I see these phones as having great potential for distance training, since projectors and speakers can be set up with them. What ACN's service cannot do is broadcast a video call to multiple video phones, their latest model only allows for a conference call with three people. So.....

    I am interested in how to unlock these phones and make them work with an Asterisk server to be set up in our office. I see elsewhere that some people have been able to do this to receive calls, but not place them.

    Unfortunately I am a Linux novice, though all of our office systems run Mint and Ubuntu. Any takers on this or anyone who can offer understandable instructions? rpbcentral@gmail.com 503-970-1876.

    ReplyDelete