High-speed cellular wireless modems (e.g. EVDO, HSPDA) in Ubuntu GNU/Linux 6.10


Note: If you are running Ubuntu 7.04 or greater, this article is no longer relevant. Your EVDO modem should be detected and run at a higher speed automatically.

I’ve been raving about cellular wireless modems/data cards for a while now. While they’ve been available for a long while, they’ve finally become practical with networks such as EVDO and HSPDA that offer broadband-like speeds. I personally own a Novatel Merlin S720 that I use with Sprint’s Mobile Broadband service.

Most of these datacards are easy to get running in Linux–I actually setup mine in Linux faster than I did in Microsoft Windows. However, due to some shortcomings in the kernel used by Ubuntu GNU/Linux 6.10, you cannot take advantage of the speeds that these modern wireless networks offer.

This article talks about some of the problems of the often-used usbserial driver, and how to use the better-performing airprime driver instead.

Using the usbserial vs airprime drivers

Many instructions on the Internet that detail how to use these modems in Linux talk about using the usbserial driver, often having to pass custom vendor and device IDs to the driver so that it recognizes the device. While this does work, the usbserial driver was not made to handle high-speed devices like EVDO and HSPDA modems. It has some small I/O buffers, and with these small buffers you will not be able to get transfer speeds greater than 60 KB/sec. There are patches available to increase usbserial’s buffer size, but with the airprime driver, this is not needed.

The Linux airprime driver can operate these modems at full-speed, after support for larger buffers was added in 2.6.18. Unfortunately, the driver has to be patched to recognize any kind of new device.

This doesn’t help me using since I am Linux 2.6.17 on Ubuntu 6.10, and I’ve also no desire to deviate far from the distribution-provided kernel. 2.6.17’s airprime driver does not have the support for large buffers, nor does it contain the driver IDs so that the driver takes control of the device.

I took Andy Gay’s airprime improvement patches and backported them (“backport” is a misnomer since it was so easy), also adding the device IDs from 2.6.20 and a few other popular wireless modem devices (Note: I’ve not personally tested anything but the Novatel Merlin S720).

You can get the patch against Ubuntu’s 2.6.17 kernel, or simply download the entire patched airprime.c file. The patch contains device IDs for:

Kernel and driver setup

Install the minimum build environment, Linux sources, and Linux headers for your currently-running kernel: apt-get install build-essential linux-headers linux-source

Go into /usr/src/ and uncompress the kernel source code: cd /usr/src tar xjvf linux-source-2.6.17.tar.bz2

Enter the directory containing the airprime driver:

cd linux-source-2.6.17/drivers/usb/serial

Now, either apply the patch, or replace airprime.c with the pre-patched version (see above for download links).

If patching:

patch -p0 < airprime-sjain-012807.patch

If replacing (not recommended, patching is safer):

mv airprime.c airprime.c.bak mv airprime-sjain-012807.c airprime.c Normally, to patch a driver, you have to recompile the entire kernel tree and replace all the kernel modules as well as the core kernel image itself. But since we are using Ubuntu’s sources, we can only compile the driver’s that we need and overwrite the old ones.

To compile only the airprime dirver (this actually compiles all drivers in the directory): make -C /lib/modules/uname -r/build M=pwd

Then, install it (you need root privileges to overwrite the existing driver) and update module dependencies: sudo cp airprime.ko /lib/modules/uname -r/kernel/drivers/usb/serial/airprime.ko sudo depmod -a

You can either remove and reinsert the driver, or take the easy way out and reboot. Your device should now be recognized by the airprime driver, and a new device node /dev/ttyUSB0 created.

Some ending notes…

The above installs files outside the knowledge of Ubuntu’s package manager. If your kernel ever gets upgraded, dpkg will happily overwrite your custom driver, and you will have to go through the above procedure again. To prevent this happening at an inopportune time, set your kernel’s package status to “hold” to prevent automatic upgrades.

If you’re using Sprint’s Mobile Broadband service as I am, you may want to look the sister article I’ve written, Sprint’s Mobile Broadband on Ubuntu GNU/Linux 6.10.

