Maemo Connectivity Guide

Overview

This guide has been reviewed for maemo 4.0. This section briefly presents the clients and APIs of the maemo connectivity subsystem. Details on interfaces of connectivity are presented in the subsequent sections.

The maemo connectivity subsystem is implemented by using known Linux conventions. It resides in the user mode area of Linux, and relies on the Linux kernel through standard C libraries. Wireless LAN is the main channel to the Internet, but dial-up connections through cellular networks are also supported. The only medium to the phone is Bluetooth. The Bluetooth software of maemo is based on BlueZ, which is known as the de-facto implementation of Bluetooth for Linux. D-Bus is used for internal application level message exchange.

Even though the connectivity device drivers are closely related to this subsystem, they are considered to be outside of the scope.

Components of the maemo connectivity architecture:

Maemo connectivity UI - User Interface parts of the connectivity. This includes Connection manager, Control Panel applets and several different dialogs.

Maemo connectivity daemon (ICd) - LibConIC API works together with ICd, handling all Internet Access Points (IAPs). IC daemon handles both WLAN and Bluetooth connections.

OBEX wrapper - Interface to OBEX services. The primary target user of this library is the OBEX gnome-vfs module.

OpenOBEX - Open source implementation of the Object Exchange (OBEX) protocol. More information on OpenOBEX can be found from http://triq.net/obex/

BlueZ Bluetooth stack - The de-facto implementation of Bluetooth for Linux. More information on BlueZ can be found from http://www.bluez.org

BlueZ D-Bus API - BlueZ accepts commands via D-Bus.

WLAN connectivity daemon - The daemon controlling WLAN connections.

WLAN device driver - Device driver for Wireless LAN (IEEE 802.11g). Kernel driver is composed of two parts: a binary part (closed source) and an open source wrapper, binding the binary to the current Linux kernel.

Internet Access Points (IAP)

The central concept regarding Internet connections from maemo is the Internet Access Point (IAP). It represents a logical Internet (IP) connection, which will be defined by the user according to their needs. An IAP has a unique name. It defines the radio bearer (e.g. WLAN, CSD, GPRS) to be applied, and usually the data transfer speed, username, password, proxy server, and the corresponding access point in the Internet or the telephone number of the service provider's modem, among other characteristics.

Connectivity Subsystem

This section describes the system decomposition of the Connectivity subsystem. Maemo applications can open Internet connections by using the LibConIC API. The Internet Access subsystem will take care of the connection to the phone, if necessary, by using the services of the Phone Access subsystem. If an application needs to gain access to the phone's files, then the File selector will consult the Phone Access subsystem.

During the flight mode, the WLAN and Bluetooth radios must not be active. The Device System Management Entity (DSME) of maemo provides information about the transitions to and from the flight mode.

NameConnection Manager
PurposeProvides the UI for managing phone and Internet connections. Available as a Control Panel applet and from Status Bar.
Responsibilities and additional requirements
  • Displaying active connections with statistics
  • Updating status indicators
  • Providing dialogs for changing and disconnecting connections
Concurrent usage(Not relevant)

NamePhone Access
PurposeProvides connections to phones with different Bluetooth profiles
Responsibilities and additional requirements
  • Searching for phones and inquiring their services
  • Keeping phone register
  • Providing status of the phone connections for Connection Manager
  • Binding RFCOMM devices to DUN and FTP services on the phone
  • Providing easy access to OpenOBEX
Concurrent usageNumber of clients not limited by maemo. However, some phones may not support more than one Bluetooth profile at a time.

NameInternet Access
PurposeProvides Internet connections over WLAN and cellular systems.
Responsibilities and additional requirements
  • Providing means for configuration and management of IAP settings
  • Providing API for Internet connections both with WLAN and with dial-up/PPP
  • Providing status of Internet connections for Connection Manager
Concurrent usageNumber of clients not limited, but only one connection to the Internet can exist at any given time


Phone and Internet connections are quite different by nature and behavior. The next sections will introduce these in more detail.

Phone Access

Phone Access is the subsystem handling connections to a mobile phone. It has a search utility for finding potential phones and inquiring the services they can offer. This is based on standard Bluetooth service discovery mechanism. Phone Access also keeps a record of phones having been connected to the device in GConf, and provides a list of them for the user to choose from. Phone Access relies on the Linux Bluetooth implementation called BlueZ. BlueZ offers the Berkeley socket interface to the HCI and to the L2CAP protocol for the user space applications.

In principle, any mobile phone supporting Bluetooth Service Discovery Protocol (SDP), Dial-up Networking profile (DUN) and File Transfer Profile (FTP) can be connected to maemo. However, there is variation especially in the level of file transfer services and OBEX in different mobile phones. Some products limit the access to the Inbox (Object Push), whereas more sophisticated ones make the Gallery and the memory card available. The recent products support the OBEX Capability request, which can be used to get more specific information about the file system on the phone.

Maemo connects to a phone on an on-demand basis, i.e. when an application requires a connection. As an example, when the Internet browser is about to open a URL, it will request the Phone Access to establish a connection to the phone. This makes Phone Access to bind an RFCOMM device to the requested service (in this case DUN) on the phone. In a similar fashion, the File Selector can set up a file transfer connection to the phone using another RFCOMM device. After binding to a service, the application in question can open the local RFCOMM device. Normal file selector access is performed with GnomeVFS layer to get transparent access to phone in the same way as internal flash and MMC are accessed.

The Bluetooth SIM Access (SAP) profile is also needed in maemo to perform WLAN authentication using the EAP-SIM authentication method. In this case, the EAP component will ask the BT sap component to get session keys from a GSM/UMTS phone.

NamePhone selection UI
PurposeUser interface for managing phone operations. Supports Connection Manager.
Responsibilities and additional requirements
  • Keeping a list of phones
  • Storing the Bluetooth device addresses of phones to GConf
  • Invoking device search and capability query
Concurrent usageN/A

NameGeneral Bluetooth UI
PurposeUser interface for managing all paired BT devices
Responsibilities and additional requirements
  • Keeping a list of all paired devices (not only phones)
Concurrent usageN/A

NameBT search
PurposeSearches for available Bluetooth devices
Responsibilities and additional requirements
  • Bluetooth inquiry
  • Checking on flight mode state
Concurrent usageN/A

NameBT service discovery
PurposeChecks if a found Bluetooth device is sufficient
Responsibilities and additional requirements
  • Bluetooth service discovery (SDP)
Concurrent usageNot limited (but used by Phone selection UI and Phone connection daemon only)

NameGW OBEX library
PurposeProvides access to OpenOBEX library for the File selector (Gnome VFS) on a higher abstraction level than OpenOBEX itself supports
Responsibilities and additional requirements
  • Handling OBEX requests
