Karl Hans Janke Kollaborativ
Heute die Welt, morgen das Sonnensystem!
<< prev next >>

Getting FreeBSD on the Net via UMTS

So, now I know how to make these USB UMTS stick thingies work…


I've been meaning to get one for a while, so I got a cheap SIM-locked stick with a prepaid plan for this year's post-christmas gadget shopping. I'm recording how I got it to work as much for my own sake as anyone else's…

For FreeBSD, you need the u3g driver. My model is a HUAWEI E1750, which is one of several supported by the driver. Here's what dmesg shows:

ugen3.2: <vendor 0x12d1> at usbus3
ugen3.2: <vendor 0x12d1> at usbus3 (disconnected)
ugen3.2: <HUAWEI Technology> at usbus3
u3g0: <HUAWEI Technology HUAWEI Mobile, class 0/0,
    rev 2.00/0.00, addr 2> on usbus3
u3g0: Found 4 ports.

Note the 4 ports message. These things act like an old modem, presenting a virtual serial port on which they accept AT commands. Just like old times. Actually, they often present several ports serving different functions.

$ ls /dev/cuaU?.?
/dev/cuaU0.0    /dev/cuaU0.1    /dev/cuaU0.2    /dev/cuaU0.3

You have to find the one to use by experimentation. I learned that screen can actually be used as a terminal emulator for this (instead of the clunky old minicom):

$ screen /dev/cuaU0.0

Type AT and see if you get an OK reply.

Most sticks also present mass storage devices. There is usually an emulated CD drive that contains driver software for Windows and MacOS. Some models appearently require this disk to be ejected before even switching on the modem part. I'm not sure if mine does; the u3g manpage states that it should happen transparently (look for u3gstub).

This model also has a microSD slot that can be used like any regular usb storage device.

cd0 at umass-sim0 bus 0 scbus0 target 0 lun 0
cd0: <HUAWEI Mass Storage 2.31> Removable CD-ROM SCSI-2 device 
da0 at umass-sim1 bus 1 scbus1 target 0 lun 0
da0: <HUAWEI SD Storage 2.31> Removable Direct Access SCSI-2 device 

Since the SIM card is usually protected by a PIN, one needs to enter this before it will perform its function. These and other UMTS-specific functions are simply accessed by special AT commands. Many have a query variant ending in a question mark that will report the current status and a set function with an equals sign.

> AT+CPIN=1234

If you don't care about feedback, the PIN entry can be done by writing directly to the device file.

$ echo "AT+CPIN=1234" > /dev/cuaU0.0

My device now signals its ready status by blinking its LED in a different color and rhythm.

Lots of fiddling later…

Now for the PPP connection (just like old times!), in /etc/ppp/ppp.conf:

 set log Phase Chat LCP IPCP CCP tun command +connect
 set device /dev/cuaU0.0
 set speed 460800
           \"\" \
           AT OK-AT-OK \
           AT+CFUN=1 OK-AT-OK \
           AT+CSQ OK \
           AT+CGDCONT=1,\\\"IP\\\",\\\"internet\\\" OK \
           AT+CGACT? OK \
           AT+CGATT? OK \
           ATD*99***1# CONNECT"
 set timeout 180			# 3 minute idle timer (the default)
 set ifaddr
 set vj slotcomp off
 set crtscts on
 add default HISADDR   # set default route
 enable dns            # set dns servers in resolv.conf

There is a bunch of stuff in there I just copied from examples on the web. Let's see:

set log Phase Chat LCP IPCP CCP tun command +connect

This makes ppp write all kinds of stuff to syslog (/var/log/ppp.log). Very useful if something goes wrong, but completely optional. The keywords after set log select different parts of the whole exchange and can be left out individually if desired.

set speed 460800

No idea if this is necessary. All kinds of baud rates seem to just work.


The dial setting is the conversation script ppp follows in order to set off the right sequence of AT commands that open the connection. This is actually executed by chat(8). See that manpage for the syntax. The first line sets abort conditions. If the modem responds with BUSY, NO CARRIER or ERROR to any command, ppp will consider the connection attempt failed.


This one uses a subexpect/subresponse pair (-AT-OK) and just makes sure that the modem responds (two tries).


This command turns the device on if it doesn't do it automatically. Not sure what on means exactly, maybe that it actually goes on the air looking for its network. My device does this automatically after entering the PIN. (I think that's what the changed LED pattern actually means.) Anyway, the command just becomes a no-op when it is issued again.


This asks for the signal strength. Not really necessary, but maybe it fails if there is absolutely no signal.

AT+CGDCONT=1,\\\"IP\\\",\\\"internet\\\" OK

This is somewhat important. It sets the APN. I'm actually not sure what that is, but I'm guessing some kind of logical access point that the mobile network operator can define. It's just called internet in my case, you have to set the right one for your network. The Web has lists of these. Google for umts apn setting.

Actually, the command sets a bundle of parameters known as a PDP context. There can be many of these, identified by numbers, and the modem can be switched around among them.


Asks the modem which of the above-mentioned contexts is active. Not sure why this is necessary or useful, copied it from an example.


Asks the modem whether it is attached to the GPRS service. Presumably this can fail.


Finally, this is the dial command that opens the PPP connection. The number 99 seems to be standard. The part ***1 is optional and specifies the PDP context to use.

BTW, I'm guessing the ATD command can also be used to dial the magic numbers used for activating prepaid time on the card. Will have to try this later.

Enough AT commands, back to ppp settings:

set ifaddr

This is another important one. I didn't look it up in the docs, but one thing it accomplishes is explicitly setting the point-to-point address on the network interface. Appearently the necessity of this depends on the setup of the peer, i.e. some supply their own address, some don't. Mine didn't and I always got this in the log:

tun0: Warning: iface add: ioctl(SIOCAIFADDR,
    -> Destination address required
tun0: Error: ipcp_InterfaceUp: unable to set ip address

The last two interesting ones are these:

add default HISADDR   # set default route
enable dns            # set dns servers in resolv.conf

And that's basically it. Now

$ ppp -ddial o2

will establish the connection, disappear into the background, and keep it open until killed. There are a few other modes besides ddial, consult the manpage.

Interesting links: