How to not write code for a mobile device

Earlier this week, I got a shiny, brand-new XV6800 to replace my aging (and rather limited in terms of running user-created programs) BREW-ified phone.

After setting up ActiveSync, IPsec, and all of the other usual required configuration settings, the next step was, of course, to install the baseline minimum set of applications on the device to get by. Close to the top of this list is an SSH client (being able to project arbitrary console programs over SSH and screen to the device is, at the very least, a workable enough solution in the interm for programs that are not feasible to run directly on the device, such as my SILC client). I’ve found PuTTY a fairly acceptable client for “big Windows”, and there just so happened to be a Windows Mobile port of it. Great, or so I thought…

While PocketPuTTY does technically work, I noticed a couple of deficiencies with it pretty quickly:

  1. The page up / page down keys are treated the same as the up arrow / down arrow keys when sent to the remote system. This sucks, because I can’t access my scrollback buffer in SILC easily without page up / page down. Other applications can tell the difference between the two keys (obviously, or there wouldn’t be much of a point to having the keys at all), so this one is clearly a PocketPuTTY bug.
  2. There is no way to restart a session once it is closed, or at least, not that I’ve found. Normally, on “big Windows”, there’s a “Restart Session” menu option in the window menu of the PuTTy session, but (as far as I can tell) there’s no such equivalent to the window menu on PocketPuTTY. There is a “Tools” menu, although it has some rather useless menu items (e.g. About) instead of some actually useful menu items, like “Restart Session”.
  3. Running PocketPuTTY seems to have a significantly negative effect on battery life. This is really unfortunate for me, since the expected use is to leave an SSH session to a terminal running screen for a long period of time. (Note that this was resolved, partially, by locating a slightly more maintained copy of PocketPuTTY.)
  4. SSH port forward support seems to be fairly broken, in that as soon as a socket is cleaned up, all receives in the process break until you restart it. This is annoying, but workable if one can go without SSH port forwards.

Most of these problems are actually not all that difficult to fix, and since the source code is available, I’m actually planning on trying my hand at doing just that, since I expect that this is an app that I’ll make fairly heavy use of.

The latter problem is one I really want to call attention to among these deficiencies, however. My intent here is not to bash the PocketPuTTY folks (and I’m certainly happy that they’ve at least gotten a (semi)-working port of PuTTY with source code out, so that other people can improve on it from there), but rather to point out some things that should really just not be done when you’re writing code that is intended to run on a mobile device (especially if the code is intended to run exclusively on a mobile device).

On a portable device, one of the things that most users really expect is long battery life. Though this particular point certainly holds true for laptops as well, it is arguably even more important that for converged mobile phone devices. After all, most people consider their phone an “always on” contact mechanism, and unexpectedly running out of battery life is extremely annoying in this aspect. Furthermore, if your mobile phone has the capability to run all sorts of useful programs on it, but doing so eats up your battery in a couple of hours, then there is really not that much point in having that capability at all, is there?

Returning to PocketPuTTY, one of the main problems (at least with the version I initially used) was, again, that PocketPuTTY would reduce battery life significantly. Looking around in the source code for possible causes, I noticed the following gem, which turned out to be the core of the network read loop for the program.

Yes, there really is a Sleep(1) spin loop in there, in a software port that is designed to run on battery powered devices. For starters, that blows any sort of processor power management completely out of the water. Mobile devices have a lot of different components vying for power, and the easiest (and most effective) way to save on power (and thus battery life) is to not turn those components on. Of course, it becomes difficult to do that for power hungry components like the 400MHz CPU in my XV6800 if there’s a program that has an always-ready-to-run thread…

Fortunately, there happened to be a newer revision of PocketPuTTY floating about with the issue fixed (although getting ahold of the source code for that version proved to be slightly more difficult, as the original maintainer of the project seems to have disappeared). I did eventually manage to get into contact with someone who had been maintaining their own set of improvements and grab a not-so-crusty-old source tree from them to do my own improvements, primarily for the purposes of fixing some of the annoyances I mentioned previously (thus beginning my initial forey into Windows CE development).

Tags: ,