Like this article? Please support my writing! Flattr my blog (see my thoughts on Flattr), tip me via PayPal, or send me an item from my Amazon wish list.


Samat's picture

Thanks! The patch isn’t a straight backport (I added some additional device IDs), so I’m not sure how likely this will get merged in…

Regardless, I’ve subscribed myself to the bug and will help look after it.

Anonymous's picture

I’ve followed these instructions, but am a total newb at compiling kernel modules, and am having trouble during the make step.

A couple of things I had to differently to get to the make step were:

tar xvf linux-source*.tar.bz2 (note no z option)

then i had to cd into linux-source-2.6.17/drivers/usb/serial instead of just drivers/usb/serial

however after patching make fails with the following error:

root@my-laptop:/usr/src/linux-source-2.6.17/drivers/usb/serial# make -C /lib/modules/uname -r/build M=pwd make: Entering directory /lib/modules/2.6.17-11-386/build' make: *** No targets specified and no makefile found. Stop. make: Leaving directory/lib/modules/2.6.17-11-386/build’

any suggestions?

this is for a merlin s620


Samat's picture

I’ve made corrections to the bit about the tarball extraction and directories–thanks!

Do you have the linux-headers package installed? I think this may be a dependency missing from the instructions…

AndyHitchman's picture

I’m trying to follow your instructions to add my Bigpond Maxon modem to the airprime driver. I’ve got as far as:

make -C /lib/modules/uname -r/build M=pwd

but this returns an error:

make: Entering directory /lib/modules/2.6.15-23-386/build' make: *** No targets specified and no makefile found. Stop. make: Leaving directory/lib/modules/2.6.15-23-386/build’

The build directory didn’t actually exist the first time I ran the make command, so I created the directory (empty).

So obviously I’m missing something. As a complete newbie when it comes to recompiling kernels I have no idea what this means or how to proceed.

Any assistance greatly appreciated. Using Ubuntu 6.06 with the 2.6.15 kernel.



julian (anonymous from make fails post)'s picture

It appears that the linux-headers package didnt make the symlink to /lib/modules/’uname -r’/build. once I put it there, I was able to build the kernel module. I wasn’t able to get an ip address after running the connection script though…

I just installed from scratch with edgy (instead of the upgrade from breezy that i had before) and it seems to have correctly added the symlink, not to mention correctly running the -generic kernel instead of the -i386 on my latitude d820.

Anyways, i’ll go through the instructions again and see if i have success.

Chanders's picture

I follow your steps to a T and everything works perfectly. However when I insert the card and run dmesg I see that the modem is connected to

/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 /dev/ttyUSB4 /dev/ttyUSB5

After doing this I cannot get the modem to dial when configured with wvdial.conf.

I tried your easy connect scripts but when I run the pon command nothing happens and I see no error messages…

Any ideas?

chanders's picture

Everything compiled ok and dmesg gives this when the card is plugged in [17179755.688000] usb 4-2: new full speed USB device using uhci_hcd and address 2 [17179755.908000] usb 4-2: configuration #1 chosen from 1 choice [17179755.988000] usbcore: registered new driver usbserial [17179755.988000] drivers/usb/serial/usb-serial.c: USB Serial support registered for generic [17179755.988000] usbcore: registered new driver usbserial_generic [17179755.988000] drivers/usb/serial/usb-serial.c: USB Serial Driver core [17179756.000000] drivers/usb/serial/usb-serial.c: USB Serial support registered for airprime [17179756.000000] airprime 4-2:1.0: airprime converter detected [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB0 [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB1 [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB2 [17179756.000000] airprime 4-2:1.1: airprime converter detected [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB3 [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB4 [17179756.000000] usb 4-2: airprime converter now attached to ttyUSB5 [17179756.000000] usbcore: registered new driver airprime [17179756.032000] usbcore: registered new driver cdc_acm [17179756.032000] drivers/usb/class/cdc-acm.c: v0.25:USB Abstract Control Model driver for USB modems and ISDN adapters

However it seems it becomes registered to USB0-USB5 and the ppp scripts keep saying ‘cannot open modem’ no matter which device i choose..

Please, any ideas?

Samat's picture

The modem is the first device, /dev/ttyUSB0.

