There are two major mobile broadband technology families: GSM/UMTS (which three quarters of the world uses) and CDMA/EVDO (used by the rest). Keep in mind that UMTS uses CDMA as the radio technology, but incompatibly from CDMA/EVDO.
Back to School
GSM is a TDMA (Time Division Multiple Access) technology; communication is divided into a number of slots in which specific devices talk. Each slot contains voice, data, or signalling information. When it’s not your turn, you can’t talk. Pretty simple, but given that it’s a TDMA technology, it’s prone to multipath interference and hard capacity limits. You also have to carefully plan out your cell layout to ensure that adjacent towers don’t use the same frequency.
CDMA, on the other hand, is an ingenious spread-spectrum technology. It’s got a great back story with movie stars and a war and stuff. In contrast to GSM, in a CDMA system every user talks at the same time. Each user is given a unique sequence of zeros and ones called a “spreading code” which is used to modulate the data stream over a certain frequency range (hence the spread-spectrum part). On the receive side, when you know a user’s spreading code you apply it to the RF signal and retrieve the original data. Each user in the cell just sees every other user’s signal as slightly increased background noise. This is why CDMA is extremely robust against snooping and multipath interference, and why its capacity gracefully degrades as cell utilization increases.
What about Qualcomm?
Qualcomm holds many of the patents on CDMA since they spent a ton of time and money turning CDMA into a viable cellular radio technology 20 years ago. They are also one of the largest sellers of cellular chipsets in the world. We as open-source developers have to care, because their stuff shows up in tons of the devices we support. Users don’t like being told “no”.
Most mobile broadband devices (Qualcomm’s included) appear as USB interfaces providing two or more serial ports. One port is usually AT-command capable. If you’re lucky, you get a secondary AT-capable port to use for signal quality and status while the primary port is using PPP for data transmission. Most GSM/UMTS modems have a second AT port. Most CDMA modems do not.
So when your device only has one AT-capable port, what language do the other ports speak?
Proprietary Protocol #1: QMI
This protocol is found on newer Qualcomm chipsets like the MSM7k series that show up in Android handsets Qualcomm Gobi data cards. Google exposed some of the QMI protocol in the Android drivers. Other details have recently turned up through the Gobi Linux driver sources, though Qualcomm doesn’t distribute sources for the “QCQMI DLKM” that probably contains the protocol mechanics. It shouldn’t be too hard to reverse-engineer most of the protocol given these sources and a USB sniffer, but nobody has had the time yet. QMI uses an HDLC-type framing which is quite common in proprietary mobile broadband protocols: a CRC-16 and 0x7E terminates a frame, and the frame is escaped such that 0x7E doesn’t show up in the data. But since we haven’t reverse-engineered QMI yet, it isn’t the main focus of this post.
Proprietary Protocol #2: DM
Diagnostic Monitor is an older protocol found in most Qualcomm devices. I’ve been interested in QCDM for a while, since without it, you can’t get signal strength and status from most CDMA devices while connected. So I’ve been trawling the web for the past couple years looking for anything related to QCDM, and I finally hit the jackpot last fall: the GPL sources for the Sprint-branded Linksys WRT54G3G-V2 router, which have since disappeared. They include a GPL-licensed tool called ‘nvtlstatus’ which implements various pieces of the QCDM protocol. The code is complete junk (as you’d expect from many embedded device manufacturers with schedules to hit) but it worked.
There’s also a sketchy Chinese package called “CDMA_Test.rar” that includes lists of the NVRAM items and some of the DM command numbers. While not GPL, we can use the command numbering and structure definitions because it falls under the phonebook and interoperability copyright exceptions. Additionally, there’s the TCL-based (ick) “RTManager” tool that implements some interesting QCDM commands, which, while we can’t use any of the code, is useful for structure field names that I hadn’t already guessed. Third, some guy did some reverse engineering of Novatel devices on Windows and built up a list of commands, subsystems, and NVRAM locations that were useful for confirming what I found in the other sources.
So through a combination of reverse engineering and these sources I wrote libqcdm, which we now use extensively in ModemManager for controlling CDMA devices.
Since DM is a pretty old protocol (2000 and possibly earlier), many of the commands are purely historical and currently unused. The most interesting ones are:
- DIAG_CMD_VERSION_INFO: grabs firmware build dates and version information
- DIAG_CMD_ESN: grabs the CDMA device’s ESN, which is essentially the IMEI of a CDMA device
- DIAG_CMD_NV_READ and DIAG_CMD_NV_WRITE: NVRAM read/write commands, see below
- DIAG_CMD_SUBSYS: subsystem commands; see below
- DIAG_CMD_STATUS_SNAPSHOT: gives information about the current state and registration of the device on the CDMA 1x network
But given that many aren’t really used anymore, Qualcomm started running out of command IDs a long time ago…
So Qualcomm used command 75 (DIAG_CMD_SUBSYS) to extended the number of available commands; this command takes a subsystem selector and a subsystem command ID, thus getting around the original 8-bit command ID limitation.
There are a number of standard subsystems (Call Manager, HDR Manager, WCDMA, GSM, GPS, etc) but each manufacturer generally implements their own subsystem too. In this way QCDM isn’t that different from AT commands; while supposedly standardized, each manufacturer inevitably implements a bunch of proprietary commands for their own device because the specs simply don’t cover everything. This just makes our life harder.
The currently identified subsystems are:
- Call Manager: the most important command here reports the general state of the device, including the registered SID/NID, the terminal state (online/offline), the network mode (2G/3G), and various preferences that control which network the mobile registers with. This is what we use to determine online/offline mode for CDMA devices since there aren’t any “standard” AT commands we can use to detect both 1x and EVDO registration. Other commands start and end voice or data calls.
- HDR (High Data Rate, ie EVDO): the most important command here provides EVDO state, which is mostly taken from the state machines specified in the IS-856 standard. This lets us figure out if the modem is registered on the EVDO network or the CDMA 1x network.
- Novatel: only implemented on Novatel Wireless devices, obviously. But it provides access to a lot of stuff we want: the Extended Roaming Indicator (ERI) which shows detailed roaming state, the current access-technology the device is using (AMPS, digital, IS-95, CDMA 1x, EVDO r0, EVDO rA, etc), the voice mail and SMS indicators, and more.
- ZTE: for ZTE devices, obviously. I actually did reverse engineer this one using a ZTE AC2726 kindly provided by Huzaifas S. from Red Hat India. All we’ve got so far is the signal strength, the other fields of the command are unknown.
There are also GSM and WCDMA subsystems used with Qualcomm UMTS chipsets, but since most UMTS devices have multiple AT-capable ports we’re less interested in using QCDM there.
Each device has a number of NVRAM locations in which it stores various parameters like mode preference, roaming, home networks, radio parameters, and a whole bunch of other stuff. Not all devices implement every location. I’ve only included the locations that we actually use in libqcdm, but there a couple thousand. The ones we currently use are:
- DIAG_NV_MODE_PREF: sets the mode preference: analog (ie AMPS), digital (TDMA), CDMA 1x, or EVDO (HDR)
- DIAG_NV_DIR_NUMBER: retrieves your Mobile Directory Number (MDN), aka your phone #
- DIAG_NV_ROAM_PREF: controls whether your device will roam on a partner network or not
The values each contains took a bit of time reverse-engineer using the Sprint connection manager, 3 different Sprint CDMA cards, and some USB traces, but now we’ve got the important parts.
Pulling It All Together
Earlier this year we had a number of bugs from Russian, Indian, and Czech Fedora users where ModemManager simply wouldn’t connect. MM is pretty clever (a good thing) but the IS-707 AT commands aren’t useful enough to tell us what we need (not good). The IS-707 standard AT+CAD? and AT+CSS commands really apply to the CDMA 1x network, not the EVDO network, and all these users had EVDO-only plans. So when ModemManager checked AT+CSS and found that the device wasn’t registered, we sat around polling the registration state for a while. The modem was already registered on the EVDO network, but not on a CDMA 1x network; of course AT+CSS doesn’t tell us that so MM got it wrong.
The real fix was to utilize QCDM and ask the Call Manager whether the modem was online or not, and if so, whether it had a 1x or an EVDO connection. Sounds simple, but it took a lot of work to get there.
Next, since most CDMA devices only expose one AT-capable port, we need a way to get signal strength from the device while it’s connected and the primary port is talking PPP. I’ll cover that in another blog post; stay tuned. We still don’t have a good way to figure out which EVDO revision (either 0 or A) we’re using, nor can we get a reliable roaming indicator yet.
The Kernel Side
Many devices provide the AT port via the standard CDC-ACM serial mechanism, which is picked up automatically by the kernel drivers. But their QCDM-capable ports are only exposed via vendor-specific USB interfaces, so I created the qcaux driver to handle these ports; it’s in the 2.6.34 kernel. With qcaux.ko and a recent version of ModemManager stuff will Just Work.
Why You Care
First a big shout to Qualcomm for keeping this shit secret. NOT. Double-plus-shout-out for keeping QMI secret; it’s a pretty simple protocol and there’s not much there worth keeping under wraps. It might be nice to let open-source developers actually talk to your hardware.
With that out of the way, you care because we now have better support for a whole bunch of mobile broadband devices. We even have support for CDMA signal strength while connected for the vast majority of CDMA devices that only expose one AT port. I’ll talk about that later, since it’s quite an interesting story.
Why Sierra Wireless Rocks and Qualcomm Doesn’t
Buy Sierra stuff. It’s top quality and they actually care about open-source, unlike Qualcomm’s mobile broadband division. Last year I initiated a dialogue with Sierra about releasing some details of their proprietary Command and Status (CnS) protocol. Being able to talk CnS to their modems gets us a lot that AT commands and even QCDM don’t provide, like roaming indicator, access technology, and RSSI.
And guess what? They actually listened, did the work, and put the documentation under a Creative Commons license too. I hear it’ll show up soon on their support site if it’s not there already (document #2131024, “CDMA 1xEV-DO CnS Reference”).
Sierra rocks. Now if only Qualcomm would do it too…