Huawei E3531 configuration Raspbian Jessie – pppd

In the previous post huawei-e3531-configuration-raspbian-jessie I got usb_modeswitch running to change the mode of the usb dongle into modem mode on insertion or reboot. This post is a continuation on the previous post to configure pppd to use the usb dongle as a modem and set up a point to point connection to the internet, or at least the mobile provider. When using a tutorial found online it didn’t work first time. A problem setting up the connection is described with logfiles and attempts to diagnose the problem, then the solution is provided. This solution is most likely specific to o2(uk). The final section describes the configuration file used just to get pppd working with o2. Networking is not covered since once the connection is established there are many ways you can configure routing, firewalls and VPN to name a few. An example use for this is you can configure hostapd and dnsmasq to provide a mobile broadband hotspot.

Following the advice on [Insert Link here, unknown source], when trying to the connect the connection would fail to come up. On checking /var/log/syslog I was getting the following PAP authentication succeeded but then the modem would hang up immediately afterwards:

Dec 24 12:54:28 raspberrypi pppd[9435]: Serial connection established.
Dec 24 12:54:28 raspberrypi pppd[9435]: Using interface ppp0
Dec 24 12:54:28 raspberrypi pppd[9435]: Connect: ppp0 <--> /dev/ttyUSB0
Dec 24 12:54:29 raspberrypi pppd[9435]: Remote message: Greetings!!
Dec 24 12:54:29 raspberrypi pppd[9435]: PAP authentication succeeded
Dec 24 12:54:29 raspberrypi pppd[9435]: LCP terminated by peer
<strong>Dec 24 12:54:29 raspberrypi pppd[9435]: Hangup (SIGHUP)</strong>
Dec 24 12:54:29 raspberrypi pppd[9435]: Modem hangup
Dec 24 12:54:29 raspberrypi pppd[9435]: Connection terminated.

This logfile isn’t very descriptive, luckily you can enable debugging by adding the “debug” option to the end of the pppd configuration file. The one I was using was located in: /etc/ppp/peers/gprs. I also changed the authentication to CHAP but this had no success. Below is the logfile with debugging enabled.

