It’s been almost 4 years working for Lanedo, and I don’t regret a single day having worked for them. Still, I believe it was a time for a change in my life, and since February 1st I am now working as a freelance developer.
I’ve really been involved in pretty different things during my professional life… antivirus desktop applications and gateways, satellite orbit determination and time synchronization systems, VoIP-based push-to-talk server development, and of course NetworkManager, ModemManager, libqmi, libmbim, Tracker, OpenWRT or GTK+.
I would love to keep on working on all these Free Software projects, but I’m also open to exploring new technologies. Change is always good, they say.
So, if you’re looking for a passionate software engineer to develop, improve or integrate your system, just check my website and get in touch. I’d love to hear about your needs and issues and how we can solve them together🙂
So I wanted to have ModemManager in OpenWRT to handle my mobile broadband connections.
OpenWRT has its own built-in support to handle mobile broadband modems of different types, mainly for AT-controlled modems, but also for QMI-controlled modems through libqmi and qmicli (now available in upstream OpenWRT). But hell, why not package ModemManager for that work, and provide a unified single DBus API to control any kind of mobile broadband modem in the same way?
ModemManager itself isn’t a very complex daemon, so it doesn’t have many dependencies, just: glib/gio, dbus, udev/gudev and libqmi. In the world of OpenWRT, though, none of these are blessed dependencies, as they have a lightweight replacement for everything: libubox (instead of glib), ubus (instead of dbus) and hotplug2 (instead of udev). These replacements target minimal embedded systems, and are perfectly integrated into OpenWRT and provide the building blocks of other core software like the netifd network interface daemon.
Still, having ModemManager available as a OpenWRT package seems like a good idea if you’re not very constrained by the hardware you’re going to use. If you are building a system which should support multiple broadband modems from different vendors, or just building a base system for one specific modem model but leaving the door open to change the model in the future, ModemManager seems a good choice.
systemd’s udev in OpenWRT
Since April 2012, udev sources are now integrated within the systemd source code. And that means that udev packages in OpenWRT would need to get updated in order to get built from that new repository. systemd provides some hints on what would be the best way of creating a minimal systemd build which can be used to gather just the udev-specific libraries and binaries. The easiest way involves compiling the whole systemd package with all optional features disabled, and that would get us not only systemd (which we won’t need), but also udevd and libudev. Easy, yes, but then we have some issues in the environment that we would need to handle…
In OpenWRT, the udev package is available in the trunk repository, where only the core OpenWRT packages are given. But in order to get the new udev compiled out of systemd we end up needing additional dependencies (dbus, libcap) which are only available in the packages repository. Moreover, if you also want to compile the glib-based gudev library, glib is also needed, which is also only available in the packages repository. And you cannot require a package from trunk to depend on a package from packages, so… ended up creating a new systemd-udev package within the packages repository.
As I was targeting the uClibc toolchain, I also ended up requiring some additional patches both in uClibc (e.g. to enable utmpx) and systemd to get the thing properly compiled. The patches applied in the systemd sources are just to handle missing features in uClibc (execvpe, secure_getenv…). Whenever uClibc includes those, we’ll be able to remove those patches.
ModemManager in OpenWRT
I prepared an easy setup of ModemManager packaging in OpenWRT, where all possible plugins get compiled. It wouldn’t have been difficult to allow selecting via configuration which plugins to get compiled, but didn’t want to spend time on that.
I sent the patches to the OpenWRT mailing list already, but if you want to give it a quick try, you can just clone the Lanedo OpenWRT repositories (trunk and packages) from gitorious.org:
$> git clone git://gitorious.org/lanedo/openwrt.git
$> git clone git://gitorious.org/lanedo/openwrt-packages.git
You’ll want both ‘modemmanager-support‘ branches in those git repositories.
ModemManager will be available under the ‘Network’ section in the OpenWRT build configuration; but only after explicitly selecting the following kernel modules (all under Kernel Modules/USB support):
Once all above are enabled, ModemManager can be selected, and it will itself pull all its other required dependencies (systemd-udev, glib, dbus, libqmi…).
No LuCI? No connection manager?
Well, not yet🙂. If you want to use ModemManager you still need to have your own connection manager software to manage the connectivity. ModemManager will get your mobile broadband modem connected, but you still need to either call pppd or setup the wwan interface yourself (depending on the data port type). This is really not a big deal; and you can just setup a shell script using the provided mmcli command line interface to talk to ModemManager.
Linux 3.2 kernel with QMI support
When I started to develop the QMI support in OpenWRT, latest trunk was based on the 3.2 kernel series. By the time you read this, OpenWRT may already have a recent enough kernel (>= 3.4), so this custom setup may not be needed any more, so keep it just for reference.
The ‘v3.2.5-qmi’ branch in the Lanedo stable kernel tree contains a set of patches on top of the 3.2.5. Linux kernel release. These patches add support for QMI ports (updated ‘cdc-wdm’ and new ‘qmi_wwan’ driver) in the 3.2 stable series:
OpenWRT with QMI support
The same set of patches was then added to the ‘qmi-support’ branch of the Lanedo openwrt tree, enabling OpenWRT builds with QMI support:
When you compile this OpenWRT build, make sure you configure the kernel with the QMI-specific requirements enabled:
libqmi-glib and qmi4g
‘libqmi-glib’ and ‘qmi4g’ are two new packages added to the ‘qmi-support’ branch of the Lanedo openwrt-packages tree:
This repository can be added to your OpenWRT build by creating a new ‘
feeds.conf‘ with the following contents:
src-git packages git://gitorious.org/lanedo/openwrt-packages.git;qmi-support
The new packages, in detail:
- libqmi-glib: This package provides a preliminary version of
libqmi-glib, as released unofficially by me. This package will provide the
qmiclicommand line utility and the
- qmi4g: This package registers a new ‘
qmi4g‘ network protocol, which takes care of launching the network start/stop requests through QMI.
If you’re using the precompiled OpenWRT images I gave above, you can just install these packages using ‘opkg’ once you’ve added the ‘latest’ Lanedo repository.
qmi4g package is installed, you are then allowed to include the
following configuration under /etc/config/network:
config 'interface' 'broadband'
option 'ifname' 'wwan0'
option 'proto' 'dhcp'
option 'auto' '0'
config 'interface' 'wdm0'
option 'proto' 'qmi4g'
option 'wdmif' '/dev/cdc-wdm0'
option 'wwanif' 'broadband'
The configuration is split into 2 interfaces:
- First, the configuration for the ‘
wwan0‘ interface. This interface needs to be set with ‘
auto‘ equal to ‘
0‘, so that it is never brought up automatically; and with ‘
dhcp‘ as the protocol to be used. You should never ifup/ifdown this interface manually.
- Second, a virtual interface using the new ‘
qmi4g‘ protocol, which needs 2 options set: ‘
wdmif‘ with the cdc-wdm port to use for the QMI protocol, and ‘
wwanif‘ with the uci-interface-name of the wwan iface to use.
Start/Stop the network
Once the qmi4g setup is added in /etc/config/network, you can now then just:
$> ifup wdm0
That command will internally first launch the network start QMI command, and if succeeds it will itself ifup wwan0. The wwan interface can be used as any other eth-based interface now, it can be added as part of multiwan or in a vlan or in a bonding, or anything.
Once the connection is no longer wanted, you can just:
$> ifdown wdm0
That command will stop the network with QMI and also ifdown wwan0.
Once the network configuration is in place, the connection can also be started via web. Just log in to LUCI, go to Network interfaces and you’ll see both the wwan interface (“broadband“) and the virtual “wdm0“. Starting/Stopping the “wdm0” interface via LUCI should work. As said before, you shouldn’t touch the wwan interface directly.