WiFi Management on Maemo

Connectivity System Overview

Maemo Connectivity Guide gives an overview as well as some details about the connectivity subsystem and we advice the reader to take a look at it. While maemo's connectivity system also includes support for connecting through bluetooth, but we don't discuss it here. The figure below shows the components relevant to WiFi management and packet sending/receiving.

WiFi Management

The intended configuration is that applications manage Internet connections through the libConIC library. The library provides high level functions such as connection, disconnection, status change notifications, connection statistics, etc. Internally, libConIC is just a wrapper for calls to the Internet Connectivity Daemon (ICd) through D-BUS. Unfortunately, ICd is closed source and we were able to find neither its dbus api documentation nor header files. ICd manages Internet connectivity at a high level by talking to WLAN Connectivity Daemon (wlancond) and bluetooth (though the BlueZ). Thus, ICd can establish connectivity either through WiFi or though bluetooth (ppp connection over bluetooth DUN profile). ICd also talks to Internet Connectivity UI daemon (ICd_UI) for user input when needed.

wlancond is open source and can be obtained by

 $ apt-get source osso-wlan

. We could not find any documentation for this daemon and could not compile it as well. It requires a couple of files that are supposedly included in the osso-wlan-dev package, which is not available from anywhere. There is a bug report (filed last august and still open) that asks for the files. The daemon manages WiFi connectivity by talking to the WiFi driver for Conexant cx3110x chip in the kernel.

The WiFi driver is also closed source with an open source wrapper which can be obtained here. The wrapper contain a dummy file umac.ko which is there so that the wrapper compiles. After compilation, this file should be replaced with the one in tablet ( details )

Overall, the connectivity management system is either officially closed, open but not available for unknown reasons, or is not particularly well designed (to be discussed later). The only currently stable and usable, but very limited interface is through LibConIC.

Packet Sending and Receiving

The network stack is provided by the Linux Kernel. This implies that packets can be sent and received through regular BSD-style socket interface. We put together a collection of 4 simple source files (unpack them with $ tar -xzvf sockets.tgz) that contain echo servers and clients for both tcp and udp. You can build them with make both on the regular host machine and inside your scratch box. If you build the files with CHINOOK_ARM as the target, you can copy them to the phone and try sending and receiving between the phone and you machine, for example.

Even though, bare socket's interface can be used to send and receive packets, if your application wants to use LibConIC it should use non-blocking sockets. Further, if your application has a GUI it is probably using hildon and glib. If so, you can use either glib's IOChannels (come with glib, but is not designed particularly for sockets), gnet (not included with glib, but integrates with glib well and is specific for sockets and network programming). Gnet has a pretty complete API and a good amount of example code in included in the distribution. If your app has little network interaction or you don't want to add a dependency on an extra library, you can use glib's IOChannels. We put together an example application that uses GIOChannels, which is described below.

Writing Code

LibConic overview

LibConic has one main structure, ConIcConnection, which captures the connection related state. You should have a single instance of this structure in your program and it is needed (almost) any time you make a libconic call. You can look at the fields of the structure in conic/conicconnection.c in the libconic source to get a sense of what is in there. However, these fields are not exposed to application writers, who is supposed to use accessors and setters provided in header files. Once the ConIcConnection object is created with con_ic_connection_new(), it can be used in any call.

The other important aspect of libConic architecture are the glib signals. There are two signals, “connection-event” and “statistics”, that are emitted by instances of ConIcConnection. You can register callbacks for these signals with

g_signal_connect(G_OBJECT(connection), "connection-event", G_CALLBACK(my_connection_handler), NULL);

However, unlike the usual g_signal architecture where signals are emitted in response to each relevant event, in libconic signals are not emitted by default at all. Below is the list of scenarios where signals are emitted:

  1. You can set the connection signals to be emitted on each connection event with
    g_object_set(G_OBJECT(connection), "automatic-connection-events", TRUE, NULL);
  2. When you request a connection with con_ic_connection_connect(connection, CON_IC_CONNECT_FLAG_NONE), connection object will emit two signals if the connection is successful (one upon connection, and one upon subsequent disconnection), and one signal if the connection request is not successful (the signal with status CON_IC_STATUS_DISCONNECTED)
  3. You cannot call con_ic_connection_disconnect(connection) if con_ic_connection_connect was not called before (your program will crash). Thus it is not clear whether it results in any signals, but if the con_ic_connection_connect was called prior to con_ic_connection_disconnect, the latter does not result in any new signals.
  4. Statistics signals are emitted one in response to each request for statistics with each con_ic_connection_statistics.

Another important detail that is not documented is that calling con_ic_connection_disconnect does not disconnect the tablet. This call only lets the ICd know that the app does not need connectivity any more. ICd then presumably keeps track of which apps still require connectivity and possibly switch of the radio when no application asks for connectivity (though we were not able to cause this to happen).

LibConic Problems

In the first paragraph of this section, we said that developers are supposed to access connection information through accessors. Surprisingly enough, there are no accessors. This is particularly strange because many functions take in the id of the access point as an argument, while there is no way get this id given just the connection object. One particular place where this issue comes up is when we want to call con_ic_connection_disconnect. Before calling it we have to make sure that we are connected (otherwise the program crashes), but there is no way to query the current connection status.

The way around this problems that we found is to always listen for connection events and keep a pseudo copy of the data in the ConIcConnection object ourselves, updating it in the signal handler.

LibConic examples

We did not find code examples and explanations of LibConic in the Connectivity Guide particularly clear. Instead, we suggest that you get the source code for the libconic library by executing

 $ apt-get source libconic

and study the test files in the “tests” directory (it is interesting to note that the latest available source has version 0.13 while the libConIC in your phone is probably 0.14. We did not find the change list between these two version, but it seems like they are minor as we did not encounter any problems). There are 9 test files. Each of them is a tiny standalone command line application that exercises a single management API function.

We had trouble compiling the whole library together with the tests in the regular way. Instead, you can compile each individual test file with this command by substituting test-xyz with the test you want to compile

 $ gcc -Wall -g test-xyz.c `pkg-config --cflags gtk+-2.0 hildon-1 conic` \ 
           -o test-xyz `pkg-config --libs gtk+-2.0 hildon-1 conic`
LibConic Prerequisites

LibConic has a number of requirements from the applications that use it. They are describe pretty well in the Maemo Connectivity Guide and you can look in the source code of any tests mentioned above to see a complete required environment initialization. However, if your application has a GUI and uses hildon/gtk you are probably calling gtk_init(). If so, you don't need to call g_type_init() because it is called by the gtk_init().

Demo Application

We put together a demo hildon GUI application that exercises most of the available WiFi management features and includes a simple TCP server written with glib's IOChannels. The tar file can be unpacked with “$ tar -xzvf hildon_net.tgz” and built with “$ make”.

Miscellaneous Related Stuff

  1. In case anybody is interested in hacking or debugging at the d-bus level, the tool dbus-monitor can be used to capture d-bus messages. Refer to this or this links.
  2. Most services including WiFi related ones can be started/stopped as in regular Linux through scripts in /etc/init.d. For example, /etc/init.d/wlancond stop will stop wlancond.
  3. LibConic API can be found here. This page has all the globally visible libconic names.
 
shortproject/wifi.txt · Last modified: 2008/03/18 12:27 by igor
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki