Using the Verizon Wireless AirPrime 5220 1xEV-DO Card With Linux

Phil Karn

Verizon Wireless has recently begun to deploy the Qualcomm-developed 1xEV-DO wireless internet service, which they market as BroadbandAccess. It was first deployed in San Diego and Washington, DC, and on January 9, 2004 Verizon announced plans to roll it out nationwide. As of September 2004, I know of one additional city: Las Vegas, NV; Verizon doesn't seem to be announcing specific cities in advance.

At present (September 2004), the Air Prime 5220 is the only device available for this service. Verizon officially supports it only on Microsoft Windows, and Apple has a driver for Mac OS X. Fortunately, it isn't hard to get it working on Linux. (Note: AirPrime was acquired by Sierra Wireless in the summer of 2003).

Initialization and Setup

When you first get the card, you should first set it up on a Windows machine with the supplied software. Once the service has been activated, you can use it on Linux. You won't be able to use the fancy "connection manager" software supplied with the card, but you can connect to the Internet. And that's all that really counts!

Card Architecture

It may help to know what's actually inside the 5220 card. It contains a Qualcomm MSM 5500 mobile station modem chip that implements the actual 1xEV-DO functionality. This chip has a native USB 1.1 interface that emulates two USB serial ports. The first provides a classic serial modem interface that accepts AT commands and PPP data. The second is reserved for diagnostics and is unused. To package this chip in a PC Card, AirPrime added a Lucent OHCI (Compaq-style) USB 1.1 host controller and a Cardbus interface. The MSM is hardwired to the USB host controller as its only slave device.

The 5220 card cannot make voice calls. Several other features of the MSM 5500 are also unavailable.

To get the card going on Linux, you first must install the Linux driver for the OHCI USB host adapter and then a Linux USB driver for the MSM itself. Finally, the Linux point-to-point protocol daemon pppd can be configured to place calls over the MSM's virtual serial port.

Checking The Card

If you don't already have PCMCIA/Cardbus support on your Linux laptop, turn it on. When you insert the card, it will appear (like any Cardbus device) as a PCI device. Here is how the card appears on an IBM Thinkpad T23 running the 2.4.24 kernel:
# lspci -vv -s06:00.0
06:00.0 USB Controller: Lucent Microelectronics USS-312 USB Controller (rev 10) (prog-if 10 [OHCI])
        Subsystem: Lucent Microelectronics USS-312 USB Controller
        Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
        Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- SERR- 
#

Installing the USB Host Adapter Driver

The Lucent OHCI USB host controller in the 5220 card is supported by the stock Linux usb-ohci driver. So your first step is to build and install this driver if you don't already have it on your system. Ensure that your Linux kernel .config file contains either CONFIG_USB_OHCI=m or CONFIG_USB_OHCI=y. I personally prefer to build my drivers as modules (CONFIG_USB_OHCI=m), as that's more flexible than hardwiring them into the kernel.

If you configure the OHCI driver as a module, you can either set up the Linux hotplug subsystem to load it on demand when this card is inserted or you can append usb-ohci to /etc/modules so that it will be loaded at boot time.

Since changes to /etc/modules require a reboot to take effect, you can avoid a reboot by also manually installing the module into your running kernel with the command modprobe usb-ohci .

Note that you will need to be root both to edit /etc/modules and to run the modprobe command.

Verify that the usb-ohci driver found the 5220's USB host adapter with the MSM chip attached:

