Update: It seems like this method got irrelevant over the years because the Raspberry Pi 4 now seems to detect the correct mode of the USB modem on its own!
Long-time readers of this website might recognize this article. It was the first article, I published on nerdhut. As of today, this is still one of the most popular articles on the page and because of that, I decided to shorten it a bit and translate it to English.
However, the original German version remains online here!
Due to my work on a remote-controlled unmanned ground vehicle, I searched for a way to control it anywhere in the world. Because I wanted it to have a high range and reliability, I decided to communicate with it over the internet, which should be available almost anywhere on the planet.
So I got myself a cheap 3G modem and started experimenting. I came across many other people, that seemed to have similar problems getting the Pi connected. So after I managed to connect it to the internet, I decided to share my method in this article.
The main problem with this stick is, that it acts as a removable drive (which contains the drivers) and as a networking card simultaneously. Even though many operating systems detect the device(s) correctly, Raspbian/Debian (and seemingly a lot of other Linux systems) seem to have trouble switching between the devices.
How I made it work
I assume, that the Surf-Stick is already configured and working correctly (Sim-PIN turned off, correct carrier information, etc.) and the only problem is, that it doesn’t get mounted correctly in Raspbian.
- First of all, I started with setting up a new SD-card with a fresh installation of Raspbian. I did this to make sure, that no other software was causing any problems with drivers. I also unplugged any other unnecessary peripherals.
- Then I installed a program called “usb-modeswitch”:
sudo apt-get install usb-modeswitch
After the installation was done, you have two options to use the program: You can either edit a global configuration file (which is the preferred method if you only have one device), or you can create and edit one config file per device. I went with the first option, because I only have one modem I would like to configure.
- Now you need to get the ID of the device and the manufacturer. You can list the connected devices with the “lsusb” command:
Bus 001 Device 005: ID 12d1:1f01 Huawei Technologies Co., Ltd.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
So my modem’s manufacturer ID (hexadecimal) is: “12d1”, the product ID (hexadecimal too) is: “1f01”.
This product ID is the before mentioned removable drive, so exactly what we want to change to the modem’s ID, so that the OS communicates with the modem instead of the drive.
- Then I changed the ID by altering the configuration file, mentioned under 2). Different codes exist for various manufacturers and devices. However, I got the correct codes for my device here.After I found the necessary codes, I added the following lines to the end of the global configuration file of usb-modeswitch:
# Huawei E303 DefaultVendor= 0x12d1 DefaultProduct=0x1f01 TargetVendor= 0x12d1 TargetProduct= 0x14dc MessageContent="55534243123456780000000000000a11062000000000000100000000000000"
As you can see, the “DefaultVendor” and “DefaultProduct” entries are the same hexadecimal values, I got earlier. The “TargetVendor” stays the same and the “TargetProduct” is the modem’s ID.
The “MessageContent” contains the sequence sent to the device to let it know, that it should switch to the other device.
- After I saved the config file, I ran “usb-modeswitch” with the same values that I wrote into the config-file:
sudo usb_modeswitch -v 12d1 -p 1f01 -M '55534243123456780000000000000a11062000000000000100000000000000'
You might ask, why I saved the values to the config file, just to start the program with the same values manually. I did this, because the program displayed error messages from time to time, stating that no config-file was found or that it was incorrect. So just as a precaution, I started the program with the same parameters.
However, usually you don’t run usb-modeswitch manually anyways. When you plug the device in, the program automatically switches it to the modem, using the codes from the config file.
After running usb-modeswitch, run “lsusb”:
Bus 001 Device 005: ID 12d1:1fdc Huawei Technologies Co., Ltd.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
You can see, that the ID got changed. If that worked, the modem should also be listed when running “ifconfig” and additionally, the LED on the E303 stick should light up constantly instead of flashing blue.
- If running usb-modeswitch manually worked this time, it should work every time from now on, as long as you don’t change the device or config file. However, my stick seemed to restart from time to time (probably due to energy-saving or a forced re-connect).Theoretically, usb-modeswitch should detect, that the device got switched back and correctly re-configure it again. However, because reliability has a such a high priority in my case, I decided to add the following line to new bash-script, which I called “modeswitch.sh”:
/usr/sbin/usb_modeswitch -v 12d1 -p 1f01 -M '55534243123456780000000000000a11062000000000000100000000000000'
which simply runs usb-modeswitch with the parameters discussed earlier. Just make sure, to include the full path to usb-modeswitch.
Afterwards, I added the following line to the super user’s cron-table:
* * * * * sh /modeswitch.sh @reboot sleep 60 && sh /modeswitch.sh
This entry will run the “modeswitch.sh” script every minute. If nothing changed, usb-modeswitch will not find the removable drive and it won’t alter the modem. If for whatever reason, the ID got changed and usb-modeswitch didn’t automatically switch the device to the “modem”-mode, this script will run modeswitch and then the correct device will be used again.
- Now reboot the system. After logging in, usb-modeswitch should automatically detect the 3G-modem and should switch the ID and send the message from the config file, which will cause the system to use the modem, instead of the removable drive. This usually takes around 20-30s on my Pi. If it doesn’t happen automatically, simply wait for the cron-job to execute.
- Now you should be able to use ping to check your connectivity to the internet.
Setting up a dynamic DNS service
Because your modem has an external IP-address, which usually gets assigned by your ISP and changes from time to time, you can not expect, to always reach your device with the same IP-address, which can be bad, if you depend on reaching it. With a dynamic DNS server you can assign a hostname to your device’s IP-address and therefore you can always reach your device with a unique address, that won’t change. I used a service called “duckDNS” because the setup was really quick and easy to do.
You simply register on the site and then choose a domain name for each device you want to configure:
As you can see, I already registered two domains. You can register up to five unique domains for free with one account. To create a new domain, enter the subdomain in the black bar and click on “add-domain”.
You can also see, that there are no IP-addresses linked to the domains yet. We don’t want to manually enter them here, because the main purpose of using this service is, that we might not even know the IP-address.
For updating the address of a device, click on “install” on top of the page and choose “Linux cron” on the next page. Afterwards simply let the website create the necessary code for you and save it on your Pi!
The IP-address should now be updated automatically, so you can always use the same domain-name to reach you Raspberry Pi!
[Fig. 1] Huawei E303 surf-stick, consumer.huawei.com