Concurrent usageNot limited

NameBT SAP
PurposeObtains session keys for EAP-SIM authentication from the phone
Responsibilities and additional requirements
  • SIM/PIN entry
  • Connecting to the phone with SIM Access Profile
  • Delivering the session keys to EAP
Concurrent usageN/A

Maemo Bluetooth also supports HID (keyboard) and OPP (printer) profiles.

Internet Access

The Internet Access subsystem manages connections to the Internet over both WLAN and cellular dial-up. It is also responsible for the configuration and management of Internet Access Points. The Internet Access provides applications with TCP/IP connections. They can be established with:

  • WLAN connection to a wireless access point.
  • Bluetooth connection through phone using Point-to-Point Protocol (PPP) and a cellular modem (in the phone).

In the latter case, AT commands are applied to establish a PPP link to the cellular modem and the connection to the Internet.

NameIC daemon
PurposeIC daemon establishes Internet connections over WLAN and Bluetooth DUN.
Responsibilities and additional requirements
  • Controlling that only one Internet connection (one active IAP) can exist at any given time
  • Using Phone Access for getting a character device for a dial-up connection and WLAN connection daemon for getting a network device and getting the connection authenticated
  • Starting IP level services like PPP and DHCP
  • Providing statistics about the usage of IAPs to any application
Concurrent usageHas only one client and limits the connections to one at a time

NameInternet Connectivity GUI
PurposeThis package has the GUI applications for configuring Internet Access Points and WLAN settings. N.B. The Connection Manager is a separate application.
Responsibilities and additional requirements
  • Providing the UI for configuring an IAP
  • Providing the UI for WLAN settings
  • Scanning for available WLAN networks (on request)
  • Saving IAP and WLAN settings (excluding EAP settings) to GConf
  • Opening up dialogs and displaying notifications
Concurrent usageN/A

NameWLAN connection daemon
PurposeManages WLAN network connections
Responsibilities and additional requirements
  • Starting WLAN driver with the settings provided; stopping WLAN
  • Requesting authentication when necessary
  • Relaying WLAN IAP settings from IC daemon to WLAN drivers and authentication requests to EAP
  • Relaying WLAN events from WLAN drivers
  • Providing WLAN status information
Concurrent usageNot limited

NameEAP UI
PurposeUser interface for EAP authentication
Responsibilities and additional requirements
  • Invoking a dialog for an authentication password
  • Showing authentication status
Concurrent usageN/A

NameEAP
PurposeProvides WLAN security excluding basic WEP settings, which are in Wireless Extensions
Responsibilities and additional requirements
  • Taking care of the authentication process for the active IAP
  • Delivering progress events to IC daemon
  • As a special case, controlling the EAP-SIM authentication using the SIM Access Profile
  • Providing authentication status
Concurrent usageN/A

Internet Connectivity Daemon

This section describes how the Internet Connectivity daemon works internally. The following subsections explain the behavior and the decomposition of this component in detail, also covering the interfaces that this component realizes.

Decomposition

When the ICd receives a request to activate or deactivate an IAP, ICd will activate the IAP or show an UI requesting the user to choose one, if no IAP has been selected as the default. Depending on the type of the IAP, ICd will activate or deactivate either a Bluetooth DUN or a WLAN interface.

ICd tracks the applications requesting IAPs by recording their D-Bus base service names. This allows ICd to detect situations where processes using an IAP have aborted or crashed. ICd also implements an idle timeout mechanism to shut down the active IAP, if no packets have been sent in a configurable amount of time.

Maemo version 3.0 introduced the automatic connection creation feature in the Internet Connectivity Daemon. In other words, the device will try to connect automatically to the saved IAPs, and keep connected as long as possible, unless the idle timeout is set. With this feature, applications like e-mail and RSS reader will always be up to date. The device will also be always ready for online usage, for example, incoming VoIP calls or IM chat. In former versions, the Internet connection was automatically closed when there were no more applications using it, or when the connection was idle for a given period of time defined by the configuration parameter idle timeout.

When not connected, the device scans for saved IAPs and tries to connect automatically, taking into account the value defined by the configuration parameter for search interval, which can be 5, 10, 30 or 60 minutes. All other values will be automatically mapped to "Never". This setup switches off the automatic connection feature. In this case, the device will behave just like the former versions: Connections will be created only when required by applications.

ICd is responsible for connection creation only, as it is the responsibility of each application to keep its data updated, and then providing the always-online feature.

While writing an application making use of the ICd system, the following points should be kept in mind:

  • The application must always use the existing available connection.
  • As it was done in former versions, if device is not connected but a connection is required by user interaction, the application must require connection creation using LibConIC API.
  • The user should be kept aware of updates, making visible when the data was last updated.
  • The application must register via LibConIC and listen to signals emitted by ICd (Connection Created, Lost and Changed), and react as follows:
    • Connection Created: Use the connection and update all data.
    • Connection Lost: Go to an idle state silently and wait until a new connection is created.
    • Connection Changed: Use the new connection.
  • Automatic data updates must run in background and silently:
    • Alarming the user with unnecessary banners or dialogs should be avoided.
    • Usernames and passwords should be saved, so that automatic updates can be performed without prompts.
    • In this case, no failures are allowed to show error notification dialogs.
  • The connectivity infrastructure takes care of error situations in a centralized way.

Automatic connection creation feature can also be switched off using flight mode (offline mode). While in this mode, the configuration parameter for allowing WLAN in flight mode is checked. Depending on the state of this configuration parameter, WLAN IAPs are either enabled or disabled in the flight mode. Also Bluetooth connections are normally disabled in the flight mode.

Bluetooth Dial-up Networking

ICd uses PPP to establish IP connectivity over Bluetooth DUN interfaces. If there already is a different IAP active using Bluetooth DUN, the old IAP is first deactivated. The IAP is activated according the following action sequence:

  • The character device used by the Bluetooth DUN device is acquired from btcond. If the device is not available due to gateway not being present, exhaustion of simultaneous Bluetooth connections, or similar, ICd shows an error message to the user and aborts with a D-BUS error message.
  • ICd starts PPP using the exec family of system calls. It directs PPP to use the acquired Bluetooth DUN device with the dial-up configuration parameters specified for the configured DUN IAP type. If PPP cannot get the connection established, ICd will show an error message to the user, and abort with a D-BUS error message. When the PPP connection is established, PPP-specific scripts will be run. These scripts will set dynamic IP connection related configuration entries, and send a state change D-BUS message to all the interested applications to indicate that the IAP has been established.

If the previously active IAP was not using Bluetooth DUN, it will be closed down after establishing the PPP connection.