Dec 26 18:56:21 raspberrypi pppd[10226]: Using interface ppp0
Dec 26 18:56:21 raspberrypi pppd[10226]: Connect: ppp0 &lt;--&gt; /dev/ttyUSB0
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [LCP ConfReq id=0x2 &lt;asyncmap 0x0&gt; &lt;magic 0x55b552f8&gt; &lt;pcomp&gt; &lt;accomp&gt;]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [LCP ConfReq id=0x1 &lt;accomp&gt; &lt;pcomp&gt; &lt;asyncmap 0x0&gt; &lt;mru 1500&gt; &lt;magic 0x54d&gt; &lt;auth chap MD5&gt;]
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [LCP ConfAck id=0x1 &lt;accomp&gt; &lt;pcomp&gt; &lt;asyncmap 0x0&gt; &lt;mru 1500&gt; &lt;magic 0x54d&gt; &lt;auth chap MD5&gt;]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [LCP ConfAck id=0x2 &lt;asyncmap 0x0&gt; &lt;magic 0x55b552f8&gt; &lt;pcomp&gt; &lt;accomp&gt;]
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [LCP EchoReq id=0x0 magic=0x55b552f8]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [CHAP Challenge id=0x1 &lt;6a72fdb6d5e382736072d083cdd069ea&gt;, name = "HUAWEI_CHAP_SRVR"]
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [CHAP Response id=0x1 &lt;b30763faefba7325481226d08eeb2fb8&gt;, name = "o2web"]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [LCP EchoRep id=0x0 magic=0x54d]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [CHAP Success id=0x1 "Welcome!!"]
Dec 26 18:56:22 raspberrypi pppd[10226]: CHAP authentication succeeded: Welcome!!
Dec 26 18:56:22 raspberrypi pppd[10226]: CHAP authentication succeeded
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [CCP ConfReq id=0x2 &lt;deflate 15&gt; &lt;deflate(old#) 15&gt; &lt;bsd v1 15&gt;]
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [IPCP ConfReq id=0x2 &lt;compress VJ 0f 01&gt; &lt;addr; &lt;ms-dns1; &lt;ms-dns2;]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [IPCP ConfReq id=0x1]
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [IPCP ConfNak id=0x1 &lt;addr;]
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [LCP ProtRej id=0x2 80 fd 01 02 00 0f 1a 04 78 00 18 04 78 00 15 03 2f]
Dec 26 18:56:22 raspberrypi pppd[10226]: Protocol-Reject for 'Compression Control Protocol' (0x80fd) received
<strong>Dec 26 18:56:22 raspberrypi pppd[10226]: Hangup (SIGHUP)</strong>
Dec 26 18:56:22 raspberrypi pppd[10226]: rcvd [LCP TermReq id=0x2]
Dec 26 18:56:22 raspberrypi pppd[10226]: LCP terminated by peer
Dec 26 18:56:22 raspberrypi pppd[10226]: sent [LCP TermAck id=0x2]
Dec 26 18:56:22 raspberrypi pppd[10226]: Modem hangup
Dec 26 18:56:22 raspberrypi pppd[10226]: Connection terminated.

It looks like “Protocol-Reject for ‘Compression Control Protocol’ (0x80fd) received” is causing the hangup. After trying additional options in /etc/ppp/peers/ to disable compression it seemed like this made things worse by not trying to negotiate over LCP and ending the connection sooner. The additional options used are listed below, these all resulted in no success but sometimes the modem would connect and provide a link! On reboot or reconnecting it would not reliably connect.

holdoff 10
maxfail 0

The solution

In the default chatscript /etc/chatscript/gprs there is a line to dial in data mode:

OK ATD*99#

It turns out for o2 this should be:

OK ATD*99***2#

After changing that line connection attempts succeeded consistently.

Configuration files

This section describes all the configuration used to get a connection working with the E3531 and o2 uk pay as you go.

The first configuration is to install pppd the usual way (apt-get ppp). Once this has completed a ppp configuration need to be established. The default file located in /etc/ppp/peers/gprs does a good job. Each configuration file in the peers directory represents a different connection. There can be multiple peers to connect to that you can configure in this directory. My gprs configuration for o2 is listed below.

# example configuration for a dialup connection authenticated with PAP or CHAP
# This is the default configuration used by pon(1) and poff(1).
# See the manual page pppd(8) for information on all the options.

# MUST CHANGE: replace myusername@realm with the PPP login name given to
# your by your provider.
# There should be a matching entry with the password in /etc/ppp/pap-secrets
# and/or /etc/ppp/chap-secrets.
user "payandgo"
password "wap"

# MUST CHANGE: replace ******** with the phone number of your provider.
# The /etc/chatscripts/pap chat script may be modified to change the
# modem initialization string.
connect "/usr/sbin/chat -v -f /etc/chatscripts/gprs -T"

# Serial device to which the modem is connected.

# Speed of the serial line.

# Assumes that your IP address is allocated dynamically by the ISP.
# Try to get the name server addresses from the ISP.
# Use this connection as the default route.

# Makes pppd "dial again" when the connection is lost.

# Do not ask the remote to authenticate.

The user and password at the top of the configuration seems to bypass the secrets file despite the comment “There should be a matching entry with the password in /etc/ppp/pap-secrets and/or /etc/ppp/chap-secrets.” In my configuration this is ignored.

The connect line gets /usr/sbin/chat to send AT commands to the modem pointed to at /dev/ttyUSB0.  The -v option enables verbose logging in syslog (you can probably omit this). The -f option provides the chatfile described below. The -T option provides additional arguments to the chatscript. In the comments this is described as the phone number but in 3G this is the APN that o2 uses for pay as you go connections,

noipdefault obtains an ip address from o2 although during the connection negotiation it seems to default to

defaultroute adds o2 as the default route and noauth is ok to leave.

As mentioned before the chatscript sets up the modem and “dials”, this is where the number needed to change from the default script /etc/chatscripts/gprs

# You can use this script unmodified to connect to cellular networks.
# The APN is specified in the peers file as the argument of the -T command
# line option of chat(8).

# For details about the AT commands involved please consult the relevant
# standard: 3GPP TS 27.007 - AT command set for User Equipment (UE).
# (


# cease if the modem is not attached to the network yet

"" AT

# +CPIN provides the SIM card PIN
#OK "AT+CPIN=1234"

# +CFUN may allow to configure the handset to limit operations to
# GPRS/EDGE/UMTS/etc to save power, but the arguments are not standard
# except for 1 which means "full functionality".

OK AT+CGDCONT=1,"IP","\T","",0,0
OK ATD*99***2#

The final configuration is required in /etc/network/interfaces.

auto gprs
iface gprs inet ppp
&nbsp; &nbsp; provider gprs

The ppp tells networking to use pppd with the configuration given by the provider option. I could be wrong but this seems equivalent to networking calling pppd call gprs where gprs is the options file given in /etc/ppp/peers/gprs describing the individual connection. If you had multiple connections you could use provider conn1 …etc.

All the configuration required is complete. Run ifup gprs to start connecting to the mobile broadband modem.

On reboot this doesn’t seem to automatically connect on boot and nothing in syslog seems to shed light on why. Ifup is required to get the connection going again but a script could be added in a udev rule for when the ttyUSB0 comes online, that’s for another day.


That concludes this two part post on using the E3531 Huawei dongle as a modem with o2 pay as you go. I’m sure this can be applied to other networks with different APN, user and password setting along with the ATD number.

Note: This usb modem and ppp was configured with raspbian jessie lite, at the time of writing raspbian stretch was available and it had not been verified that the usb_modeswitch fix in the first post was still necessary. If you try this with raspbian stretch you may find that usb_modeswitch works correctly when the modem is inserted the first time.

Huawei E3531 configuration Raspbian Jessie

This post describes the configuration I used on raspbian Jessie lite to get a Huawei E3531 working with the o2(uk) carrier. After searching a lot over the forums and google it was difficult to determine the correct way to do this using raspbian with this particular model of modem and the problems I was experiencing. The first hurdle was getting usb_modeswitch working correctly to switch the usb modem from mass storage mode into modem mode. The second hurdle was configuring pppd to set up the modem correctly and make a ppp connection to o2.

The first problem was usb_modeswitch not being run or failing to switch the dongle into modem mode.

The second problem was pppd connecting and successfully getting past authentication but then receiving modem hangups after LCP compression negotiation (if that’s the right term?).

In the end the solution to get this working was from a mixture of posts and manpages and a little bit of hacking. There are two sections to this, usb_modeswitch which describes how to get usb_modeswitch working with udev (the kernel event handler). The second section pppd is the actual configuration of pppd to set up the modem and dial to create the ppp connection.


Usually when a 3G USB dongle is inserted it starts up in mass storage mode that gives you access to pre-loaded windows drivers stored on the device. When installed these drivers then send a specific packet to the modem to switch the mode into the modem mode. In the case of the Huawei E3531 under windows for simplicity there is a third mode which runs the HiLink firmware on the dongle. What HiLink does is present a LAN interface on windows much like a USB to Ethernet adapter. This interface then acts as if you’ve connected the Ethernet port to a modem/router where you can navigate to on your favorite browser and view usage, signal strength messages etc. A dhcp server issues the dns and default route addresses to get out onto the mobile broadband network. For casual use HiLink is probably good enough but this additional layer of complexity is not required for small projects.

What usb_modeswitch does is send the special packet to the usb dongle which causes the mode to switch. Once the dongle has switched to change modes again it needs to be unplugged and plugged back in again so that it starts in mass storage mode.

For the Huawei you can tell which mode the device is in by using lsusb, if usb_modeswitch hasn’t already changed the mode (as in my case) there will be a line reported somewhere like:

pi@raspberrypi:~ $ lsusb
Bus 001 Device 004: ID 12d1:1f01 Huawei Technologies Co., Ltd.

ID 12d1:1f01 identifies mass storage mode, modem mode for this dongle is identified by ID 12d1:1001 and HiLink mode is ID 12d1:14dc.

usb_modeswitch is installed through the usual way by apt-get, in Raspbian jessie it was already available but as noted before nothing happend after the device was plugged in. There is a way to manually switch this device through the command line:

sudo usb_modeswitch -W -I -v 12d1 -p 1f01 -M 55534243123456780000000000000011062000000101000100000000000000

sudo usb_modeswitch -W -I -v 12d1 -p 1f01 -M 55534243123456780000000000000011062000000100000000000000000000

The first command switches it into HiLink mode and the second command switches the device into modem mode where /dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2 is created to communicate through the modem with AT commands. AT commands configure the modem much like the common conexant dial up modems. There are a vast variety of commands to get RSSI info and much more. You can also send/receive text messages, a little on that in a later post.

Using the second command you should see the output, lsusb result and tty devices:

pi@raspberrypi:~ $ sudo usb_modeswitch -W -I -v 12d1 -p 1f01 -M 55534243123456780000000000000011062000000100000000000000000000
Take all parameters from the command line

* usb_modeswitch: handle USB devices with multiple modes
* Version 2.2.0 (C) Josua Dietze 2014
* Based on libusb1/libusbx


DefaultVendor= 0x12d1
DefaultProduct= 0x1f01


Look for default devices ...
found USB ID 12d1:1f01
vendor ID matched
product ID matched
found USB ID 0424:ec00
found USB ID 0424:9514
found USB ID 1d6b:0002
Found devices in default mode (1)
Access device 007 on bus 001
Current configuration number is 1
Use interface number 0
Use endpoints 0x01 (out) and 0x81 (in)
Inquire device details; driver will be detached ...
Looking for active driver ...
OK, driver detached

SCSI inquiry data (for identification)
Vendor String: HUAWEI
Model String: Mass Storage
Revision String: 2.31

USB description data (for identification)
Manufacturer: HUAWEI
Product: HUAWEI Mobile
Set up interface 0
Use endpoint 0x01 for message sending ...
Trying to send message 1 to endpoint 0x01 ...
OK, message successfully sent
Reset response endpoint 0x81
Reset message endpoint 0x01
-&gt; Run lsusb to note any changes. Bye!

pi@raspberrypi:~ $ lsusb
Bus 001 Device 008: ID 12d1:1001 Huawei Technologies Co., Ltd. E169/E620/E800 HSDPA Modem
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@raspberrypi:~ $ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2

The serial devices show up in /dev which great, pppd can then be configured to use these devices. One question remains is why is this not auto matically switching?

On the developer’s site, it mentions:

/etc/usb_modeswitch.d – a folder for customized config files. You can put new or modified config files here; they will take precedence over the collection of configurations in /usr/share/usb_modeswitch.”

On insertion of the USB dongle Udev should run usb_modeswitch and looking through syslog usb_modeswitch is being run, more worringly repeatedly. It first looked like usb_modeswitch does not recognise this device so I created the config file in usb_modeswitch.d below.



This config file worked by manually running usb_modeswitch but not when inserting the dongle.

pi@raspberrypi:~ $ usb_modeswitch -c /etc/usb_modeswitch.d/12d1:1f01

Without investigating further as to why usb_modeswitch wasn’t automatically running and changing modes, since I’m not familiar with the internals of udev and usb_modeswitch, I hacked a little script in the home directory to get udev to run 15s after inserting the device so that usb_modeswitch isn’t required to be run manually. This script will take the usb ID from udev and run the config file saved in /etc/usb_modeswitch.d/. 



sleep 15

usb_modeswitch -D -c $CONFIG

A udev rule is required to run this script, as a start a template was taken from /lib/udev/rules.d/40-usb_modeswitch.rules


ATTRS{idVendor}=="12d1", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="/home/pi/USBDevConnect %s{idVendor} %s{idProduct}"

The above rule runs /home/pi/USBDevConnect once on insertion of the E3531 and passes the vendor and product id to the script which the script uses as the config file. %s is a neat way to pass attributes to custom scripts.

Notice the use of sleep in USBDevConnect, I put this in to mimic the delay of manually running usb_modeswitch and the length is plucked out of thin air. Udev does have a limit of how long this script can run for, it seems 30s is hardcoded and any longer the script will get killed by udev unfortunately.

Using the above hack will get the E3531 to switch on insertion and at reboot. The next section will describe connecting to the internet via pppd.


See part 2 – pppd


This has turned into a two part post as the workaround to get usb_modeswitch working was long. A workaround has been proposed but please note this usb modem was configured with raspbian jessie lite, at the time of writing raspbian stretch was available and it had not been verified that the usb_modeswitch fix in the first post was still necessary. If you try this with raspbian stretch you may find that usb_modeswitch works correctly when the modem is inserted the first time.

See part 2 – pppd to get to the configuration of dialing the modem and establishing a point to point connection.


Using plink for remote wireshark captures

plink.exe -ssh -pw abc123&nbsp;root@ "tcpdump -ni eth0 -s 0 -w - not port 22" | "C:\Program Files\Wireshark\Wireshark.exe" -k -i -

This command uses plink to pipe the standard out of tcpdump on the remote linux device to wireshark on windows over an ssh session.

The “not port 22” is a filter that is important to prevent an endless loop of reporting ssh packets going back the remote device. If the ssh session is on a different interface this filter is not required.

Waveshare35a overlay

I used device trees in raspbian to configure the waveshare 4″ display (DEVICE TREES, OVERLAYS, AND PARAMETERS). 

Raspberry Pi’s latest kernels and firmware, including Raspbian and NOOBS releases, now use a Device Tree (DT) to manage some resource allocation and module loading by default

Following that information from the raspberry pi site somehow I created an overlay below (note the frequency may be incorrect).

EDIT: The waveshare overlays have been found here.

 * Device Tree overlay for waveshare 3.5inch TFT LCD


/ {
	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

	fragment@0 {
		target = <&spi0>;
		__overlay__ {
			status = "okay";

				status = "disabled";

				status = "disabled";

	fragment@1 {
		target = <&gpio>;
		__overlay__ {
			waveshare35a_pins: waveshare35a_pins {
				brcm,pins = <17 25 24>;
				brcm,function = <0 0 0>; /* in in in */

	fragment@2 {
		target = <&spi0>;
		__overlay__ {
			/* needed to avoid dtc warning */
			#address-cells = <1>;
			#size-cells = <0>;

			waveshare35a: waveshare35a@0{
				compatible = "ilitek,ili9486";
				reg = <0>;
				pinctrl-names = "default";
				pinctrl-0 = <&waveshare35a_pins>;

				spi-max-frequency = <16000000>;
				txbuflen = <32768>;
				rotate = <90>;
				bgr = <0>;
				fps = <30>;
				buswidth = <8>;
				regwidth = <16>;
				reset-gpios = <&gpio 25 0>;
				dc-gpios = <&gpio 24 0>;
				debug = <0>;

				init = <0x10000b0 0x00 0x1000011 0x20000ff 0x100003a 0x55 0x1000036 0x28 0x10000c2 0x44 0x10000c5 0x00 0x00 0x00 0x00 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 /* piscreen -> waveshare35a */
					0x1000036 0x28

			waveshare35a_ts: waveshare35a-ts@1 {
				compatible = "ti,ads7846";
				reg = <1>;

				spi-max-frequency = <2000000>;
				interrupts = <17 2>; /* high-to-low edge triggered */
				interrupt-parent = <&gpio>;
				pendown-gpio = <&gpio 17 0>;
				ti,x-plate-ohms = /bits/ 16 <60>;
				ti,pressure-max = /bits/ 16 <255>;
	__overrides__ {
		speed =		<&waveshare35a>,"spi-max-frequency:0";
		txbuflen =	<&waveshare35a>,"txbuflen:0";
		rotate =	<&waveshare35a>,"rotate:0";
		fps =		<&waveshare35a>,"fps:0";
		bgr =		<&waveshare35a>,"bgr:0";
		debug =		<&waveshare35a>,"debug:0";
		swapxy =	<&waveshare35a_ts>,"ti,swap-xy?";

The overlay needs to be compiled where .dts is the source and the .dtbo file is the compiled source:

dtc -@ -I dts -O dtb -o waveshare35a-overlay.dtbo waveshare35a-overlay.dts

The -@ surpresses errors to do with references.

With the created overlay object .dtbo that needs to be copied into the boot partition:

sudo cp waveshare35a-overlay.dtbo /boot/overlays/waveshare35a-overlay.dtbo

At the end of /boot/config.txt add the following (omit the dtparam=spi=on if it is already enabled):


The dtoverlay should match the name of the .dtbo file copied into /boot/overlays.

At the moment the raspberry pi will still use its default frame buffer so the screen will initialise as a blank screen and not display anything although the framebuffer /dev/fb1 for this screen is available. To get the console to use the screen’s framebuffer a change in the boot configuration is required []. In /boot/cmdline.txt add to the end:


There is an option to use smaller fonts with the option fbcon=font:VGA8x8 but for the 4″ version the regular font is fine.

Finarlly reboot the device and the screen should be up and running.

Raspbian Waveshare Makibes 4 Inch Touch Screen RPi LCD (A) 320×480 IPS TFT LCD – Installation and configuration

April 2016 I purchased a 4″ touchscreen from Amazon. Turns out it’s a waveshare device.

To get the device working the support on the waveshare website suggests installing LCD-Show or using their pre-configured raspberry pi image. In order to use LCD-Show an internet connection is required to download the drivers. Naturally I was a bit skeptical about having to download some unknown files, especially since there should be some drivers available with raspbian included already?

Turns out there is a fbtft module already in raspbian from notro ( that supports a variety of devices but the 4″ waveshare was not one of them listed.

After some configuration the output from dmesg I used for this 4″ touchscreen is:

  • TFT: ili9486 spi0.0 8000kHz 8 bits mode=0x00
  • Touchscreen ds7846 spi0.1 2000kHz 8 bits mode=0x00

The bitrate configurate was crucial to get this working but turns out 16MHZ was suitable. Further information about how I configured these in the link below.

Go to the configuration

Apache mod_rewrite

When enabling mod_rewrite on apache after reloading the configuration a 403 error was given. This was because Options -FollowSymLinks was used in the <Directory> configuration.

This is because follow symlinks is required for per-directory rewrites as described in the apache module manual. “To enable the rewrite engine in this context, you need to set ”

RewriteEngine On

” and ”

Options FollowSymLinks

” must be enabled. If your administrator has disabled override of 


 for a user’s directory, then you cannot use the rewrite engine.”

Follow symlinks was disabled beforehand to prevent using symlinks to gain access into the rest of the file system when using scripts. I thought when I disabled symlinks this was related to the php configuration open_basedir which I wanted to use to prevents the php script getting access outside of this directory (but sub directories are ok).

On the php documentation “All symbolic links are resolved, so it’s not possible to avoid this restriction with a symlink” which sound like good news. If a symlink is created to link to outside of the open_basedir then php should resolve this and reject the file operations.