Raspberry Pi with SIM7600X 4G HAT as a router

December 16th, 2024, last changes on January 10th, 2025

Cheat sheet for setting it up, as most of the information is spread over many different docs and therefore time consuming to collect it.

Waveshare/SimCom SIM7600X 4G HAT appears per default as VID:PID 0x1e0e:0x9001. Accordingly to SIM7600X ECM dial-up Internet is has to be switched to the PID 9018 in order to work as a network adapter. Another option would be to use the RNDIS protocol as stated in Raspberry Pi networked via RNDIS, but since it's a Microsoft's proprietary approach, trying to avoid it.

Get the Internet

  1. Install minicom apt install minicom.
  2. Open connection to the right ttyUSB (in my case ttyUSB2 as in examples) minicom -D /dev/ttyUSB2.
  3. Test, whether it answers to the AT command.
  4. Switch the PID to 9018 with AT+CUSBPIDSWITCH=9018,1,1.
  5. Should see the usb0 network interface now, but no tty anymore.
  6. My adapter did automatically get an IP address. If not (or even as they say: if the usb0 adapter is missing) then enter dhclient -v usb0.
  7. Without a SIM card I did get an IP of the 192.168.225.x range. The modem seems to offer a DNS service on the 192.168.225.1 address and nothing more.

Restore tty

After switching the PID, no more ttyUSB were available. The modem uses the same PID for all features, so I need to tell the kernel, to load the serial driver for the new PID as well.

  1. Instant approach: sudo /bin/sh -c 'echo 1e0e 9018 > /sys/bus/usb-serial/drivers/generic/new_id'.
  2. Permanent approach: a. Create a new udev rule file, e.g. /etc/udev/rules.d/99-simcom.rules. b. Define a rule ACTION=="add", ATTRS{idVendor}=="1e0e", ATTRS{idProduct}=="9018", RUN+="/bin/sh -c 'echo 1e0e 9018 > /sys/bus/usb-serial/drivers/generic/new_id'".
  3. Note the quasi-random enumeration of the ttyUSB ports. To make sure, you use the right one, use the full id, e.g. /dev/serial/by-id/usb-SimTech__Incorporated_SimTech__Incorporated_0123456789ABCDEF-if02-port0.
Good to know

Because there were no other serial devices in the system, the usb-serial-simple module did not load automatically. As a result, the /sys/bus/usb-serial/drivers/generic/new_id path could not be found and the udev rule failed. It could have been solved by adding the module to /etc/modules, just add a line saying usb-serial-simple.

Debugging udev

It's a messy thing. First, a unique identifier of the device is needed. The lsusb -t command shows a tree of USB devices, including the respective bus numbers and device numbers. Having them, you may construct a command line like sudo udevadm test /dev/bus/usb/BUS_NO/DEVICE_NO, where both BUS_NO and DEVICE_NO are expanded to 3 digits (zero-prefixed). Then, being lucky, you may see, whether the rule you added has been fired and why it did not work.

Other approaches: 1. This did not work: sudo modprobe usb-serial-simple vendor=0x1e0e product=0x9018. 2. This did work, but the usb0 adapter did disappear: a. sudo modprobe option to allow options. b. echo "1e0e 9018" > /sys/bus/usb-serial/drivers/option1/new_id as root.

Share the connection over LAN

  1. Configure a network adapter with a static private IPv4 address (did not try IPv6 yet), let's say eth0.
  2. Install dnsmasq apt install dnsmasq.
  3. Edit /etc/dnsmasq.conf:
interface=eth0
listen-address=[address of eth0]
bind-interfaces
server=[external DNS server] # if needed
domain-needed
bogus-priv
dhcp-range=[starting address],[last address],[lease period, e.g. 12h]
  1. Edit /etc/sysctl.conf by adding:
net.ipv4.ip_forward=1
  1. To avoid a restart, either sudo sysctl -p or sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward".
  2. Install iptables apt install iptables.
  3. Enable masquerade iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADE.
dnsmaq fails to start

On one device, the dnsmasq seems to start before the eth0 adapter is available. Maybe it's some oddity of the annoying Network Manager. How to know about this issue: by checking the service's status with sudo systemctl status dnsmasq.service. It says, it could not bind to the given address failed to create listening socket for 192.168.1.1: Cannot assign requested address (or the given adapter was not found unknown interface eth0, depending on whether you use the listen-address configuation option or not). The solution was to change the dependencies under sudo nano /lib/systemd/dnsmasq.service as follows: After=network-online.target and Wants=network-online.target.

Automate SIM PIN

Add a line to the `/etc/rc.local':

minicom -D /dev/serial/by-id/CHANGE_HERE -S /YOUR_PATH/modem.script > /YOUR_PATH/modem.log 2>&1

Create a script /YOUR_PATH/modem.script:

send AT
expect "OK"

send AT+CPIN?
expect "+CPIN: SIM PIN"
expect "OK"

send AT+CPIN=YOUR_PIN
expect "OK"

expect "SMS DONE"

expect "PB DONE"

exit

Please note, the script reflects the responses given by my particular device. Please test it first manually to see, how you modem behaves. And, if you have enough time, feel free to extend it to cover the case, when it would not require any PIN at all (this case would fail here). Full syntax defined under runscript(1).

Automatic reboot

It did happen already that the modem stopped responding at all (as both: as a serial device and as a network adapter), although it was still visible as a valid USB device by the OS. It looks like only a short power-off does the thing. Maybe there is some softer way of cycling the USB power, but for now I have found a following approach to do the thing - test for the Internet or reboot the system if it fails:

for i in {1..10}
do
    # echo "iteration $i"

    if ping -c 1 google.com > /dev/null 2>&1; then
        # works!
        break
    fi

    if [ $i -eq 10 ]; then
        # failed!
        /usr/sbin/reboot
        break
    fi

    sleep 6
done

So, at least one google-ping must work within of one minute or the OS will be restarted. The script is executed triple times an hour via cron.

References


Previous: Zigbee2mqtt with Sonoff Dongle Plus ZBDongle-P

Main Menu