A Bluetooth DUN is closed down by sending the PPP daemon a SIGINT or SIGTERM signal. This will terminate the PPP daemon, and remove all routing entries associated with the PPP dial-up interface. The PPP shutdown scripts will remove the dynamic IP connection related configuration entries, and send a state change D-BUS message announcing deactivation of the IAP. This is described below.

WLAN

When connecting to a WLAN, ICd needs to associate with the network, and enable EAP authentication and the DHCP client as needed. Independently of whether there is an IAP active using WLAN, the requested WLAN network will first be scanned to ensure that it is available. The current IAP will be deactivated, if the requested network is found and the current IAP is using WLAN. WLAN is activated according to the following procedure:

  • If the network requires EAP authentication, the EAP authentication procedure is started. While performing the EAP authentication, the EAP software may show GUI dialogs relating to the EAP authentication procedure. When the EAP authentication has been completed, the EAP software will set security keys for the WLAN network, resulting in state change messages from wlancond. ICd will receive these messages but ignore them, and wait for the reply from EAP authentication instead. If the EAP authentication fails, ICd aborts with a D-Bus error message.
  • After the EAP process has been started, ICd instructs wlancond to associate with the WLAN network. Any static security settings relating to pre-shared security keys are also supplied at this point. If a connection to the WLAN network cannot be established, ICd aborts with an error.
  • As the DHCP client is a stand-alone program, it is started by using exec when the WLAN IAP requires dynamic IP address acquisition. When the DHCP client has obtained an IP address, it configures IP-related parameters, and sends a D-Bus signal to ICd. If the IP address lease cannot be obtained, ICd will timeout, stop the DHCP client and abort with a D-Bus error message.

LibConIC Library

Internet Connectivity API (in shorter form: Libconic) is an API for applications to manage internet connections on Maemo devices. It was introduced in the first IT OS 2007 release deprecating the old OSSO IC API (osso-ic-lib). OSSO IC API was conclusively removed in IT OS 2008 release. The interface documentation to libconic can be found at Internet Connectivity API

Unlike osso-ic-lib, Libconic is high level and stable object-oriented API. It can be used to

  • Request internet connection
  • Listen for internet connection status events
  • Receive statistics of internet connection
  • Get proxy settings for the current connection
  • Get list of user saved connections (IAPs)

Application requirements

Applications have few requirements prior using the Libconic API. They are:

  1. use non-blocking sockets
  2. system D-BUS running
  3. g_type_init() has to be called
  4. no threading support in the Libconic API

If your application is a standard Hildon application, almost all of these requirements are already fulfilled. LibOSSO context initialization connects your application to both session and system D-BUS buses, g_type_init() is called as a part of gtk_init() and there is probably no extra threads used.

Non-blocking sockets

Blocking sockets cannot be used, because that would also block receiving of the Connectivity events. Use non-blocking sockets to receive the events properly. For example, GLib IO Channels with the G_IO_FLAG_NONBLOCK flag provide non-blocking way to use sockets.

With threads blocking sockets can be used, although Libconic API itself is not thread safe.

System D-BUS

Libconic API uses internally system D-BUS for delivering messages to the Connectivity components. Application needs to have normal D-BUS dispatch, watch and timeout monitoring running before the Libconic API can be used. If the GLib mainloop is used, this can be accomplished with dbus_connection_setup_with_g_main().

Please note that setting up LibOSSO context connects your application to required D-BUS.

GType

Libconic API is GObject-based. This means that to get API working, GLib's GType needs to be initialised properly. Use g_type_init() to do that.

No multiple threads

Libconic API is not thread-safe. If the applications have threads, use Libconic API only from the same context where GMainloop is running.

Libconic usage

Requesting for a connection

Libconic is asynchronous connection API, which heavily relies on GObject signals. Basically this means that GMainloop must be iterated in order to successful execution of connection requests. After your application has been correctly setup (please see previous section for some requirements), you can request for a connection with ConIcConnection object:

    gboolean success = FALSE;

    /* Create connection object */
    ConIcConnection *connection = con_ic_connection_new();

    /* Connect signal to receive connection events */
    g_signal_connect(G_OBJECT(connection), "connection-event", G_CALLBACK(my_connection_handler), NULL);

    /* Request connection and check for the result */
    success = con_ic_connection_connect(connection, CON_IC_CONNECT_FLAG_NONE);
    if (!success) g_warning("Request for connection failed");

At this point, your application does not yet have an internet connection. Successful return from con_ic_connection_connect() means only that request was successfully dispatched to the Internet Connectivity daemon. When the daemon has a connection ready, your application will receive an event (as an GObject signal) indicating that the device is connected. If the connection attempt fails, your application will receive a disconnected event with an error describing the reason for the failure.

Your connection handler (my_connection_handler() function registered in the previous snippet), could look like this:

static void my_connection_handler(ConIcConnection *connection,
                                  ConIcConnectionEvent *event,
                                  gpointer user_data)
{
    ConIcConnectionStatus status = con_ic_connection_event_get_status(event);
    ConIcConnectionError error;

    const gchar *iap_id = con_ic_event_get_iap_id(CON_IC_EVENT(event));
    const gchar *bearer = con_ic_event_get_bearer_type(CON_IC_EVENT(event));
    
    switch(status) {

        case CON_IC_STATUS_CONNECTED:
            g_debug("Hey, we are connected to IAP %s with bearer %s!", iap_id, bearer);
            break;

        case CON_IC_STATUS_DISCONNECTING:
            g_debug("We are disconnecting...");
            break;

        case CON_IC_STATUS_DISCONNECTED:
            g_debug("And we are disconnected. Let's see what went wrong...");
            error = con_ic_connection_event_get_error(event);

            switch(error) {

                case CON_IC_CONNECTION_ERROR_NONE:
                    g_debug("Libconic thinks there was nothing wrong.");
                    break;

                case CON_IC_CONNECTION_ERROR_INVALID_IAP:
                    g_debug("Invalid (non-existing?) IAP was requested.");
                    break;

                case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
                    g_debug("Connection just failed.");
                    break;

                case CON_IC_CONNECTION_ERROR_USER_CANCELED:
                    g_debug("User canceled the connection attempt");
                    break;
            }
            break;

        default:
            g_debug("Unknown connection status received");
    }
}

Listening for connection events

Sometimes your application does not want to actively start connections, but it is still interested to know, when the device is online. It is possible to achieve this with Libconic "automatic events" feature, which is enabled with "automatic-connection-events" GObject property:

    /* Create connection object */
    ConIcConnection *connection = con_ic_connection_new();

    /* Connect signal to receive connection events */
    g_signal_connect(G_OBJECT(connection), "connection-event", G_CALLBACK(my_connection_handler), NULL);

    /* Set automatic events */
    g_object_set(G_OBJECT(Connection), "automatic-connection-events", TRUE, NULL);

When automatic events are turned on, the application will receive connected and disconnected events for all internet connection changes. In addition to this, the application will receive an event for the initial connection status. If the device is disconnected, ConIcConnectionEvent with status CON_IC_STATUS_DISCONNECTED will be emitted. This event will have NULL IAP ID and bearer as there is no IAP getting disconnected, but event just indicates that the device is offline.

Please note that you have to again iterate the main loop in order to receive the event. If you insist having the connection status information synchronously, you can always iterate the main loop yourself:

static void connection_info(ConIcConnection *connection,
                            ConIcConnectionEvent *event,
                            gpointer user_data)
{
    ConIcConnectionStatus status = con_ic_connection_event_get_status(event);
    ConIcConnectionStatus *status_ptr = (ConIcConnectionStatus*)user_data;
    *status_ptr = status;
}

...

    /* Create connection object and set on automatic events (see previous snippet) ... */
    static ConIcConnectionStatus status = 0xFFFF;
    ConIcConnection *connection = con_ic_connection_new();
    g_signal_connect(G_OBJECT(connection), "connection-event", G_CALLBACK(connection_info), &status);
    g_object_set(G_OBJECT(Connection), "automatic-connection-events", TRUE, NULL);

    /* Iterate main loop for the first connection event */
    while (status == 0xFFFF) g_main_context_iteration(NULL, TRUE);
    
    if (status == CON_IC_STATUS_CONNECTED) 
        g_debug("We are connected!");
    else
        g_debug("We are not connected!");

Receiving statistics of the connection

Receiving statistics of the current internet connection is achieved with con_ic_connection_statistics() function and corresponding event handler. If you want, you can get statistics for a specified IAP or just statistics for the current default connection. Please note that currently Internet Connectivity daemon provides only one internet connection at the time, so leaving IAP ID NULL is the best option.

static void connection_statistics(ConIcConnection *connection,
                                  ConIcStatisticsEvent *event,
                                  gpointer user_data)
{
    g_debug("Here are all kind of nice statistics about the connection:");
    g_debug("Time active: %u, signal strength: %u, received packets: %llu, "
            "sent packets: %llu, received bytes: %llu, sent bytes: %llu",
            con_ic_statistics_event_get_time_active(event),
            con_ic_statistics_event_get_signal_strength(event),
            con_ic_statistics_event_get_rx_packets(event),
            con_ic_statistics_event_get_tx_packets(event),
            con_ic_statistics_event_get_rx_bytes(event),
            con_ic_statistics_event_get_tx_bytes(event));
}

...

    /* ConIcConnection object named "connection" has already been created */
    g_signal_connect(G_OBJECT(connection), "statistics", G_CALLBACK(connection_statistics), NULL);
    if (!con_ic_connection_statistics(connection ,NULL)) 
        g_warning("Requesting connection statistics failed!");

Getting proxy settings

With Libconic, you can get internet connection proxy settings for various protocols. First, you should query, what kind of proxy mode is in use. This is achieved with con_ic_connection_get_proxy_mode() function. After getting the proxy mode, use the following functions to get the actual proxy settings:

  • If proxy mode is CON_IC_PROXY_MODE_NONE, do not use any proxies.
  • If proxy mode is CON_IC_PROXY_MODE_MANUAL, use the following functions to query proxy settings:
    • con_ic_connection_get_proxy_host() to get the proxy host
    • con_ic_connection_get_proxy_port() to get the proxy port
    • con_ic_connection_get_proxy_ignore_hosts() to get a list of hosts, for which the proxy should not be used.
  • If proxy mode is CON_IC_PROXY_MODE_AUTO, use con_ic_connection_get_proxy_autoconfig_url() to get a proxy auto configuration URL.
    • Use of auto configuration URL is explained in Wikipedia

In this example, "connection-event" handler is modified to print HTTP proxy settings when we get connected:

static void my_connection_handler(ConIcConnection *connection,
                                  ConIcConnectionEvent *event,
                                  gpointer user_data)
{
    ConIcConnectionStatus status = con_ic_connection_event_get_status(event);
    GSList *ignore_hosts;

    if (status == CON_IC_STATUS_CONNECTED) {
        g_debug("We are connected! Let's see what kind of settings we have for HTTP proxy...");

        /* Do things based on specified proxy mode */
        switch (con_ic_connection_get_proxy_mode(connection)) {

            case CON_IC_PROXY_MODE_NONE:
                g_debug("No proxies defined, it is direct connection");
                break;

            case CON_IC_PROXY_MODE_MANUAL:
                g_debug("HTTP proxy %s:%d in use", 
                        con_ic_connection_get_proxy_host(connection, CON_IC_PROXY_PROTOCOL_HTTP),
                        con_ic_connection_get_proxy_port(connection, CON_IC_PROXY_PROTOCOL_HTTP));
                
                g_debug("List of hosts, for which proxy should not be used:");
                ignore_hosts = con_ic_connection_proxy_ignore_hosts(connection);
                for (GSList *iter = ignore_hosts; iter != NULL; iter = g_slist_next(iter)) {
                    g_debug("%s", (gchar *)iter->data);
                    g_free(iter->data);
                }
                g_slist_free(ignore_hosts);
                break;

            case CON_IC_PROXY_MODE_AUTO:
                g_debug("Proxy auto-config URL %s should be used", 
                        con_ic_connection_get_proxy_autoconfig_url(connection));
                break;
        }
    }
}

There exists also proxy functions for each individual protocol (like con_ic_connection_get_proxy_ftp_host()), but these functions are deprecated and should be avoided in newly-written code.

Getting list of user saved connection

You can get all user saved connections (IAPs) with con_ic_connection_get_all_iaps() function. The function returns simply singly linked list of ConIcIap objects:

    /* ConIcConnection object named "connection" has already been created */
    GSList *saved_iaps = con_ic_connection_get_all_iaps(connection);
    
    g_debug("The following connections have been saved by the user:");
    for (GSList *iter = saved_iaps; iter != NULL; iter = g_slist_next(iter)) {
        
        /* Get IAP object and print some information about it */
        ConIcIap *iap = (ConIcIap *)iter->data;
        g_debug("Connection %s called '%s' using bearer %s",
                con_ic_iap_get_id(iap), con_ic_iap_get_name(iap),
                con_ic_iap_get_bearer_type(iap));
        
        /* We unref the IAP object as we are not going to use it anymore */
        g_object_unref(iap);
    }

    g_slist_free(saved_iaps);