I think the rest are used for other features: one is a control interface, so one can check the signal strength while using the main modem device, and if using the S720/related devices, an interface to the built-in GPS receiver. I’ve not figured out how to use either of these yet.

John's picture

I’m having trouble at the command:

make -C /lib/modules/uname -r/build M=pwd

Others have been posting about problems with this too.

My question is, does uname mean username and pwd mean password? there is no uname file or directory obviously and I just would like an explanation of what the single quote sections of this command actually do or mean. Please let me know as I can’t go to the next step until I can do this.

One last thing. I am two days old in the linux world, so please try to help me by being very descriptive or “step” oriented. I have yet to learn the acronyms or the “obvious” stuff.

Thanks, John

Samat's picture

This article assumes a certain comfort with the Linux command line–it’s not mentioned but important. Some parts will be confusing without this comfort or understanding.

Contents within backticks (i.e. “", you're missing these when you pasted the command) tell the shell to execute these commands.uname -r` prints the running kernel’s running release, and pwd prints the current directory. Both uname and pwd are standard UNIX commands and have man pages where you can read more information about them.

Paul Peterson's picture

I have been meesing around with this card for a few days. I used the patch and then added a new line for the Maxon modem vendor and product (0x16d8, 0x5111) to airprime.c and recompiled the kernel. Everything worked except the modem does notrespond. I simply get a “Connect script failed”. It works fine (but slow) under the standard cdc_acm driver and I use the same connect script. The device does show up in /proc/bus/usb/devices. I am at a loss here as I don’t know what to do next. Any clues would be most appreciated.

Thanks, Paul

Samat's picture

Does the modem work with usbserial? Those that work with usbserial should work with airprime; those using CDC, I’m not sure…

Anonymous's picture

how do you make it switch from 1xrtt? to evdo ?? or is this automajik…

Samat's picture
how do you make it switch from 1xrtt? to evdo ?? or is this automajik…

Switching from 1xRTT to EVDO is not automatic (though I believe EVDO to 1xRTT is). On Windows, I believe this is done manually by the connection manager software…

Anonymous's picture

.>> Switching from 1xRTT to EVDO is not automatic

True, because the service provider’s network controller for EVDO is not the same server as the network controller for RTT.

What the modem “sees” at the cell site drives a lot of this process:

First, the modem will prefer to use EVDO. It will try to register with the EVDO network controller unless EVDO is unavailable. If the EVDO signal is too weak (or doesn’t exist, or becomes too weak), the modem will try to register with the RTT network controller.

Since the modem prefers EVDO… If the modem is instead using RTT it is assumed that the modem is using RTT because EVDO is unavailable. Assuming this, it would make no sense for the modem to try sometime later to contact an EVDO network–after all, it tried to do that once already and failed.

redarrow's picture


I can’t seem to get this to work on my Fedora Core 6 system..

I managed to compile it, but I needed to make one small change:

include "usb-serial.h"


include <linux/usb/serial.h>

It then compiled, but on trying to insert the module it crashes with: FATAL: Error inserting airprime (/lib/modules/2.6.18-1.2798.fc6/kernel/drivers/usb/serial/airprime.ko): Invalid module format

And the the system log shows: drivers/usb/serial/usb-serial.c: USB Serial Driver core airprime: disagrees about version of symbol struct_module

My Kernel version is: 2.6.18-1.2798

Any ideas? Thanks!

Anonymous's picture

Great tutorial! I’ve gotten everything working, but I’m not sure how to tell the type of connection. How can I tell if I’ve connected at 1xRTT or EVDO speeds? Running Ubuntu Edgy Eft.

pieri's picture

Hy all I just upgraded from 6.10 to 7.04 and the patch above doesn’t work anymore. Did any of you find a solution to make this hsdpa card work in ubuntu feisty? Is there any other patch available?

Thanks a lot pieri

Samat's picture
Hy all I just upgraded from 6.10 to 7.04 and the patch above doesn’t work anymore. Did any of you find a solution to make this hsdpa card work in ubuntu feisty? Is there any other patch available?

This patch is no longer needed for Ubuntu 7.04, as the kernel it uses (2.6.20) already includes an updated airprime driver.