You would think that writing a program to talk dirty to the GSM controller in the Openmoko Freerunner wouldn't be at the top of many peoples TODO lists. After all, it has been done. Multiple times. And having yet another implementation (with doubtlessly a different set of bugs) is just going to hurt interoperability of applications. But I did anyway.
My main reason for heading in this directing is that I have an irrational fear of/ dislike for D-BUS. And the only really interesting gsmd implementation for the Freerunner (the FSO framework one) uses D-Bus for information and control. As a secondary reason, writing code is a good way to learn about something. And it is fun.
I tried to bring two main "Unix" concepts to the design for my gsmd. The first is "everything is a file". In this context, I interpret that to suggest that where possible communication with gsmd should be done via files. So status information such as Carrier, Cell Name, Signal Strength and even Calling Number and communicated by gsmd writing the values to files. In particular, files in /var/run/gsm-state. Any program that wants to be aware of these values can read the files, or watch for changes with dnotify or inotify or even simple polling.
Similarly information is communicated to gsmd using files. Flight mode is selected by writing to /var/lib/misc/flightmode/enabled. Whenever this file is non-empty, gsmd gets notified using dnotify and it takes action appropriately. Similarly suspend/resume is managed using file-based communication as I'll discuss later.
The other "Unix" concept that I tried to included is "one tool, one task". So there are lots of things that gsmd doesn't do. It doesn't answer the phone or allow calls to be made. It doesn't collect SMS messages when they arrive. It plays no part in GPRS connections. The closest it comes to being involved in any of this is that it writes to a file when there is an incoming call, and to another file when an SMS message arrives. Some other program needs to handle the details.
The "one task" that gsmd does is configure and monitor the phone and make sure it is always in the correct state for the current situation.
The other tasks such as making and taking phone calls can be achieved independently thanks to the GSM multiplexer: gsm07810muxd. Some other program can monitor the 'newsms' file and when it changes, that program can connect to the multiplexer and request the content of any new messages.
There is one main file involved in mediating suspend - /var/lock/suspend/suspend. Any program that wants to provide special handling at suspend time should take a shared lock (flock(LOCK_SH)) on this file, and should watch for changes.
If the file ever becomes non-empty, suspend is pending and the program should do any processing and then drop the lock. Before dropping the lock, it should probably take a lock on /var/lock/suspend/next_suspend, as that will guarantee that it can observe the following resume (when that file is renamed) and can act before the next suspend (as that file will become the suspend file for the next cycle).
To enable this, a simple script called interlock is installed in /etc/apm/event.d. This scripts modifies the files as required and waits for a flock(LOCK_EX) on the suspend file before allowing suspend to continue.
This, combined with a simple library to lock and monitor the two files allows gsmd to easily respond to suspend and resume events.
gsmd isn't perfect yet. It probably doesn't handle being out of signal range well, and has no functionality to support PIN codes or Roaming. That'll probably come one day.
It also assumes that the +CBM response that reports the Cell name has the whole name on a single line. This turns out not to be the case. It looks like I probably need to collect lines until I find a blank line.
You can find all this code in my git repository, which can be cloned or pulled from git://neil.brown.name/project or browsed at http://neil.brown.name/git/. You will need my modified gsm0710muxd and various code from the freerunner project, particularly gsm/gsmd.py and various bits from lib.