Porting application from OSSO IC API to Libconic

  • If your application has not configured GType, GLib or D-BUS, then setup those:
    DBusConnection *system_dbus;
    GMainloop *main_loop;
    
    g_type_init();
    main_loop = g_main_loop_new(NULL, FALSE);
    
    system_dbus = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
    dbus_connection_setup_with_g_main(system_dbus, NULL);
    
  • Include the correct header file:
    #include <osso-ic.h>
    
    ===>
    
    #include <conic.h>
    
  • Setup ConIcConnection object and "connection-event" handler instead of osso_iap_cb_t callback:
    static void my_connection_cb(struct iap_event_t *event, void *arg)
    {
    ...
    }
    
    ...
    
        osso_iap_cb(my_connection_cb);
    
    ===>
    
    static void my_connection_cb(ConIcConnection *connection,
                                 ConIcConnectionEvent *event,
                                 gpointer user_data)
    {
    ...
    }
    
    ...
    
        ConIcConnection *connection = con_ic_connection_new();
        g_signal_connect(G_OBJECT(connection), "connection-event", G_CALLBACK(my_connection_cb), app_data);
    
  • Manage connections through ConIcConnection API instead of osso_iap_connect() and osso_iap_disconnect():
    osso_iap_connect(OSSO_IAP_ANY, OSSO_IAP_REQUESTED_CONNECT, app_data);
    osso_iap_disconnect(iap_name, app_data);
    
    ===>
    
    con_ic_connection_connect(connection, CON_IC_CONNECT_FLAG_NONE);
    con_ic_connection_disconnect(connection);
    
    
  • Request statistics with con_ic_connection_statistics() instead of osso_iap_get_statistics().
  • List all available IAPs with con_ic_connection_get_all_iaps() instead of osso_iap_get_configured_iaps().
  • Configure autoconf to use Libconic instead of OSSO IC API:
    PKG_CHECK_MODULES(OSSOIC, osso-ic)
    AC_SUBST(OSSOIC_CFLAGS)
    AC_SUBST(OSSOIC_LIBS)
    
    ===>
    
    PKG_CHECK_MODULES(CONIC, conic)
    AC_SUBST(CONIC_CFLAGS)
    AC_SUBST(CONIC_LIBS)
    
    
  • In debian/control file "Build-Depends" section, depend on libconic0-dev instead of osso-ic-dev.

Bluetooth Libraries

This section explains how maemo Bluetooth libraries work internally. The following subsections explain the behavior and the decomposition of the Bluetooth library components in detail.

Libgwobex

Libgwobex provides access to libopenobex functionality by providing a helper/wrapper interface to it. Libopenobex is explained in detail in the following section.

The interface to libgwobex can be found at GW OBEX Library Documentation.

Creating Connection

The connection with libgwobex is established using the gw_obex_setup_dev function, setting up the connection.

#define OBEX_FTP_UUID \
	"\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
#define OBEX_FTP_UUID_LEN 16

GwObex* gw_obex_setup_dev (const gchar * device, const gchar * uuid, gint uuid_len, GMainContext * context, gint * error )
				

The following code snippet illustrates how to open a handle using gw_obex_setup_dev.

if (ctx->rfcomm_dev) {
	if (ctx->use_ftp)
		ctx->obex = gw_obex_setup_dev(ctx->rfcomm_dev,
			OBEX_FTP_UUID, OBEX_FTP_UUID_LEN,
			NULL, &err);
	else
		ctx->obex = gw_obex_setup_dev(ctx->rfcomm_dev, NULL,
			0, NULL, &err);

	if (ctx->obex == NULL)
		printf("OBEX setup failed: %s\n", response_to_string(err));
}
				

In this example, ctx->rfcomm_dev points to a string containing the device node name (e.g. /dev/rfcomm0). ctx->use_ftp dictates whether standard folder browsing services should be set up. If use_ftp is untrue, then INBOX is connected to.

Closing Connection

For closing a gwobex connection, it is possible to use the function

void gw_obex_close ( GwObex * ctx )
				    

The following code demonstrates this usage.

if (ctx->obex) {
	gw_obex_close(ctx->obex);
	ctx->obex = NULL;
}
				    

If ctx->obex is not NULL we simply pass it as an argument to gw_obex_close().

Using Connection

The libgwobex library provides general file handling functionality, including reading directory structure, browsing in different folders and getting files.

For reading entries from an opened directory, it is possible to use the function

gboolean gw_obex_read_dir (GwObex * ctx, const gchar * dir, gchar ** buf, gint * buf_size, gint * error )
				    

gw_obex_read_dir reads an entry from the selected folder and returns the result in the buf argument given to the function.

gboolean ret;
....
ret = gw_obex_read_dir(ctx->obex, dir, buf, buf_size, err);
				    

This reads an entry from the directory dir (char *) and returns it in buf (char **).

For changing the current directory, it is possible to use the function:

gboolean gw_obex_chdir (GwObex * ctx, const gchar * dir, gint * error )
				    

which changes the directory of the FTP connection. Below is a code example using this function.

/* Ignore parent dir pointers */
if (g_str_equal(name, ".."))
	return TRUE;

if (!gw_obex_chdir(ctx->obex, name, err)) {
	printf("Could not chdir to %s\n", name);
	return FALSE;
}
				    

To retrieve files over the OBEX connection, the gw_obex_get_file function can be used.

gboolean gw_obex_get_file (GwObex * ctx, const gchar * local, const gchar * remote, gint * error)
				    

gw_obex_get_file uses the ctx context for retrieving the remote file to local file.

gboolean ret;

ret = gw_obex_get_file(ctx->obex, name, name, err);
				    

There are a lot more functions that can be performed by using libgwobex wrapper directly, for full list of functions and their usage, see the API document.

Libopenobex

LibOpenOBEX library implements a generic OBEX Session Protocol. It does not implement the OBEX Application Framework. OBEX is a protocol designed to allow interchanging of data between different kinds of connections (e.g. Bluetooth, IrDA). Specific information about the OBEX protocol can be found at http://www.irda.org, by selecting the Developer->Specifications category. OBEX is similar to HTTP protocol, expect for a few differences:

  • Transports: While HTTP is normally layered above a TCP/IP connection, OBEX is usually transported over IrLAP/IrLMP/Tiny TP (on IrDA) or over Baseband/Link Manager/L2CAP/RFCOMM (on Bluetooth).
  • Binary transmissions: OBEX communicates using binary transmissions, as HTTP is transmitted in a human-readable XML-based format.
  • Session support: HTTP is stateless, while OBEX maintains the connection.

A fairly good overlook of OBEX can be found at http://en.wikipedia.org/wiki/OBEX.

Code examples for libopenobex can be obtained from http://openobex.triq.net/downloads, from the example apps package.

Using BlueZ D-Bus API

The BlueZ system exports a D-Bus API that can be employed instead of OSSO Bluetooth tools. See the following documents:

Connectivity UI

UI components

Connectivity UI contains different dialogs and other components used to control the connectivity. The different UI parts are:

  • Connection manager
  • Connectivity dialogs
  • Status bar applets
  • Control panel applet
  • Bluetooth UIs

The connectivity dialogs are invoked by D-Bus method calls, so for example ICd is using these D-Bus method calls for showing dialogs when they are needed. Next section specifies the D-Bus API of maemo connectivity UI

D-Bus Connectivity UI interface

If some information is needed from the user about the IAP that is about to be connected to, the following can be used.

Service:           com.nokia.icd_ui
Interfaces:        com.nokia.icd_ui
Object paths:      /com/nokia/icd_ui
			    

The Internet Connectivity UIs implements the following D-Bus API used by ICd and EAP.

Method:            show_conn_dlg
Parameters:        none
Return parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown
Description:       Shows the Connect Dialog where the user can choose an IAP.
			    
Method:            show_disconnect_dlg
Parameters:        none

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows the disconnect dialog.
			    
Method:            show_retry_dlg
Parameters:        1. string  Bluetooth address of the device used with SAP
                   2. string  Name of the connection attempt error which
                               selects the retry dialog type.

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows the retry dialog.
			    
Method:            show_change_dlg
Parameters:        1. string  Name of the currently active IAP
                   2. string  Name of the IAP to be activated

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows the Change IAP Dialog
			    
Method:            show_passwd_dlg
Parameters:        1. string  Username supplied by ICd
                   2. string  Password supplied by ICd
                   3. string  Name of the IAP

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows the username/password dialog.
			    
Method:            show_gtc_dlg
Parameters:        1. string  GTC challenge string

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows EAP GTC challenge dialog.
			    
Method:            show_mschap_change_dlg
Parameters:        1. string  Supplied username
                   2. string  Old password that is to be changed
                   3. string  Name of the IAP

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows EAP MSCHAPv2 change password dialog.
			    
Method:            show_private_key_passwd_dlg
Parameters:        1. uint32  The private key ID

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows EAP private key password dialog
			    
Method:            show_server_cert_dlg
Parameters:        1. string  Certificate name
                   2. string  Certificate serial
                   3. boolean  TRUE if certificate is expired, FALSE otherwise
                   4. boolean  TRUE if root CA is unknown or self-signed
                                certificate, FALSE otherwise

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows server certificate error and expiration dialogs.
                   If both boolean arguments are false, the error dialog is
                   shown. If either or both boolean arguments are TRUE, the
                   expiration dialog is shown instead.
			    
Method:            strong_bt_req
Parameters:        1. string  Bluetooth address of the device to pair with
                   2. boolean  TRUE if strong authentication enabled, FALSE
                                if strong authentication is disabled

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Requests strong (16 digit) BT PIN dialog for a BT device
                            
Method:            show_sim_pin_dlg
Parameters:        1. string  Bluetooth address of the device used with SAP
                   2. boolean  TRUE if PIN was incorrect and retry dialog
                                should be displayed before asking PIN. FALSE
                                if this is the first PIN request.

Return Parameters: none
Errors:            com.nokia.icd_ui.error.flight_mode:
                   Flight mode enabled, dialog not shown

Description:       Shows SIM PIN dialog
                            

Example code for the application to show the connect dialog using show_conn_dlg is following. Please note the usage of macro for doing this.

#include <osso-ic-ui-dbus.h>
...
/* in our code somewhere, where we need the Connect Dialog*/
DBusMessage *uimsg;

/* construct the message for Connect Dialog request*/
uimsg =
  dbus_message_new_method_call(ICD_UI_DBUS_SERVICE,
  		           ICD_UI_DBUS_PATH,
		           ICD_UI_DBUS_INTERFACE,
			 /*macro for show_conn_dlg */
                               ICD_UI_SHOW_CONNDLG_REQ);

/* send the message */
reply =
  dbus_connection_send_with_reply_and_block(connection,
				    uimsg,
				   reply_timeout,
				   &error);

if (reply == NULL) {
    DLOG_ERR("Failed to show connect dialog: %s", uierror.message);
    dbus_error_free(&uierror);
}

dbus_message_unref(uimsg);
dbus_message_unref(reply);
...
                            

The signals emitted from com.nokia.icd_ui interface are listed below.

Signal:        disconnect
Parameters:    1. boolean  TRUE if "disconnect" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when disconnect dialog has been closed.
                            
Signal:        retry
Parameters:    1. string  The IAP that is to be retried
               2. boolean  TRUE if "retry" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when retry dialog has been closed.
                            
Signal:        change
Parameters:    1. string  Old IAP to change from
               2. string  New IAP to change to
               3. boolean  Change to the new IAP If TRUE, keep old if FALSE

Description:   Signal emitted from UI when change connection dialog has
                been closed.
                            
Signal:        passwd
Parameters:    1. string  Username supplied or modified by the user
               2. string  Password supplied or modified by the user
               3. string  IAP name
               4. boolean  TRUE if "ok" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when the username/password dialog has
               been closed
                            
Signal:        gtc_response
Parameters:    1. string  Response to the given challenge or empty string
                           if cancelled
               2. boolean  TRUE if "ok" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when the EAP GTC challenge dialog has
               been closed.
                            
Signal:        mschap_change
Parameters:    1. string  Supplied username
               2. string  The new password or empty string if cancelled
               3. string  IAP name
               4. boolean  TRUE if "ok" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when the MSCHAPv2 password has been
               changed
                            
Signal:        private_key_passwd
Parameters:    1. uint32  The id of the private key
               2. string  Password for the private key or empty string if none
               3. boolean  TRUE if "ok" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when the private key password dialog
               has been closed
                            
Signal:        server_cert
Parameters:    1. boolean  TRUE if strong PIN entered, FALSE if strong
                            PIN dialog was cancelled

Description:   Signal emitted from UI when the server certificate error
               dialog has been closed
                            
Signal:        strong_bt
Parameters:    1. boolean  TRUE if strong PIN entered, FALSE if strong
                            PIN dialog was cancelled

Description:   Signal emitted from UI when the strong (16 digit) BT PIN
               has been entered
                            
Signal:        sim_pin
Parameters:    1. string  SIM PIN code or empty string if  cancelled
               2. boolean  TRUE if "ok" pressed, FALSE if "cancel"

Description:   Signal emitted from UI when the SIM PIN has been entered.
                            

Bluetooth DBUS UI dialogs

  Example of use (command line):
  
  dbus-send --system --print-reply \
    --dest='com.nokia.icd_ui' /com/nokia/bt_ui \
    com.nokia.bt_ui.show_send_file_dlg \
    array:string:file:///home/user/MyDocs/.documents/testing.txt
    
  dbus-send --system --print-reply \
    --dest=com.nokia.bt_ui  /com/nokia/bt_ui 
    com.nokia.bt_ui.show_search_dlg \
    string: string: array:string: boolean:true
*/

#ifndef CONBTDIALOGS_DBUS_H
#define CONBTDIALOGS_DBUS_H

#ifdef __cplusplus
extern "C" {
#endif

/** Conbtdialogs service, resides in system dbus */
#define CONBTDIALOGS_DBUS_SERVICE		"com.nokia.bt_ui"
/** Conbtdialogs interface */
#define CONBTDIALOGS_DBUS_INTERFACE		"com.nokia.bt_ui"
/** Conbtdialogs path */
#define CONBTDIALOGS_DBUS_PATH		        "/com/nokia/bt_ui"

/** 
  Show send file dialog
 
  Arguments:
  
  uris: DBUS_TYPE_ARRAY	        Array of strings representing the URIs of the
                                files to send.
  
  Returns:
  
  DBUS_TYPE_BOOLEAN             TRUE, if dialog was shown successfully.
 */
#define CONBTDIALOGS_SEND_FILE_REQ		"show_send_file_dlg"

/** 
  File sending result signal
 
  Arguments:
  
  success: DBUS_TYPE_BOOLEAN	TRUE, if all files were sent successfully or
                                FALSE, if error occurred or sending was 
                                cancelled.
 */
#define CONBTDIALOGS_SEND_FILE_SIG	        "send_file"

/** 
  Show BT device search dialog
 
  Arguments:
  
  major_class: DBUS_TYPE_STRING To set filtering based on major_class or
                                "". Possible major class values are:
                                
                                "miscellaneous", "computer", "phone", 
                                "access point", "audio/video", 
                                "peripheral", "imaging", "wearable",
                                "toy" and "uncategorized".
  
  minor_class: DBUS_TYPE_STRING To set filtering based on minor_class or "".
                                Possible minor class values are:
                        
                                - Minor classes for "computer": 
                                  "uncategorized", "desktop", "server",
                                  "laptop", "handheld", "palm", "wearable"

                                - Minor classes for "phone": "uncategorized",
                                  "cellular", "cordless", "smart phone",
                                  "modem", "isdn"
  
  service_classes: DBUS_TYPE_ARRAY To set filtering based on service classes.
                                   Supported classes include "positioning", 
                                   "networking", "rendering", "capturing",
                                   "object transfer", "audio", "telephony", 
                                   "information". Can be empty list, when no
                                   service class filtering is performed.
  
  bonding: DBUS_TYPE_STRING     Bonding mode for found and selected device:
                                
                                "require" for requiring a bonding from a
                                selected device (i.e. bond device if it has not
                                been bonded before). 
                                
                                "force" to always bond (i.e. device will be
                                bonded even if bonded before).
                                
                                Any other string will allow to search and
                                select device without bonding it.
                                
  Returns:
  
  DBUS_TYPE_BOOLEAN             TRUE, if dialog was shown successfully.
 */
#define CONBTDIALOGS_SEARCH_REQ                 "show_search_dlg"

/** 
  Bluetooth search result signal
 
  Arguments:
  
  address: DBUS_TYPE_STRING     Bluetooth address of the selected device, or ""
                                if search dialog was cancelled.
  
  name: DBUS_TYPE_STRING        Name of the device.
  
  icon: DBUS_TYPE_STRING        Logical name for the icon describing the 
                                device.
  
  major_class: DBUS_TYPE_STRING Major class of the device.
  
  minor_class: DBUS_TYPE_STRING Minor class of the device.
  
  trusted: DBUS_TYPE_BOOLEAN    Defines whether the device is marked as a trusted device.
  
  services: DBUS_TYPE_ARRAY     List of strings describing the service classes
                                and SDP-based services provided by the device.
 */
#define CONBTDIALOGS_SEARCH_SIG                 "search_result"

/**
  Bluetooth UI Library for maemo

  Copyright (C) 2006 Nokia. All rights reserved.
  
  This sample demonstrates the use of conbtdialogs API and especially 
  send_file function. Compile the program with conbtdialogs and dbus:
  
  gcc -Wall `pkg-config --libs --cflags dbus-glib-1 conbtdialogs` -o send_file conbtdialogs_send_file.c
  
  Run with list of URLS:
  
  ./send_file file:///home/user/MyDocs/.sounds/Everyday.mp3
*/

#define DBUS_API_SUBJECT_TO_CHANGE

#include <glib.h>
#include <conbtdialogs-dbus.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>


DBusGConnection *connection = NULL;
GMainLoop *mainloop = NULL;


static gboolean initialize(void)
{
    GError *error = NULL;
    
    g_type_init ();
    
    /* Create main loop */
    mainloop = g_main_loop_new(NULL, TRUE);
    if ( mainloop == NULL ) return FALSE;
    
    /* Create DBUS connection */
    connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
  
    if (connection == NULL )
    {
        g_print ("Error: %s\n", error->message);
        g_clear_error (&error);
        return FALSE;
    }
    
    return TRUE;
}


static gboolean uninitialize(void)
{
    /* Quit main loop and unref it */
    if (mainloop != NULL)
    {
        g_main_loop_quit(mainloop);
        g_main_loop_unref(mainloop);
    }
    
    return TRUE;
}


static DBusHandlerResult file_sent_signal ( DBusConnection *connection,
                                            DBusMessage *message,
                                            void *data )
{
    gboolean success = FALSE;
    
    /* check signal */
    if (!dbus_message_is_signal(message,
                                CONBTDIALOGS_DBUS_INTERFACE,
                                CONBTDIALOGS_SEND_FILE_SIG))
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    
    /* get args */
    if ( !dbus_message_get_args ( message, NULL,
                                  DBUS_TYPE_BOOLEAN, &success,
                                  DBUS_TYPE_INVALID ) )
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    
    /* print if file sending was success or failure */
    g_print ( "File sending was a " );
    
    if (success) g_print("success\n"); else g_print("failure\n");
    dbus_connection_close(connection);
    uninitialize();
    
    return DBUS_HANDLER_RESULT_HANDLED;
}


gint main(gint argc, gchar **argv)
{
    GError *error = NULL;
    gchar **files = NULL;
    gint idx = 0;
    DBusGProxy *proxy;
    DBusConnection *sys_conn;
    gchar *filter_string = NULL;

    if (argc < 2) return 1;
        
    if (initialize() == FALSE) {
        uninitialize();
        return 1;
    }
    
    /* Copy urls to GLib compatible char array */
    files = g_new0(gchar*, argc);
    
    for (idx = 1; idx < argc; idx++)
        files[idx-1] = g_strdup(argv[idx]);
    
    files[argc-1] = NULL;
    
    /* Open connection for btdialogs service */
    proxy = dbus_g_proxy_new_for_name(connection,
                                      CONBTDIALOGS_DBUS_SERVICE,
                                      CONBTDIALOGS_DBUS_PATH,
                                      CONBTDIALOGS_DBUS_INTERFACE);
    
    /* Send send file request to btdialogs service */
    if (!dbus_g_proxy_call(proxy, CONBTDIALOGS_SEND_FILE_REQ, 
                           &error, 
                           G_TYPE_STRV, files, G_TYPE_INVALID,
                           G_TYPE_INVALID))
    {
        g_print("Error: %s\n", error->message);
        g_clear_error(&error);
        g_strfreev (files);
        g_object_unref(G_OBJECT(proxy));
        uninitialize();
        return 1;
    }
    g_strfreev (files);
    files = NULL;
    
    g_object_unref(G_OBJECT(proxy));
    
    /* Now wait for file sent signal, use low level bindings as glib 
       bindings require signal marshaller registered */
    sys_conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
    g_assert(dbus_connection_add_filter(sys_conn,
                                        file_sent_signal,
                                        NULL,
                                        NULL ));
    filter_string =
       g_strdup_printf ("type='signal',interface='%s'", CONBTDIALOGS_DBUS_INTERFACE);
    
    dbus_bus_add_match(sys_conn, filter_string, NULL);
    dbus_connection_unref(sys_conn);
    
    /* Run mainloop */
    g_main_loop_run(mainloop);
    
    return 0;
}

Samba Network Shares

The device has support for connecting Samba network shares. To access Samba network shares with GnomeVFS, a Samba module for the GnomeVFS (libosso-gnomevfs2-samba) needs to be installed.

Here is a simple example on how to read a file via Samba:

#include <libgnomevfs/gnome-vfs.h>
#include <stdio.h>

int main(void)
{
    GnomeVFSHandle *handle = NULL;
    GnomeVFSResult res;
    GnomeVFSFileSize bytes_read;
    gchar buf[1024];

    // URI to open for reading
    gchar *uri = "smb://host/file.txt";

    if (!gnome_vfs_init()) {
        fprintf(stderr, "GnomeVFS initialization failed.\n");
        return 1;
    }

    if (GNOME_VFS_OK != (res = gnome_vfs_open(&handle, uri, GNOME_VFS_OPEN_READ))) {
        fprintf(stderr, "GnomeVFS open failed.\n");
        return 2;
    }

    while (GNOME_VFS_OK == res) {
        res = gnome_vfs_read(handle, buf, sizeof(buf)-1, &bytes_read);
        buf[bytes_read] = 0;

        // Write buffer to stdout
        write(1, buf, bytes_read);

        if(bytes_read == 0)
            break;
    }

    if (GNOME_VFS_OK != gnome_vfs_close(handle))
        fprintf(stderr, "GnomeVFS close failed\n");

    gnome_vfs_shutdown();
    return 0;
}

Example can be compiled including GnomeVFS:

gcc `pkg-config gnome-vfs-2.0 --libs --cflags` vfscat.c -o vfscat

Location

Location framework has one library; liblocation. The liblocation is made up of functions for parsing GPSD's output, for controlling GPSD and for other helper functions.

Using Liblocation

The headers for liblocation are stored in the location subdirectory, and so they should be included as follows.

#include <location/location-gps-device.h>

Listening to GPSD

GPSD is used in maemo to talk to GPS devices and report position data. Liblocation contains an object that listens to GPSD and converts the output into GObject signals. Creating the object is as follows
LocationGPSDevice *device;

device = g_object_new (LOCATION_TYPE_GPS_DEVICE, NULL);

We can then connect to the changed signal to hear about gps fix changes.

g_signal_connect (device, "changed", G_CALLBACK (location_changed), NULL);

And our location changed callback looks like this

static void
location_changed (LocationGPSDevice *device, gpointer userdata)
{
	g_print ("Latitude: %.2f\nLongitude: %.2f\nAltitude: %.2f\n",
		 device->fix->latitude, device->fix->longitude, device->fix->altitude);
}

That is all that is required for a simple GPS client that listens for GPSD. Notice that the LocationGPSDevice object has some public fields. These are as follows:

  • device->online: Whether GPSD is connected to a GPS or not
  • device->status: The GPS status
  • device->fix: The GPS fix information
  • device->satellites_in_view: The number of satellites that the GPS can see
  • device->satellites_in_use: The number of satellites used in fix calculation
  • device->satellites: An array of satellite details

The most important of these is device->fix as this contains the fix location data from GPSD. The fields of the LocationGPSDeviceFix structure are fairly self-explanatory except for the fields field. This field is a bitmask of what other fields in the structure have valid content. To check whether the latitude and longitude fields are valid you would do

if (fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET)

and so on. The bitmask flags are defined in location-gps-device.h

Controlling GPSD

Sometimes a program may need to start or stop GPSD, or find out when GPSD has been started or stopped. This is accomplished using the LocationGPSDControl object. This object can only be created once in a program, so it is obtained with the location_gpsd_control_get_default() function.

LocationGPSDControl *control;

control = location_gpsd_control_get_default ();

There are three signals on this object; error, gpsd_running and gpsd_stopped. error is emitted when there is an error starting GPSD, gpsd-running is emitted whenever GPSD starts up and gpsd-stopped is emitted when GPSD stops. Only one application is able to control GPSD at a time, and this will be the application that initially starts it. The control->can_control field will be TRUE if your application can control it, or FALSE if it cannot.

Other Liblocation functions

Liblocation also comes with a function for getting the distance between two points. This is called the great-circle distance (see Wikipedia for more details on it). The function location_distance_between() takes the latitude and longitude of two locations and returns the distance between them in kilometres.

g_print ("distance between LAX and BNA is %fkm\n", location_distance_between (36.12, -86.67, 33.94, -118.40));

Compiling Programs With LibLocation support

Liblocation comes with a pkgconfig file, so adding support to a program is a case of adding liblocation to your configure scripts PKG_CHECK_MODULES macro, like so:

PKG_CHECK_MODULES(LOCATION)
AC_SUBST(LOCATION_CFLAGS)
AC_SUBST(LOCATION_LIBS)

Then in the Makefile.am you will need to add these variables to the program's CFLAGS and LDADD flags.



Improve this page