$ cat /proc/bus/usb/devices
T:  Bus=04 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0000 ProdID=0000 Rev= 0.00
S:  Product=USB OHCI Root Hub
S:  SerialNumber=e8987000
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms
T:  Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=16 #Cfgs=  1
P:  Vendor=0f3d ProdID=0112 Rev= 0.01
S:  Manufacturer=AirPrime, Incorporated
S:  Product=AirPrime CDMA Wireless PC Card
C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=128ms
E:  Ad=8a(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=0b(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
I:  If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=05(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
[remainder of output removed]

Installing the Serial Driver

The Qualcomm MSM chip inside the 5220 emulates two serial ports over its USB interface. Unfortunately, the device does not seem to advertise itself as a generic modem or serial port, so we must specify the vendor and product IDs to the Linux USB serial driver so it will recognize it. This can be done with command-line parameters when the module is installed. This command will immediately install it into your running kernel:
# modprobe usbserial vendor=0xf3d product=0x0112
and appending this line to /etc/modules will cause it to be automatically (re)loaded the next time you reboot:
usbserial vendor=0xf3d product=0x0112
Verify that the usbserial driver found the MSM by looking at /var/log/messages or the output of the dmesg command. It should look something like this:
usb.c: registered new driver serial
usbserial.c: USB Serial support registered for Generic
usbserial.c: Generic converter detected
usbserial.c: Generic converter now attached to ttyUSB0 (or usb/tts/0 for devfs)
usb.c: serial driver claimed interface c55f9a20
usbserial.c: Generic converter detected
usbserial.c: Generic converter now attached to ttyUSB1 (or usb/tts/1 for devfs)
usb.c: serial driver claimed interface c55f9a38
usbserial.c: USB Serial Driver core v1.4
If you are running devfs, the device file system, the character special devices /dev/usb/tts/0 and /dev/usb/tts/1 should now exist. Otherwise you should make the appropriate nodes if they don't already exist:
# mknod /dev/ttyUSB0 c 188 0
# mknod /dev/ttyUSB1 c 188 1

Configuring PPPD

The next step is to set up the Linux PPP daemon pppd. Create the file /etc/ppp/peers/1xevdo with these contents:
-detach
ttyUSB0
115200
debug
noauth
defaultroute
usepeerdns
user your_telephone_number@vzw3g.com
show-password
crtscts
lock
connect '/usr/sbin/chat -v -t3 -f /etc/ppp/peers/1xevdo_chat'
Replace your_telephone_number with your 10-digit Verizon-assigned telephone number that you received with your 5220 card.

Create /etc/ppp/peers/1xevdo_chat with these contents:


'' 'AT'
'OK' 'ATE0V1&F&D2&C1&C2S0=0'
'OK' 'ATE0V1'
'OK' 'ATS7=60'
'OK' 'ATDT#777'

Finally, append this line to /etc/ppp/pap-secrets:

your_telephone_number@vzw3g.com * vzw
again replacing your_telephone_number with the 10-digit telephone number of your 5220 card. (Why an Internet device that cannot make voice calls should require a telephone number is beyond me.)

Just in case it wasn't obvious, we created a PPP dialup account that can be reached by dialing #777 (#PPP) over /dev/ttyUSB0. Your PPP login name is your 10-digit phone number followed by @vzw3g.com and your password is simply vzw.

Trying it all out

You should now be ready to bring up the link. Run the following command:
sudo pppd call 1xevdo
If you succeed in setting up the link, you will see something like this:
$ sudo pppd call 1xevdo
Perms of /dev/ttyUSB0 are ok, no 'mesg n' neccesary.
Serial connection established.
using channel 1
Using interface ppp0
Connect: ppp0 <--> /dev/ttyUSB0
sent [LCP ConfReq id=0x1    ]
sent [LCP ConfReq id=0x1    ]
rcvd [LCP ConfReq id=0x0   ]
sent [LCP ConfAck id=0x0   ]
rcvd [LCP ConfReq id=0x1   ]
sent [LCP ConfAck id=0x1   ]
sent [LCP ConfReq id=0x1    ]
rcvd [LCP ConfAck id=0x1    ]
sent [LCP EchoReq id=0x0 magic=0xc57d039a]
sent [CCP ConfReq id=0x1   ]
sent [IPCP ConfReq id=0x1    ]
rcvd [LCP DiscReq id=0x2 magic=0x32250cdb]
rcvd [LCP EchoRep id=0x0 magic=0x32250cdb c5 7d 03 9a]
rcvd [LCP ProtRej id=0x4 80 fd 01 01 00 0f 1a 04 78 00 18 04 78 00 15 03 2f]
rcvd [IPCP ConfReq id=0x3 ]
sent [IPCP ConfAck id=0x3 ]
rcvd [IPCP ConfRej id=0x1 ]
sent [IPCP ConfReq id=0x2   ]
rcvd [IPCP ConfNak id=0x2   ]
sent [IPCP ConfReq id=0x3   ]
rcvd [IPCP ConfAck id=0x3   ]
not replacing default route to eth0 [129.46.76.1]
Cannot determine ethernet address for proxy ARP
local  IP address 166.154.180.95
remote IP address 66.174.32.27
primary   DNS address 66.174.6.7
secondary DNS address 66.174.3.7
Script /etc/ppp/ip-up started (pid 3416)
Script /etc/ppp/ip-up finished (pid 3416), status = 0x0
Because of the -detach flag in /etc/ppp/peers/1xevdo, debug messages will continue to appear in this window. I find this useful to see link status at a glance. Do not hit control-C unless you want to bring down the link. Test it from another shell window:
$ ping 66.174.32.27
PING 66.174.32.27 (66.174.32.27) 56(84) bytes of data.
64 bytes from 66.174.32.27: icmp_seq=1 ttl=64 time=608 ms
64 bytes from 66.174.32.27: icmp_seq=2 ttl=64 time=180 ms
64 bytes from 66.174.32.27: icmp_seq=3 ttl=64 time=400 ms
64 bytes from 66.174.32.27: icmp_seq=4 ttl=64 time=190 ms

--- 66.174.32.27 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3038ms
rtt min/avg/max/mdev = 180.092/344.649/608.135/175.670 ms
$
Success! You should now be on the Internet!

Last modified: 17 Sep 2004, Phil Karn