10 Responses to “How to not write code for a mobile device”

  1. Nate says:

    The poll loop is because they didn’t want to block the UI threads with a blocking read of the socket. However, if they fork off a separate thread, they don’t have to poll. They can just do a blocking (i.e. WFMO) read.

  2. Skywing says:

    Actually, it’s an artifact of the port to Windows CE. Normally, PuTTY uses WSAAsyncSelect, but that doesn’t exist on WinCE. The way the person who did the initial port elected to handle this case was with a spin loop on ioctlsocket, which is, to say the least, probably not the best approach.

    Later on, somebody patched it to use WSAEventSelect/WFMO in the dedicated thread. However, this also broke as due to how the logic was wired up internally, > 1 socket would not be properly supported, and this put SSH port forward support in a rather broken state.

    I rewrote it to just use MsgWaitForMultipleObjects/WSAEventSelect on the main (UI) thread. Ironically, PuTTY already uses MWFMO by default, and using WSAEventSelect (even on “big Windows”) would have been a far better solution than WSAAsyncSelect.

    Creating extra threads is undesirable in the (relatively) resource constrainted environment of WinCE anyways, and here things can be done just as effectively (and actually better, due to the lack of required context switching) by moving the logic inline to the main thread.

    The only downside to this is that network events might not be processed if you’ve got a modal dialog up, but the only modal dialog that’s nonfatal in WinCE is the about dialog, and it’s fullscreen. Not much point in leaving that up all day, or so goes my take on the subject, so I just went with MWFMO on a single thread.

  3. Mark Steward says:

    That’s awesome! I guess this is why Pocket PCs have such a nannyish power policy (http://blogs.msdn.com/446240.aspx) – to encourage porting.

    Are you planning on putting your updated sources anywhere? I haven’t seen any traffic on Teamforge since March.

    Cheers,
    Mark

  4. Skywing says:

    Sure. I’ve put up a snapshot of the source and a release WM6 binary here:

    http://www.nynaeve.net/Skywing/PocketPuTTY.zip

    I use VS2005 SP1 and the WM6 Refresh SDK for building it.

    The main changes I made apart from Masaki Saeki‘s (who seems to be as close to a new maintainer as anyone) are the following:

    – a horrendous hack to get page up / page down / the scroll wheel working. I’d love to know the correct way to differentiate those keys from up arrow / down arrow, because the approach I took is well and truly awful, even if it does work.
    – various badness in networking support repaired (unbreaks SSH forwards), as I mentioned above
    – a restart session item on tools menu if the session is disconnected
    – battery meter added to about dialog, since I’m often in PuTTY and going to the settings screen to check battery life is a pain, and the battery meter at the top only seems to have 3 or 4 states of precision (ugh). Might as well put something of value in the about box since it’s on the tools menu…

  5. […] Nynaeve Adventures in Windows debugging and reverse engineering. « How to not write code for a mobile device […]

  6. Skywing says:

    Just a quick note that I updated the PocketPuTTY zip I put out there earlier.

    – Added some enhancements to the resize logic to not wake network unnecessarily if PocketPuTTY isn’t active
    – Added some extremely rudimentary autoreconnect support (may be of some limited use if you use screen, requires manual regedit to configure, beware)
    – Added support for dialing a network connection if one isn’t present, like Pocket IE, so we don’t just stupidly fail right away in that case. The network connection will also be kept as long as the session is alive.

    That’s most of the things I was wanting to change with PocketPuTTY (so far, anyway). Source is included if anyone else wants to pick up improving it from there (feel free to send me patches so I can keep my copy up to date, if you don’t mind). As far as I know, PocketPuTTY.net is unfortunately dead, so there isn’t really any formal maintainer anymore. :(

  7. Alex Perez says:

    Hi there,

    I’ve got a proposition…Let’s band together and collectively help maintain PocketPuTTY. It is far too valuable of a tool to simply die. I’ve contacted and am waiting to hear back from the domain owner and pocketputty primary e-mail address, and I hope you’ll consider speaking further with me. Shoot me an e-mail, or if you’re more the chatty type, we can always communicate via IM/SMS/phone.

  8. Hey

    Having scroll bound to pgup/pgdn is really nice. Works with the D-Pad on my Touch Diamond. And the whole app actually runs faster now too.

    But there’s a slight problem: The big finger-friendly HTC soft keyboard. If I use that, I get double inputs for keys :/

    Oddly enough, the default tiny winmo keyboard works fine. It’s just really painful to type with that compared to the big HTC keyboard.

  9. Skywing says:

    Jani: I’ve got the same problem. Unfortunately, the IME HTC ships with their newer devices (eT9) seems to be a bit braindead and doesn’t synthesize key up / key down messages properly.

    PuTTY uses key up / key down messages and not WM_CHAR for its input processing internally. That code is unfortunately a big, hairy spaghetti mess which I’d really rather not deal with rewriting if at all possible.

    At this point, I have pretty much just relegated myself to using the hardware keyboard on my Touch Pro. I suppose it could be a problem on the Touch Diamond or other keyboardless models, though.

  10. tmzt says:

    Is the source code available anywhere? Is this the same or what are the differences with the htc-pocketputty patchset? The main feature I’m missing, now present on PuTTY, is the ability to connect to forwarded ports from a remote device.