The stick and wvdial

Getting a Huawei E3531, Swisscom and wvdial to work

December 16, 2016 - 4 minute read -
huawei raspberrypi wvdial udev

This is the second part of my journey with Raspberry Pi’s and USB 3G sticks, also known as ‘internet sticks’. This post is about figuring out how to get the Huawei E3531 stick to dial in to the provider’s network using wvdial.

wvdial, a phreaking-era throwback

I was glad to find out that having Linux and phone modems play nice was another functionality covered by a tool, named wvdial. What I didn’t expect whas the histroy behind wvdial, its first code was already written in 1999! Put that into perspective: that was pretty much the time that ‘mobile’ phones were relatively massive bricks, pagers were still a thing, and the iPhone wouldn’t get introduced for another 8 years. I was sceptical at how well this would work. Could a technology written in 1999 still be relevant nearly two decades later?

Ubuntu wiki proving its use once more

Thankfully, there’s actually a pretty decent walkthrough over at the Ubuntu Network Manager wiki. It explains very well what the different structures are, and how to make it work for your provider/and USB stick. I grabbed their default configuration, located here, and googled some more to find the parameters for my specific provider (this is a good source, and some general googling of wvdial + your provider can never hurt). Here’s the config I finally came up with:

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0
Modem Type = Analog Modem
Baud = 9600
New PPPD = yes
Modem = /dev/ttyUSB0
ISDN = 0
; Phone = <Target Phone Number>
; Password = <Your Password>
; Username = <Your Login Name>

[Dialer cellular]

# This configuration should work for most cellular modems and
# USB or bluetooth connected mobile phones.

# Your modem device. Usually /dev/ttyUSB0 or /dev/ttyACM0
# Bluetooth devices use an rfcomm device (/dev/rfcomm0, etc) that must be set
# up first.
#
#Modem = /dev/ttyACM0
#Modem = /dev/ttyUSB0
#Modem = /dev/rfcomm0
Modem = /dev/ttyUSB0

# Port speeds that're worth testing:
# 921600
# 460800
# 115200
#  57600
Baud = 115200

# If your SIM card has a PIN, comment this line, uncomment the next one, and
# change the PIN shown to your PIN.
#Init = ATZ
Init = ATZ+CPIN="0000"

# If you know your ISP's APN, specify it instead of YOUR_ISP_APN below.
# If you don't, you may be able to find out on the 'net, or from tech
# support.
#
# There's also an APN table at https://wiki.ubuntu.com/NetworkManager/Hardware/3G .
#
# If you can't find it, you might be able to dial out without setting an APN
# (especially from a mobile phone). Just comment this line and uncomment
# the next one.
Init2 = AT+CGDCONT=1,"IP","gprs.swisscom.ch"
#Init2 = AT+CGDCONT=1,"IP"

# Most services/devices dial with *99# . A few seem to require *99***1#
Phone = *99#

# These often suffice, but your ISP might require different details. They're
# often dummy details used for all users on the ISP, frequently the ISP's
# name, but some ISP's do require you to use a real username and password.
Username = gprs
Password = gprs
Stupid Mode = 1 # Found online that this was necessary for my specific provider

Sure enough, issuing wvdial cellular now dialed in to the network! Checking ifconfig -a would now show a ppp0 interface with a public IP address. Great! I now needed to figure out a way to run this in the background, as soon as the stick connected. Most blog posts covering wvdial tell you to simply run wvdial cellular && with the & at the end signifying fork, i.e. run it detached/in the background. However, udev won’t have any of that. Forking a process in a udev rule will just have it killed 10 seconds afterwards (stating as reason: ‘Timeout’). Thankfully, there’s of course a solution. Instead of having udev call a script, it will call a system service. This allows for proper control of the service too (through systemctl for example), and is an all round good move in the sense of better process etiquette. I set up a service in /etc/systemd/system/ which contained the following:

#modem-attachment.service
[Unit]
Description= 3G Modem

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/local/bin/modem_attachment.sh

[Install]
WantedBy=multi-user.target

Then, in /usr/local/bin/modem_attachment.sh:

#!/bin/bash
#modem-attachment.service

logger Modem detected, initiating setup...
usb_modeswitch -v 12d1 -p 15d2 -V 12d1 -P 1506 -M "55534243123456780000000000000011062000000100000000000000000000"

logger Creating mobilphone symlink in /dev
ln -s /dev/ttyUSB0 /dev/mobilephone

sleep 20s
logger Launching wvdial script
wvdial cellular | at now

sleep 20s
logger Setting ifmetric priorities
ifmetric ppp0 20

In the /lib/usr/udev/ I adjusted the rule to:

ATTR{idVendor}=="12d1", ATTR{idProduct}=="15d2", TAG+="systemd", ENV{SYSTEMD_WANTS}="modem-attachment.service"

Hint: make sure to have the file with a high index, something like 90 or 99, so that it has the highest priority when udev matches the rules. Issue sudo udevadm control --reload-rules to reload udev. And that’s it! The Pi now nicely connects to the cellular network over the USB modem. Many thanks to this post for helping me figure things out!