This is work in progress! Only the “let’s make sure it’s possible” part is done and documented for now

Challenge of the moment

Challenge: How to send commands to a computer without using an input device?

Context: While it’s not frequent, I sometimes run into situations where no input devices would work. That can happen because of a new X server with no compatible input devices; or while running a sample Wayland compositor on a console with X still running (not exactly sure what the problem was exactly); or because running gdb on X from within X is a bad idea; etc.

Simple, non-bulletproof solutions:

  • Obviously, sshing from another machine is the ideal situation. But that requires an extra machine, which might not be available during a train trip.
  • Using a smartphone to do that would be nice, but would require buying such a phone.
  • Having an extra input device, with an appropriate X configuration (i.e. not taking that input device into account) could also work. But that wouldn’t really help with some weird situations involving console, Wayland compositor, and X.

Alternative, viable solution 1:

Buying a tiny, open, programmable device, like the Arduino Nano, a few components like a selector and a push button might do the trick. Then, some bits of programming with the open source Arduino environment should make it possible to connect that device to a USB port using a mini-B cable. Some bits going through a serial console and a daemon listening on it would make it possible to trigger a predefined set of actions just by selecting a position and hitting the button. Tada!

No drawback for that solution, except the need for thinking about bringing that device everywhere. :)

Alternative, viable solution 2:

While I’m by no means a phone addict, I tend to have it with me more or less all the time, and it can be connected through a mini-B USB cable. Oh, but then, maybe I could turn it into a suitable device as described above?

That’s a Motorola RAZR V3, it runs Java applications, and there’s a SDK available for Linux (32 bits) through the Motorola developer network. That might be enough, so I decided to jump through some hoops to see whether that’s indeed feasible. Not because I like it much better than the Arduino-based solution, just because I can.

The rest of this document explains how I went from the “maybe it’s possible” idea to the “yes, now I know how to build, upload, and run a custom application” certitude.

Step 1: Enabling Java Application Loader

There’s a Java Application Loader on the phone making it possible to receive new applications over a wire. Enabling it should be about going through the following menus: SettingsJava SettingsJava App Loader. Unfortunately, that menu entry might not be there!

Here’s how I enabled it on my phone (purchased independently from a contract with phone companies; those may not want to allow it).

  1. Get moto4lin from the SourceForge moto4lin project. That can be done through:

    svn clone https://moto4lin.svn.sourceforge.net/svnroot/moto4lin
    
  2. Since that’s a Qt3 application, installing qt3-dev-tools is needed, along with switching a few alternatives to the Qt3 version if the Qt4 package is also installed: uic, moc, and qmake (that’s done through update-alternatives --config $foo). Another needed package is libusb-dev.

  3. Switch to the trunk/moto4lin/ directory, and run: qmake moto4lin.pro && make
  4. If the build succeeds, ./moto_ui/moto4lin should start the application.
  5. Plugging the cable should make a /dev/ttyACM0 device appear, with root:dialout ownership; a quick and dirty way to access this device is running the application with:

    sudo XAUTHORITY=~/.Xauthority ./moto_ui/moto4lin
    

    (or wherever the X authority file lives, gdm3 users may want to check /var/run/gdm3/).

  6. Selecting the device should just be about clicking SettingsPreferences; in the new dialog, in the USB view, clicking Update List, picking the phone, and Set as P2k Device should be sufficient.
  7. Back to the main dialog, clicking Connect/Disconnect should get a connection to the phone. As a bonus, the local file system can be inspected, files downloaded, or even uploaded (to some directories).
  8. Now switch to Seem Editor, then Read Seem. At this point, it’s strongly encouraged to save a copy to some file, just in case.
  9. The bit controlling the presence of the Java Application Loader menu entry is part of the byte located at offset 43 (in hexadecimal), meaning the byte at the intersection of row 4 and column labelled 3 (i.e. the 4th column). Once it’s selected, tick the checkbox for bit 0 in the Bit editor frame.
  10. Now Write seem; unplugging, and rebooting the phone should do the trick.

Step 2: Getting the SDK

Two components are needed to get things rolling. One is “MOTODEV Studio for Java ME v2.2” (basically a tweaked Eclipse), the other is “MOTODEV SDK for Java ME v2.2”. They can be downloaded from http://developer.motorola.com/docstools/motodevstudio/javame/downloads/ (which apparently doesn’t require registering).

That’s for Linux, 32-bit, so I decided to create an i386 VM using VirtualBox. A storage of 2GB seems to be sufficient, but 3GB would be a bit safer. Some packages were added to the basic i386, non-Desktop setup:

  • some basic X packages (both drivers aren’t really needed, that’s just to work around #631612): xserver-xorg-input-evdev xserver-xorg-video-vesa xserver-xorg
  • some packages to get a very basic desktop: xauth xterm xfwm4 xfce4-utils
  • and the Java Runtime Environment: openjdk-6-jre

Once those packages installed, starting the X session from the console is just about running startxfce4 as an unprivileged user.

In a graphical shell, untar the tarballs, and:

  1. Run: ./MOTODEV_Studio_for_Java_ME_2.2.0_Linux-x86; that’s a click-through installer, which should auto-detect the JRE path (/usr/lib/jvm/java-6-openjdk/jre/), and for which all defaults should be OK. Close the welcome screen, then the application.
  2. Run: ./MOTODEV_SDK_for_Java_ME_2.2.0_Linux-x86; that’s the same kind of click-through installer. Close the application once the installation is finished.

To start those applications again, shortcuts are available in Xfce’s Applications Menu. Basically, installing those means having an Eclipse instance tweaked for Motorola development, for a wide range of devices. This includes being able to run applications on emulated phones, instead of having to deploy them to real phones.

Step 3: Toying with a trivial project

Time for “Hello, world!”, thanks to MOTODEV Studio.

  1. From the menu: FileNew project.
  2. In the wizard, pick: Java MEMIDlet Project.
  3. Enter a name: raxor (some mix of Motorola RAZR and roxor…).
  4. Add a configuration:
    • SDK: MOTODEV SDK for Java(TM) ME
    • Device: MOTORAZR_V3
    • Click Finish in the configuration dialog.
  5. Click Finish in the wizard dialog.
  6. For reference, the current tab is called raxor, and also known as the Application Descriptor.
  7. Now add a MIDlet: Right click on raxor in the Navigator.
  8. Then NewOtherJava MEJava ME MidletNext.
  9. Enter a name, say Hello, and hit Finish, a Hello.java tab gets opened.

The file contains some boilerplate, and adding a few lines leads to this complete example:

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.*;

public class Hello extends MIDlet {
  Display display;
  Form form;

  public Hello() {
    display = Display.getDisplay(this);
    form = new Form("HelloMIDlet");
    StringItem item = new StringItem("Hello, World!", "This is raxor");
    form.append(item);
  }

  protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
  }

  protected void pauseApp() {
  }

  protected void startApp() throws MIDletStateChangeException {
    display.setCurrent(form);
  }
}

Going back to the Application Descriptor, on the Overview tab (the default), click Launch as emulated Java ME MIDlet and enjoy the emulated phone and its “Hello, World!” message!

Step 4: Getting ready to deploy

Time to stop the VM for a while and plug the phone again.

That’s where using VirtualBox is a bit nicer than using a plain chroot. It can make USB devices visible to guest systems. For that to work, one needs to be in the vboxusers group (see: ls -ld /dev/vboxusb). To check quickly what one is able to share with guest systems, there’s this command:

VBoxManage list usbhost

If it returns <none> then there’s no device to share, or there is a permission/group problem.

Once the phone pops up in the list of host USB devices, the Settings of the VM have to be tweaked:

  1. Tick Enable USB Controller.
  2. Add the phone through the Add Filter From Device button, picking the right entry.

Start the VM again, the phone should be listed there, check with lsusb for example.

Now the user starting MOTODEV Studio should be able to write to the /dev/ttyACM0 device. Since that’s a VM, a quick and dirty hack seems OK. Here’s /etc/udev/rules.d/42-motorola-permissions.rules:

KERNEL=="ttyACM0", MODE="0666"

then /etc/init.d/udev restart; alternatively, add the user to the dialout group and log in again.

From MOTODEV Studio, get back to the raxor project, and to its Application Descriptor. In the Overview tab, the Packaging section has a Create package button. I witnessed that even without any modifications, a dialog could pop up at this point, with a Configurations is dirty title. It’s been apparently noticed and mentioned on the Motorola forums. An easy workaround is to rename the project. Create package should then just work, and renaming it back should also be OK.

Now, let’s get the Deployment Tool: WindowShow ViewOther.... Then MOTODEV Studio for Java MEDeployment ToolOK.

The default option is appropriate: JAD File on Workspace. Select the raxor.jad file using the Browse button.

If the phone wasn’t plugged yet, just plug it in, and click Update next to the (probably) empty Port drop-down list. /dev/ttyACM0 should appear at this point.

Once everything is set, clicking the Deploy icon (on the top right corner of that Deployment Tool) would lead those messages in the Console window:

MWAY> Opening connection with serial port [/dev/ttyACM0].
MWAY> Starting Transmission...
MWAY> Connection Timeout.

That’s where the Java Application Loader (JAL) kicks in. On the phone, select SettingsJava SettingsJava App LoaderSelect. Now the JAL says Insert cable now and after cable unplugging/plugging, JAL link is active.... Clicking the Deploy icon should then make some prompts appear on the phone.

  • Details with name, size, version, and vendor → Download.
  • Not a signed application? Continue Downloading?Yes.
  • Downloaded then Installed.
  • Run raxor MIDlet Suite? → Yes.
  • Yatta!

Step 5: Getting documentation

Both Studio and SDK packages come with documentation. All is needed is two bits of configuration:

  • Install a browser, say: midori.
  • Configure it through the preferences: WindowPreferencesUse external Web browserNew. In the new dialog, specify the name (midori), the location (/usr/bin/midori), and the parameters (%URL%). Back in the previous dialog, tick the newly-created item, and exit preferences.

Once that done, HelpHelp Contents. To learn more about the GUI, one can pick MOTODEV Java ME Developer’s GuideJava ME APIsJSR-118 Mobile Information Device Profile (MIDP) 2.0; in the frame on the right, there’s the import seen at the very beginning of the code sample above: javax.microedition.lcdui.

Step 6: Getting started with the socket

On the phone side, applications can’t be started [FIXME]

On the compute side [FIXME]

Step 7: Designing the GUI

The overall idea is quite simple:

  1. Open a serial console.
  2. Receive a set of preset commands.
  3. Display all of them using radio buttons.
  4. Let the user pick one.
  5. Send it back through the serial console after confirmation.
  6. (optional) Receive an ACK and display it.
  7. Repeat, going back to step 2.

One could think of an extra choice here, letting user specify a custom command.

Here’s a tiny code sample:

ChoiceGroup cg = new ChoiceGroup("Available actions",
                                 Choice.EXCLUSIVE);
cg.insert(0, "foo", null);
cg.insert(1, "bar", null);
form.append(cg);

EXCLUSIVE means it’s a group of choices where only one can be selected at a time, which will likely be implemented as radio buttons; but such implementation details depend on the exact phone model. The null parameter means no image is specified.

Let’s add some commands:

Command ok = new Command("OK", Command.ITEM, 1);
Command exit = new Command("Exit", Command.EXIT, 1);
form.addCommand(ok);
form.addCommand(exit);

Again, command types and phone-specific implementations will decide how commands are rendered.

Now let’s connect commands to actual actions:

form.addCommandListener(this);

The IDE will now be unhappy. Indeed, one needs to tweak the class to implement CommandListener:

public class Hello extends MIDlet {

becomes:

public class Hello extends MIDlet implements CommandListener {

Then one needs to implement an extra method:

public void commandAction(Command command, Displayable displayable) {

This is work in progress! Hopefully some real code will follow: talking through a serial console, interacting with a daemon on the other side, and running commands remotely!