How to make your 3G modem work

USB mode-switching your CD-ROM into a modem

If you plug your USB modem to your computer and it shows up as a CD-ROM drive with Windows drivers, USB_ModeSwitch is the tool for the job. It adds itself couple of rules to udev(7) (in my Gentoo in /lib/udev/rules.d/40-usb_modeswitch.rules) that essentially for each misbehaving device identified by its ATTR{idVendor} and ATTR{idProduct} executes /lib/udev/usb_modeswitch, which in turn should run Tcl script /usr/sbin/usb_modeswitch_dispatcher, which should then automatically do whatever libusb magic is necessary to get the device switched.

Ideal world

# emerge -av usb_modeswitch
and we're done.

Tough reality

There is another way, switching it manually. Here for example is a device that wasn't switched automatically due to a bug and the fact it was connected through two USB hubs:

$ dmesg | tail -n(whatever)
[1055107.384381] hub 1-1.5.6:1.0: state 7 ports 4 chg 0000 evt 0010
[1055107.384710] hub 1-1.5.6:1.0: port 4, status 0101, change 0001, 12 Mb/s
[1055107.535246] hub 1-1.5.6:1.0: debounce: port 4: total 100ms stable 100ms status 0x101
[1055107.615240] usb 1-1.5.6.4: new high-speed USB device number 102 using ehci-pci
--- udev magic stars to run here ---
[1055107.727343] usb 1-1.5.6.4: default language 0x0409
[1055107.728108] usb 1-1.5.6.4: udev 102, busnum 1, minor = 101
[1055107.728126] usb 1-1.5.6.4: New USB device found, idVendor=12d1, idProduct=1520
[1055107.728129] usb 1-1.5.6.4: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[1055107.728132] usb 1-1.5.6.4: Product: HUAWEI Mobile
[1055107.728135] usb 1-1.5.6.4: Manufacturer: HUAWEI Technology
[1055107.728380] usb 1-1.5.6.4: usb_probe_device
[1055107.728388] usb 1-1.5.6.4: configuration #1 chosen from 1 choice
[1055107.729220] usb 1-1.5.6.4: adding 1-1.5.6.4:1.0 (config #1, interface 0)
[1055107.729285] usb-storage 1-1.5.6.4:1.0: usb_probe_interface
[1055107.729297] usb-storage 1-1.5.6.4:1.0: usb_probe_interface - got id
[1055107.729551] scsi171 : usb-storage 1-1.5.6.4:1.0
[1055107.729655] hub 1-1.5.6:1.0: state 7 ports 4 chg 0000 evt 0010
[1055108.726559] scsi 171:0:0:0: CD-ROM            Vodafone CD ROM (Huawei)  2.31 PQ: 0 ANSI: 2
[1055108.730035] sr0: scsi-1 drive
[1055108.730241] sr 171:0:0:0: Attached scsi CD-ROM sr0
[1055108.730320] sr 171:0:0:0: Attached scsi generic sg1 type 5

After executing

$ sudo usb_modeswitch -v 12d1 -p 1520 -V 12d1 -P 1446 -c /usr/share/usb_modeswitch/12d1\:1520
which just says that it should look for a device 12d1:1520 (our fake CD-ROM drive) and turn it into 12d1:1446 using whatever is in that config file.

$ dmesg | more-tail-commands
[1055191.462923] usb-storage 1-1.5.6.4:1.0: disconnect by usbfs
[1055191.466161] usb 1-1.5.6.4: usbfs: process 4356 (usb_modeswitch) did not claim interface 0 before use
[1055191.475332] ehci-pci 0000:00:1a.0: devpath 1.5.6.4 ep0out 3strikes
[1055191.581053] hub 1-1.5.6:1.0: state 7 ports 4 chg 0000 evt 0010
[1055191.581350] hub 1-1.5.6:1.0: port 4, status 0100, change 0001, 12 Mb/s
[1055191.581361] usb 1-1.5.6.4: USB disconnect, device number 102
[1055191.581365] usb 1-1.5.6.4: unregistering device
[1055191.581371] usb 1-1.5.6.4: unregistering interface 1-1.5.6.4:1.0
[1055191.581485] usb 1-1.5.6.4: usb_disable_device nuking all URBs
[1055191.738417] hub 1-1.5.6:1.0: debounce: port 4: total 100ms stable 100ms status 0x100
[1055196.443427] hub 1-1.5.6:1.0: state 7 ports 4 chg 0000 evt 0010
[1055196.443750] hub 1-1.5.6:1.0: port 4, status 0101, change 0001, 12 Mb/s
[1055196.596819] hub 1-1.5.6:1.0: debounce: port 4: total 100ms stable 100ms status 0x101
[1055196.676875] usb 1-1.5.6.4: new high-speed USB device number 103 using ehci-pci
[1055196.788727] usb 1-1.5.6.4: skipped 1 descriptor after endpoint
[1055196.788746] usb 1-1.5.6.4: skipped 3 descriptors after interface
[1055196.789065] usb 1-1.5.6.4: default language 0x0409
[1055196.789799] usb 1-1.5.6.4: udev 103, busnum 1, minor = 102
[1055196.789809] usb 1-1.5.6.4: New USB device found, idVendor=12d1, idProduct=1465
[1055196.789815] usb 1-1.5.6.4: New USB device strings: Mfr=4, Product=3, SerialNumber=0
[1055196.789828] usb 1-1.5.6.4: Product: HUAWEI Mobile
[1055196.789830] usb 1-1.5.6.4: Manufacturer: HUAWEI Technology
[1055196.790013] usb 1-1.5.6.4: usb_probe_device
[1055196.790020] usb 1-1.5.6.4: configuration #1 chosen from 1 choice
[1055196.792495] usb 1-1.5.6.4: adding 1-1.5.6.4:1.0 (config #1, interface 0)
[1055196.792578] option 1-1.5.6.4:1.0: usb_probe_interface
[1055196.792588] option 1-1.5.6.4:1.0: usb_probe_interface - got id
[1055196.792605] option 1-1.5.6.4:1.0: GSM modem (1-port) converter detected
[1055196.792670] usb 1-1.5.6.4: link qh2-0001/ffff8801d0c46200 start 1 [2/0 us]
[1055196.792725] usb 1-1.5.6.4: GSM modem (1-port) converter now attached to ttyUSB0
[1055196.792767] usb 1-1.5.6.4: adding 1-1.5.6.4:1.1 (config #1, interface 1)
[1055196.792824] usb 1-1.5.6.4: adding 1-1.5.6.4:1.2 (config #1, interface 2)
[1055196.792891] usb 1-1.5.6.4: adding 1-1.5.6.4:1.3 (config #1, interface 3)
[1055196.792923] option 1-1.5.6.4:1.3: usb_probe_interface
[1055196.792927] option 1-1.5.6.4:1.3: usb_probe_interface - got id
[1055196.792933] option 1-1.5.6.4:1.3: GSM modem (1-port) converter detected
[1055196.792999] usb 1-1.5.6.4: GSM modem (1-port) converter now attached to ttyUSB1
[1055196.793027] usb 1-1.5.6.4: adding 1-1.5.6.4:1.4 (config #1, interface 4)
[1055196.793062] option 1-1.5.6.4:1.4: usb_probe_interface
[1055196.793066] option 1-1.5.6.4:1.4: usb_probe_interface - got id
[1055196.793071] option 1-1.5.6.4:1.4: GSM modem (1-port) converter detected
[1055196.793137] usb 1-1.5.6.4: GSM modem (1-port) converter now attached to ttyUSB2
--- and storage endpoints attach back ---

Now you can connect to /dev/ttyUSB0 using tip, cu or minicom and talk to the modem.

AT commands

AT stands for attention and these commands are intended to get the modem's attention for whatever action you're trying to perform :-)

Some of them are standardized in ITU's V.250 (see references) and some of them are modem-specific. They are somewhat grouped, so the operator should have an idea about where such command is defined (for example, AT+C is V.250-defined prefix for digital cellular extensions, AT+CG is ETSI TS 127 007 General command, which is a "cellular equivalent" of V.250's +G).

Here goes a list of ones that can come in handy:

Official

A/
repeat last command
AT+CGMI
request manufacturer identification
AT+CGMM
request model identification
AT+CGMR
request revision identification
AT+CGSN
request product serial number identification
AT+CIMI
request international mobile subscriber identity
AT+CBC
battery charge ((0 = powered, 1 = connected, not powered, 2 = NC, 3 = power fault, calls inhibited), (0 = exhausted, 1..100 percent))
AT+CSQ
signal quality (RSSI, BER)
RSSI012..303199
dBm≤ -113-111-109..-53-51N/A
BER0123456799
%< 0.2< 0.4< 0.8< 1.6< 3.2< 6.4< 12.8> 12.8N/A
BER is encoded as RXQUAL in TS 45.008
AT+WS46
PCCA STD-101 select wireless network; 12 means 3GPP systems, 22 means WCDMA and 25 means GPRS

example, determine basic information

AT+CGMI
huawei

OK
AT+CGMM
E1750

OK
AT+CBC
+CBC: 2,0

OK
AT+CSQ
+CSQ: 18,99

OK
AT+WS46?
25

OK
AT+WS46=?
+WS46: (12,22,25)

OK
AT+COPS
public land mobile network (PLMN) selection
AT+COPN
read operator names

example, site survey (takes a while)

AT+COPS?
+COPS: 0,2,"23003",2

OK
AT+COPS=?
+COPS: (1,"Vodafone CZ","Vodafone","23003",0),(2,"Vodafone CZ","Vodafone","23003",2),(1,"EUROTEL - CZ","ET - CZ","23002",0),(1,"EUROTEL - CZ","ET - CZ","23002",2),(1,"T-Mobile CZ","TMO CZ","23001",0),(1,"T-Mobile CZ","TMO CZ","23001",2),,(0,1,2,3,4),(0,1,2)

OK
AT+CPIN
if it asks for your PIN

Huawei specific

AT^SYSCFG=$mode,$acqOrder,$band,$roam,$srvDomain

$mode
2=Auto-Select
13=GSM only
14=WCDMA only
16=no Change

$acqOrder
0=Automatic
1=GSM prefered
2=WCDMA prefered
3=no Change

$band
3fffffff = All
other (query list with "AT^SYSCFG=?")

$roam
0=Not Supported
1=Supported
2=no Change

$srvDomain
0=Circuit-Switched only
1=Packet-Switched only
2=Circuit- & Packet-Switched
3=Any
4=no Change

Any : AT^SYSCFG=2,0,3FFFFFFF,2,4
2G only : AT^SYSCFG=13,1,3FFFFFFF,2,4
3G only : AT^SYSCFG=14,2,3FFFFFFF,2,4
2G preferred : AT^SYSCFG=2,1,3FFFFFFF,2,4
3G preferred : AT^SYSCFG=2,2,3FFFFFFF,2,4

------------------
AT^U2DIAG
AT^u2diag=0 (all off)
AT^u2diag=1 (CD on, SD off)
AT^u2diag=256 (CD off, SD is on)
AT^u2diag=255 (all on − including SD Card)
AT^u2diag=276 (Factory Reset)

example, query my E1750

AT^SYSCFG?
^SYSCFG:2,0,3FFFFFFF,1,2

OK
AT^SYSCFG=?
^SYSCFG:(2,13,14,16),(0-3),((400380,"GSM900/GSM1800/WCDMA2100"),(280000,"GSM850/GSM1900"),(3fffffff,"All Bands")),(0-2),(0-4)

OK

How to make it work

todo :-)

Linux: wvdial, ppp and some kernel modules

$ cat /etc/wvdial.conf
[Dialer vodafone]
Init1 = ATZ
Init2 = AT+CGDCONT=1,"IP","internet"
Init3 = ATX3
Password = internet
Phone = *99***1#
Modem Type = Analog Modem
Stupid Mode = on
SetVolume = 0
Baud = 115200
Dial Command = ATDT
Modem = /dev/ttyUSB0
ISDN = 0
Username = IP
FlowControl = CRTSCTS
$ sudo wvdial vodafone
... works ...

OpenBSD: groups network+dialer, pppd

$ cat /etc/ppp/peers/vodafone
/dev/cuaU0
115200
0.0.0.0:10.64.64.64
noipdefault
defaultroute
crtscts
#debug
#nodetach
deflate 0
bsdcomp 0
noccp
noaccomp
novj
novjccomp
noauth
user IP
ipcp-restart 10
connect '/usr/sbin/chat -v -f /etc/ppp/chatscript.vodafone'
$ cat /etc/ppp/chatscript.vodafone
SAY "Zacinam se pripojovat..."
""	ATZ
SAY "\nNastavuju PDP kontext..."
OK	AT+CGDCONT=1,"IP","internet"
SAY "\nZapinam busy detection, vypinam dialtone detection..."
OK	ATX3
SAY "\nVolam *99***1# a spoustim pppd.\n"
OK	ATDT*99***1#
'CONNECT'	'\c'
'TIMEOUT'	'5'
# ifconfig ppp0 create
$ pppd call vodafone
$ grep ppp /var/log/daemon | tail -n 28 
Jun 17 00:41:45 rtin pppd[30643]: pppd 2.3.5 started by m, uid 1000
Jun 17 00:41:47 rtin pppd[30643]: Serial connection established.
Jun 17 00:41:48 rtin pppd[30643]: Using interface ppp0
Jun 17 00:41:48 rtin pppd[30643]: Connect: ppp0 <--> /dev/cuaU0
Jun 17 00:41:48 rtin pppd[30643]: sent [LCP ConfReq id=0x1  ]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [LCP ConfReq id=0x0     ]
Jun 17 00:41:48 rtin pppd[30643]: sent [LCP ConfRej id=0x0 ]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [LCP ConfAck id=0x1  ]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [LCP ConfReq id=0x1    ]
Jun 17 00:41:48 rtin pppd[30643]: sent [LCP ConfAck id=0x1    ]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [LCP DiscReq id=0x2 magic=0xf4f29b]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [CHAP Challenge id=0x1 <546be1a7e6ad4dc0ac39d42bae61167a>, name = "UMTS_CHAP_SRVR"]
Jun 17 00:41:48 rtin pppd[30643]: sent [CHAP Response id=0x1 , name = "IP"]
Jun 17 00:41:48 rtin pppd[30643]: rcvd [CHAP Success id=0x1 ""]
Jun 17 00:41:48 rtin pppd[30643]: sent [IPCP ConfReq id=0x1 ]
Jun 17 00:41:49 rtin pppd[30643]: rcvd [IPCP ConfNak id=0x1    ]
Jun 17 00:41:49 rtin pppd[30643]: sent [IPCP ConfReq id=0x2 ]
Jun 17 00:41:50 rtin pppd[30643]: rcvd [IPCP ConfNak id=0x2    ]
Jun 17 00:41:50 rtin pppd[30643]: sent [IPCP ConfReq id=0x3 ]
Jun 17 00:41:50 rtin pppd[30643]: rcvd [IPCP ConfReq id=0x0]
Jun 17 00:41:50 rtin pppd[30643]: sent [IPCP ConfNak id=0x0 ]
Jun 17 00:41:50 rtin pppd[30643]: rcvd [IPCP ConfNak id=0x3 ]
Jun 17 00:41:50 rtin pppd[30643]: sent [IPCP ConfReq id=0x4 ]
Jun 17 00:41:50 rtin pppd[30643]: rcvd [IPCP ConfReq id=0x1]
Jun 17 00:41:50 rtin pppd[30643]: sent [IPCP ConfAck id=0x1]
Jun 17 00:41:50 rtin pppd[30643]: rcvd [IPCP ConfAck id=0x4 ]
Jun 17 00:41:50 rtin pppd[30643]: local  IP address 10.28.7.106
Jun 17 00:41:50 rtin pppd[30643]: remote IP address 10.64.64.64
... works, but ms-dns seems to be unsupported for clients ...
$ pkill pppd

I need more!

AT+CLAC stands for List all available AT commands. As you can see, the list can be quite long. Obviously they have to be prepended with AT and obviously some of them can be dangerous.

References